diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 5ab826fa867..6ce3ffad460 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -330,15 +330,7 @@
// Simple helper to face what you clicked on, in case it should be needed in more than one place
/mob/proc/face_atom(var/atom/A)
- // Snowflake for space vines.
- var/is_buckled = 0
- if(buckled)
- if(istype(buckled))
- if(!buckled.movable)
- is_buckled = 1
- else
- is_buckled = 0
- if( is_buckled || !A || !x || !y || !A.x || !A.y || (stat && !isobserver(src))) return
+ if(!A || !x || !y || !A.x || !A.y) return
var/dx = A.x - x
var/dy = A.y - y
if(!dx && !dy) return
diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm
index 4f4224b04b2..906069b876f 100644
--- a/code/_onclick/other_mobs.dm
+++ b/code/_onclick/other_mobs.dm
@@ -175,7 +175,7 @@
return
if(melee_damage_upper == 0 && istype(A,/mob/living))
- custom_emote(1,"[friendly] [src]!")
+ custom_emote(1,"[friendly] [A]!")
return
var/damage = rand(melee_damage_lower, melee_damage_upper)
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 00200a24cbf..3532bf7bcde 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -504,11 +504,6 @@
if("python_path")
if(value)
config.python_path = value
- else
- if(world.system_type == UNIX)
- config.python_path = "/usr/bin/env python2"
- else //probably windows, if not this should work anyway
- config.python_path = "python"
if("use_lib_nudge")
config.use_lib_nudge = 1
@@ -741,3 +736,11 @@
runnable_modes[M] = probabilities[M.config_tag]
//world << "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]"
return runnable_modes
+
+/datum/configuration/proc/post_load()
+ //apply a default value to config.python_path, if needed
+ if (!config.python_path)
+ if(world.system_type == UNIX)
+ config.python_path = "/usr/bin/env python2"
+ else //probably windows, if not this should work anyway
+ config.python_path = "python"
diff --git a/code/controllers/lighting_controller.dm b/code/controllers/lighting_controller.dm
index 08c29e1a076..b59d3c73d69 100644
--- a/code/controllers/lighting_controller.dm
+++ b/code/controllers/lighting_controller.dm
@@ -65,7 +65,7 @@ datum/controller/lighting/proc/process()
//Does not loop. Should be run prior to process() being called for the first time.
//Note: if we get additional z-levels at runtime (e.g. if the gateway thin ever gets finished) we can initialize specific
//z-levels with the z_level argument
-datum/controller/lighting/proc/Initialize(var/z_level)
+datum/controller/lighting/proc/initializeLighting(var/z_level)
processing = 0
spawn(-1)
set background = 1
diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm
index 0a7c6c1a239..1e972dd46d2 100644
--- a/code/controllers/master_controller.dm
+++ b/code/controllers/master_controller.dm
@@ -84,7 +84,7 @@ datum/controller/game_controller/proc/setup()
if(ticker)
ticker.pregame()
- lighting_controller.Initialize()
+ lighting_controller.initializeLighting()
datum/controller/game_controller/proc/setup_objects()
diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm
index 33872391016..d5503890a2f 100644
--- a/code/controllers/voting.dm
+++ b/code/controllers/voting.dm
@@ -9,6 +9,7 @@ datum/controller/vote
var/mode = null
var/question = null
var/list/choices = list()
+ var/list/gamemode_names = list()
var/list/voted = list()
var/list/voting = list()
var/list/current_votes = list()
@@ -217,8 +218,10 @@ datum/controller/vote
for (var/T in L)
var/datum/game_mode/M = new T()
if (M.config_tag == F)
+ gamemode_names[M.config_tag] = capitalize(M.name) //It's ugly to put this here but it works
additional_text.Add("
[M.required_players] | ")
break
+ gamemode_names["secret"] = "Secret"
if("crew_transfer")
if(check_rights(R_ADMIN|R_MOD, 0))
question = "End the shift?"
@@ -307,11 +310,16 @@ datum/controller/vote
var/votes = choices[choices[i]]
if(!votes) votes = 0
. += ""
- if(current_votes[C.ckey] == i)
- . += "| [choices[i]] | [votes] | "
+ if(mode == "gamemode")
+ if(current_votes[C.ckey] == i)
+ . += "[gamemode_names[choices[i]]] | [votes] | "
+ else
+ . += "[gamemode_names[choices[i]]] | [votes] | "
else
- . += "[choices[i]] | [votes] | "
-
+ if(current_votes[C.ckey] == i)
+ . += "[choices[i]] | [votes] | "
+ else
+ . += "[choices[i]] | [votes] | "
if (additional_text.len >= i)
. += additional_text[i]
. += "
"
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index 0d817b7c8d8..4ff625defb7 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -16,11 +16,11 @@
New(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
..()
- if(!Init(arglist(args)))
+ if(!initTeleport(arglist(args)))
return 0
return 1
- proc/Init(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout)
+ proc/initTeleport(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout)
if(!setTeleatom(ateleatom))
return 0
if(!setDestination(adestination))
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 271db65fa93..70c418172da 100755
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -380,7 +380,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
containername = "Medical crate"
group = "Medical"
-/datum/supply_packs/medical
+/datum/supply_packs/bloodpack
name = "BloodPack crate"
contains = list(/obj/item/weapon/storage/box/bloodpacks,
/obj/item/weapon/storage/box/bloodpacks,
diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm
index f65ee6be508..73555f38899 100644
--- a/code/datums/wires/robot.dm
+++ b/code/datums/wires/robot.dm
@@ -51,36 +51,17 @@ var/const/BORG_WIRE_CAMERA = 16
/datum/wires/robot/UpdatePulsed(var/index)
-
var/mob/living/silicon/robot/R = holder
switch(index)
if (BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
if(!R.emagged)
- var/new_ai = select_active_ai(R)
+ var/mob/living/silicon/ai/new_ai = select_active_ai(R)
if(new_ai && (new_ai != R.connected_ai))
+ R.connected_ai.connected_robots -= src
R.connected_ai = new_ai
+ new_ai.connected_robots += src
R.notify_ai(1)
- var/numberer = 1 // Send images the Cyborg has taken to the AI's album upon sync.
- for(var/datum/picture/z in R.aiCamera.aipictures)
- if(R.connected_ai.aiCamera.aipictures.len == 0)
- var/datum/picture/p = new/datum/picture()
- p = z
- p.fields["name"] = "Uploaded Image [numberer] (synced from [R.name])"
- R.connected_ai.aiCamera.aipictures += p
- numberer++
- continue
- for(var/datum/picture/t in R.connected_ai.aiCamera.aipictures) //Hopefully to prevent someone spamming images to silicons, by spamming this wire
- if((z.fields["pixel_y"] != t.fields["pixel_y"]) && (z.fields["pixel_x"] != t.fields["pixel_x"])) //~2.26 out of 1000 chance this will stop something it shouldn't
- var/datum/picture/p = new/datum/picture()
- p = z
- p.fields["name"] = "Uploaded Image [numberer] (synced from [R.name])"
- R.connected_ai.aiCamera.aipictures += p
- else
- continue
- numberer++
- if(R.aiCamera.aipictures.len > 0)
- R << "Locally saved images synced with AI. Images were retained in local database in case of loss of connection with the AI."
-
+ R.sync()
if (BORG_WIRE_CAMERA)
if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes)
R.camera.kick_viewers() // Kick anyone watching the Cyborg's camera
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index bb1a1abc757..48408cdf18d 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -57,7 +57,7 @@
a.triggerAlarm("Power", src, cameras, source)
return
-/area/proc/atmosalert(danger_level)
+/area/proc/atmosalert(danger_level, var/set_firelocks=1)
// if(type==/area) //No atmos alarms in space
// return 0 //redudant
@@ -68,7 +68,7 @@
danger_level = max(danger_level, AA.danger_level)
if(danger_level != atmosalm)
- if (danger_level < 1 && atmosalm >= 1)
+ if (set_firelocks && danger_level < 1 && atmosalm >= 1)
//closing the doors on red and opening on green provides a bit of hysteresis that will hopefully prevent fire doors from opening and closing repeatedly due to noise
air_doors_open()
@@ -92,7 +92,8 @@
aiPlayer.triggerAlarm("Atmosphere", src, cameras, src)
for(var/obj/machinery/computer/station_alert/a in machines)
a.triggerAlarm("Atmosphere", src, cameras, src)
- air_doors_close()
+ if (set_firelocks)
+ air_doors_close()
atmosalm = danger_level
for(var/area/RA in related)
diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm
index 0d8b46b318e..a4e617aaf4a 100644
--- a/code/game/gamemodes/calamity/calamity.dm
+++ b/code/game/gamemodes/calamity/calamity.dm
@@ -91,7 +91,7 @@
// Add the cortical borer event
var/list/moderate_event_list = EModerate.available_events
- var/event = new /datum/event_meta(EVENT_LEVEL_MODERATE, "Borer Infestation", /datum/event/borer_infestation, 400, one_shot = 1)
+ var/event = new /datum/event_meta(EVENT_LEVEL_MODERATE, "Borer Infestation", /datum/event/borer_infestation, 400, is_one_shot = 1)
moderate_event_list.Add(event)
if(chosen_atypes)
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index b78baf2816d..a3829207fe5 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -331,11 +331,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
if(istype(M,/mob/dead))
var/mob/dead/D = M
- D.manifest()
- user.visible_message( \
- "\red [user] drags the ghost to our plan of reality!", \
- "\red You drag the ghost to our plan of reality!" \
- )
+ D.manifest(user)
return
if(!istype(M))
return
diff --git a/code/game/gamemodes/events/space_ninja.dm b/code/game/gamemodes/events/space_ninja.dm
index 3dac9f21488..59cca0df8b3 100644
--- a/code/game/gamemodes/events/space_ninja.dm
+++ b/code/game/gamemodes/events/space_ninja.dm
@@ -531,7 +531,6 @@ As such, it's hard-coded for now. No reason for it not to be, really.
else
equip_to_slot_or_del(new /obj/item/clothing/under/color/black(src), slot_w_uniform)
- equip_to_slot_or_del(new /obj/item/clothing/mask/gas/voice/space_ninja(src), slot_wear_mask)
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_belt)
var/obj/item/weapon/rig/light/ninja/ninjasuit = new(src)
@@ -546,16 +545,16 @@ As such, it's hard-coded for now. No reason for it not to be, really.
equip_to_slot_or_del(ninjasuit,slot_back)
- if(istype(wear_suit,/obj/item/weapon/rig))
- var/obj/item/weapon/rig/rig = wear_suit
- if(rig.air_supply)
- internal = rig.air_supply
- if(!internal && s_store)
- internal = s_store
- if(internal)
- internals.icon_state = "internal1"
-
spawn(10)
ninjasuit.toggle_seals(src,1)
+ if(istype(back,/obj/item/weapon/rig))
+ var/obj/item/weapon/rig/rig = back
+ if(rig.air_supply)
+ internal = rig.air_supply
+ if(!internal && s_store)
+ internal = s_store
+ if(internal)
+ internals.icon_state = "internal1"
+
return 1
\ No newline at end of file
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 68bf3935d86..e90b65a333a 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -56,7 +56,7 @@
"Devices and Tools" = list(
new/datum/uplink_item(/obj/item/weapon/card/emag, 3, "Cryptographic Sequencer", "EC"),
new/datum/uplink_item(/obj/item/weapon/storage/toolbox/syndicate, 1, "Fully Loaded Toolbox", "ST"),
- new/datum/uplink_item(/obj/item/weapon/stamp/chameleon, 3, "Morphic Chameleon Stmap", "CS"),
+ new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/clerical, 3, "Morphic Clerical Kit", "CK"),
new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/space, 3, "Space Suit", "SS"),
new/datum/uplink_item(/obj/item/clothing/glasses/thermal/syndi, 3, "Thermal Imaging Glasses", "TM"),
new/datum/uplink_item(/obj/item/device/encryptionkey/binary, 3, "Binary Translator Key", "BT"),
@@ -154,16 +154,14 @@
var/pltext = "Player list:"
for(var/mob/M in player_list)
- if(M.mind)
- pltext += print_player_lite(M.mind)
if(M.client)
clients++
if(ishuman(M))
- if(!M.stat)
+ if(M.stat != DEAD)
surviving_humans++
if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations)
escaped_humans++
- if(!M.stat)
+ if(M.stat != DEAD)
surviving_total++
if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations)
escaped_total++
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 0c7e738cff9..3819c2d9d53 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -117,6 +117,18 @@
first_run()
+/obj/machinery/alarm/Del()
+ //If there's an active alarm, clear it after minute so that alarms don't keep going forver
+ delayed_reset()
+ ..()
+
+//needed to cancel the alarm after it is deleted
+/obj/machinery/alarm/proc/delayed_reset()
+ var/area/A = alarm_area
+ src = null
+ spawn(600)
+ //It makes sense not to touch firelocks here. The alarm itself is gone, we have no idea what the atmos is like.
+ A.atmosalert(0, set_firelocks=0)
/obj/machinery/alarm/proc/first_run()
alarm_area = get_area(src)
@@ -1282,6 +1294,20 @@ FIRE ALARM
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
+/obj/machinery/firealarm/Del()
+ //so fire alarms don't keep going forever
+ delayed_reset()
+ ..()
+
+//needed to cancel the alarm after it is deleted
+/obj/machinery/firealarm/proc/delayed_reset()
+ var/area/A = get_area(src)
+ if (!A) return
+
+ src = null
+ spawn(600)
+ A.firereset()
+
/obj/machinery/firealarm/initialize()
if(z in config.contact_levels)
if(security_level)
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 154b2d4dc73..5219bd22b7c 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -108,6 +108,7 @@ update_flag
if (src.destroyed)
src.overlays = 0
src.icon_state = text("[]-1", src.canister_color)
+ return
if(icon_state != "[canister_color]")
icon_state = "[canister_color]"
diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm
index 4dd60649253..179557fb262 100644
--- a/code/game/machinery/bots/secbot.dm
+++ b/code/game/machinery/bots/secbot.dm
@@ -643,6 +643,9 @@ Auto Patrol: []"},
return
src.anchored = 0
for(var/mob/living/M in view(search_range,src)) //Let's find us a criminal
+ if(M.invisibility >= INVISIBILITY_LEVEL_ONE) // Cannot see him. see_invisible is a mob-var
+ continue
+
if(istype(M, /mob/living/carbon))
var/mob/living/carbon/C = M
if(C.stat || C.handcuffed)
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 4e064e347ee..eab3e5eda7e 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -55,9 +55,7 @@
if(!alarm_on)
triggerCameraAlarm()
- spawn(50)
- src = null
- cancelCameraAlarm() //so camera alarms don't just go on forever
+ cancelCameraAlarm()
..()
/obj/machinery/camera/emp_act(severity)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index aa5d7a02f17..454e6e44fc7 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -33,7 +33,7 @@
var/datum/dna2/record/buf=null
var/read_only = 0 //Well,it's still a floppy disk
-/obj/item/weapon/disk/data/proc/Initialize()
+/obj/item/weapon/disk/data/proc/initializeDisk()
buf = new
buf.dna=new
@@ -42,7 +42,7 @@
read_only = 1
New()
- Initialize()
+ initializeDisk()
buf.types=DNA2_BUF_UE|DNA2_BUF_UI
//data = "066000033000000000AF00330660FF4DB002690"
//data = "0C80C80C80C80C80C8000000000000161FBDDEF" - Farmer Jeff
@@ -57,7 +57,7 @@
read_only = 1
New()
- Initialize()
+ initializeDisk()
buf.types=DNA2_BUF_SE
var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4)
for(var/i=new_SE.len;i<=DNA_SE_LENGTH;i++)
diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm
index ba91ec2eea8..f4b5d257a05 100644
--- a/code/game/machinery/computer/HolodeckControl.dm
+++ b/code/game/machinery/computer/HolodeckControl.dm
@@ -444,7 +444,7 @@ var/global/list/holodeck_programs = list(
throw_range = 5
throwforce = 0
w_class = 2.0
- flags = FPRINT | TABLEPASS | NOSHIELD
+ flags = FPRINT | TABLEPASS | NOSHIELD | NOBLOODY
var/active = 0
/obj/item/weapon/holo/esword/green
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index b93855f0931..0a7f27d7016 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -23,6 +23,69 @@
user.reset_view(current)
return 1
+ ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
+ if(src.z > 6) return
+ if(stat & (NOPOWER|BROKEN)) return
+ if(user.stat) return
+
+ var/data[0]
+
+ data["current"] = null
+
+ var/list/L = list()
+ for (var/obj/machinery/camera/C in cameranet.cameras)
+ if(can_access_camera(C))
+ L.Add(C)
+
+ camera_sort(L)
+
+ var/cameras[0]
+ for(var/obj/machinery/camera/C in L)
+ var/cam[0]
+ cam["name"] = C.c_tag
+ cam["deact"] = !C.can_use()
+ cam["camera"] = "\ref[C]"
+ cam["x"] = C.x
+ cam["y"] = C.y
+ cam["z"] = C.z
+
+ cameras[++cameras.len] = cam
+
+ if(C == current)
+ data["current"] = cam
+
+ data["cameras"] = cameras
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ ui = new(user, src, ui_key, "sec_camera.tmpl", "Camera Console", 900, 800)
+
+ // adding a template with the key "mapContent" enables the map ui functionality
+ ui.add_template("mapContent", "sec_camera_map_content.tmpl")
+ // adding a template with the key "mapHeader" replaces the map header content
+ ui.add_template("mapHeader", "sec_camera_map_header.tmpl")
+
+ ui.set_initial_data(data)
+ ui.open()
+ ui.set_auto_update(1)
+
+ Topic(href, href_list)
+ if(href_list["switchTo"])
+ if(src.z>6 || stat&(NOPOWER|BROKEN)) return
+ if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return
+ var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras
+ if(!C) return
+
+ switch_to_camera(usr, C)
+ return 1
+ else if(href_list["reset"])
+ if(src.z>6 || stat&(NOPOWER|BROKEN)) return
+ if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return
+ current = null
+ usr.check_eye(current)
+ return 1
+ else
+ . = ..()
attack_hand(var/mob/user as mob)
if (src.z > 6)
@@ -32,35 +95,7 @@
if(!isAI(user))
user.set_machine(src)
-
- var/list/L = list()
- for (var/obj/machinery/camera/C in cameranet.cameras)
- L.Add(C)
-
- camera_sort(L)
-
- var/list/D = list()
- D["Cancel"] = "Cancel"
- for(var/obj/machinery/camera/C in L)
- if(can_access_camera(C))
- D[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C
-
- var/t = input(user, "Which camera should you change to?") as null|anything in D
- if(!t)
- user.unset_machine()
- return 0
-
- var/obj/machinery/camera/C = D[t]
-
- if(t == "Cancel")
- user.unset_machine()
- return 0
-
- if(C)
- switch_to_camera(user, C)
- spawn(5)
- attack_hand(user)
- return
+ ui_interact(user)
proc/can_access_camera(var/obj/machinery/camera/C)
var/list/shared_networks = src.network & C.network
@@ -79,6 +114,7 @@
if (!C.can_use() || user.stat || (get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) && !istype(user, /mob/living/silicon)))
return 0
src.current = C
+ check_eye(user)
use_power(50)
return 1
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index a85b24d8fb1..fdbaae21cc8 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -75,6 +75,8 @@
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
+ if(H.w_uniform != C)
+ continue
var/list/crewmemberData = list()
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index ca692bbbee3..e14c2779811 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -576,9 +576,9 @@ What a mess.*/
return photo.img
if(istype(user, /mob/living/silicon))
var/mob/living/silicon/tempAI = usr
- var/datum/picture/selection = tempAI.GetPicture()
+ var/obj/item/weapon/photo/selection = tempAI.GetPicture()
if (selection)
- return selection.fields["img"]
+ return selection.img
/obj/machinery/computer/secure_data/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index d1e3887e4b9..4fc82ebf4aa 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -381,7 +381,7 @@
// Delete the mob.
del(occupant)
occupant = null
-
+ name = initial(name)
return
@@ -442,7 +442,6 @@
src.add_fingerprint(M)
/obj/machinery/cryopod/verb/eject()
-
set name = "Eject Pod"
set category = "Object"
set src in oview(1)
@@ -464,6 +463,8 @@
src.go_out()
add_fingerprint(usr)
+
+ name = initial(name)
return
/obj/machinery/cryopod/verb/move_inside()
@@ -511,6 +512,7 @@
time_entered = world.time
src.add_fingerprint(usr)
+ name = "[name] ([usr.name])"
return
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index e595cea9333..49252eaac64 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -913,9 +913,9 @@ About the new airlock wires panel:
if(operating == -1)
new /obj/item/weapon/circuitboard/broken(src.loc)
operating = 0
- else
+ else
if (!electronics) create_electronics()
-
+
electronics.loc = src.loc
electronics = null
@@ -1059,13 +1059,17 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/New(var/newloc, var/obj/structure/door_assembly/assembly=null)
..()
+ //High-sec airlocks are much harder to completely break by emitters.
+ if(secured_wires)
+ emitter_resistance *= 3
+
//if assembly is given, create the new door from the assembly
if (assembly)
assembly_type = assembly.type
-
+
electronics = assembly.electronics
electronics.loc = src
-
+
//update the door's access to match the electronics'
secured_wires = electronics.secure
if(electronics.one_access)
@@ -1073,7 +1077,7 @@ About the new airlock wires panel:
req_one_access = src.electronics.conf_access
else
req_access = src.electronics.conf_access
-
+
//get the name from the assembly
if(assembly.created_name)
name = assembly.created_name
@@ -1093,8 +1097,8 @@ About the new airlock wires panel:
src.closeOther = A
break
-// Most doors will never be deconstructed over the course of a round,
-// so as an optimization defer the creation of electronics until
+// Most doors will never be deconstructed over the course of a round,
+// so as an optimization defer the creation of electronics until
// the airlock is deconstructed
/obj/machinery/door/airlock/proc/create_electronics()
//create new electronics
@@ -1102,7 +1106,7 @@ About the new airlock wires panel:
src.electronics = new/obj/item/weapon/airlock_electronics/secure( src.loc )
else
src.electronics = new/obj/item/weapon/airlock_electronics( src.loc )
-
+
//update the electronics to match the door's access
if(!src.req_access)
src.check_access()
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index bc8719060f4..c3ab77d74a1 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -25,6 +25,8 @@
var/air_properties_vary_with_direction = 0
var/maxhealth = 300
var/health
+ var/emitter_hits = 0 // For use when tracking amount of emitter hits taken.
+ var/emitter_resistance = 10 // Amount of emitter hits doors whistand
var/min_force = 10 //minimum amount of force needed to damage the door with a melee weapon
var/hitsound = 'sound/weapons/smash.ogg' //sound door makes when hit with a weapon
@@ -133,9 +135,22 @@
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
+ // Emitter Blasts - these will eventually completely destroy the door, given enough time.
+ if (istype(Proj, /obj/item/projectile/beam/emitter))
+ if(health > 0)
+ Proj.damage /= 4
+ else
+ emitter_hits ++
+ if(emitter_hits >= emitter_resistance)
+ visible_message("\red [src.name] breaks apart!", 1)
+ new /obj/effect/decal/cleanable/ash(src.loc) // Turn it to ashes!
+ del(src)
+
if(Proj.damage)
take_damage(Proj.damage)
+
+
/obj/machinery/door/hitby(AM as mob|obj)
..()
diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm
index 4f5e416d335..9ab7dabb2d1 100644
--- a/code/game/machinery/doors/poddoor.dm
+++ b/code/game/machinery/doors/poddoor.dm
@@ -6,6 +6,7 @@
var/id = 1.0
dir = 1
explosion_resistance = 25
+ emitter_resistance = 50 // Lots of emitter blasts, it's blast door after all.
/obj/machinery/door/poddoor/New()
. = ..()
@@ -28,6 +29,7 @@
icon_state = "pdoor0"
return
+
/obj/machinery/door/poddoor/attackby(obj/item/weapon/C as obj, mob/user as mob)
src.add_fingerprint(user)
if (!( istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/twohanded/fireaxe) && C:wielded == 1) ))
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 8d4d4ac2df2..cf19d9de278 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -55,6 +55,8 @@
var/datum/effect/effect/system/spark_spread/spark_system //the spark system, used for generating... sparks?
+ var/wrenching = 0
+
/obj/machinery/porta_turret/stationary
lethal = 1
installation = /obj/item/weapon/gun/energy/laser
@@ -223,7 +225,7 @@
else
usr << "It has to be secured first!"
- updateUsrDialog()
+ attack_hand(usr)
return
switch(href_list["operation"]) //toggles customizable behavioural protocols
@@ -242,7 +244,7 @@
check_access = !check_access
if("checkxenos")
check_anomalies = !check_anomalies
- updateUsrDialog()
+ attack_hand(usr)
/obj/machinery/porta_turret/power_change()
@@ -288,19 +290,32 @@
sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
on = 1 //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
- else if((istype(I, /obj/item/weapon/wrench)) && (!on))
- if(raised) return
+ else if((istype(I, /obj/item/weapon/wrench)))
+ if(on || raised)
+ user << ""
+ return
+ if(wrenching)
+ user << "Someone is already [anchored ? "un" : ""]securing the turret!"
+ return
+ if(!anchored && isinspace())
+ user << "Cannot secure turrets in space!"
+ return
+ user.visible_message( \
+ "[user] begins [anchored ? "un" : ""]securing the turret.", \
+ "You begin [anchored ? "un" : ""]securing the turret." \
+ )
+
+ wrenching = 1
if(do_after(user, 50))
//This code handles moving the turret around. After all, it's a portable turret!
- if(!anchored && !isinspace())
+ if(!anchored)
playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
anchored = 1
invisibility = INVISIBILITY_LEVEL_TWO
update_icon()
user << "You secure the exterior bolts on the turret."
- cover = new /obj/machinery/porta_turret_cover(loc) //create a new turret. While this is handled in process(), this is to workaround a bug where the turret becomes invisible for a split second
- cover.Parent_Turret = src //make the cover's parent src
+ create_cover()
else if(anchored)
playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
anchored = 0
@@ -308,6 +323,7 @@
invisibility = 0
update_icon()
del(cover) //deletes the cover, and the turret instance itself becomes its own cover. - qdel
+ wrenching = 0
else if(istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda))
//Behavior lock/unlock mangement
@@ -348,7 +364,7 @@
spawn()
sleep(60)
attacked = 0
-
+
..()
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
@@ -395,7 +411,10 @@
update_icon()
del(cover) //deletes the cover - no need on keeping it there! - del
-
+/obj/machinery/porta_turret/proc/create_cover()
+ if(cover == null && anchored)
+ cover = new /obj/machinery/porta_turret_cover(loc) //if the turret has no cover and is anchored, give it a cover
+ cover.Parent_Turret = src //assign the cover its Parent_Turret, which would be this (src)
/obj/machinery/porta_turret/process()
//the main machinery process
@@ -406,9 +425,7 @@
if(stat & BROKEN) //if the turret is borked
del(cover) //delete its cover, assuming it has one. Workaround for a pesky little bug - qdel
else
-
- cover = new /obj/machinery/porta_turret_cover(loc) //if the turret has no cover and is anchored, give it a cover
- cover.Parent_Turret = src //assign the cover its Parent_Turret, which would be this (src)
+ create_cover()
if(stat & (NOPOWER|BROKEN))
//if the turret has no power or is broken, make the turret pop down if it hasn't already
@@ -445,6 +462,9 @@
secondarytargets += L
/obj/machinery/porta_turret/proc/assess_living(var/mob/living/L)
+ if(L.invisibility >= INVISIBILITY_LEVEL_ONE) // Cannot see him. see_invisible is a mob-var
+ return TURRET_NOT_TARGET
+
if(!L)
return TURRET_NOT_TARGET
@@ -464,7 +484,7 @@
if(check_synth) //If it's set to attack all non-silicons, target them!
if(L.lying)
- return TURRET_SECONDARY_TARGET
+ return lethal ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET
return TURRET_PRIORITY_TARGET
if(iscuffed(L)) // If the target is handcuffed, leave it alone
@@ -480,7 +500,7 @@
return TURRET_NOT_TARGET //if threat level < 4, keep going
if(L.lying) //if the perp is lying down, it's still a target but a less-important target
- return TURRET_SECONDARY_TARGET
+ return lethal ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET
return TURRET_PRIORITY_TARGET //if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee
@@ -840,11 +860,6 @@
density = 0
var/obj/machinery/porta_turret/Parent_Turret = null
-
-//The below code is pretty much just recoded from the initial turret object. It's necessary but uncommented because it's exactly the same!
-//>necessary
-//I'm not fixing it because i'm fucking bored of this code already, but someone should just reroute these to the parent turret's procs.
-
/obj/machinery/porta_turret_cover/attack_ai(mob/user)
return attack_hand(user)
@@ -853,7 +868,6 @@
/obj/machinery/porta_turret_cover/Topic(href, href_list)
Parent_Turret.Topic(href, href_list, 1) // Calling another object's Topic requires that we claim to not have a window, otherwise BYOND's base proc will runtime.
- updateUsrDialog()
/obj/machinery/porta_turret_cover/attackby(obj/item/I, mob/user)
Parent_Turret.attackby(I, user)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 5a52dde42e4..26f1c620c7a 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -26,7 +26,6 @@
var/vend_power_usage = 150 //actuators and stuff
var/active = 1 //No sales pitches if off!
- var/delay_product_spawn // If set, uses sleep() in product spawn proc (mostly for seeds to retrieve correct names).
var/vend_ready = 1 //Are we ready to vend?? Is it time??
var/vend_delay = 10 //How long does it take to vend?
var/datum/data/vending_product/currently_vending = null // A /datum/data/vending_product instance of what we're paying for right now.
@@ -122,9 +121,6 @@
/obj/machinery/vending/proc/build_inventory(var/list/productlist,hidden=0,req_coin=0)
- if(delay_product_spawn)
- sleep(15) //Make ABSOLUTELY SURE the seed datum is properly populated.
-
for(var/typepath in productlist)
var/amount = productlist[typepath]
var/price = prices[typepath]
@@ -147,9 +143,6 @@
R.category=CAT_NORMAL
product_records += R
- if(delay_product_spawn)
- sleep(5) //sleep(1) did not seem to cut it, so here we are.
-
var/atom/temp = typepath
R.product_name = initial(temp.name)
@@ -791,7 +784,6 @@
product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!"
product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!"
icon_state = "seeds"
- delay_product_spawn = 1
products = list(/obj/item/seeds/bananaseed = 3,/obj/item/seeds/berryseed = 3,/obj/item/seeds/carrotseed = 3,/obj/item/seeds/chantermycelium = 3,/obj/item/seeds/chiliseed = 3,
/obj/item/seeds/cornseed = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/replicapod = 3,/obj/item/seeds/soyaseed = 3,
@@ -803,6 +795,34 @@
/obj/item/seeds/nettleseed = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/shandseed = 2,)
premium = list(/obj/item/toy/waterflower = 1)
+/obj/machinery/vending/hydroseeds/build_inventory(var/list/productlist,hidden=0,req_coin=0)
+
+ for(var/typepath in productlist)
+ var/amount = productlist[typepath]
+ var/price = prices[typepath]
+ if(isnull(amount)) amount = 1
+
+ var/datum/data/vending_product/R = new /datum/data/vending_product()
+
+ R.product_path = typepath
+ R.amount = amount
+ R.price = price
+ R.display_color = pick("red","blue","green")
+
+ if(hidden)
+ R.category=CAT_HIDDEN
+ hidden_records += R
+ else if(req_coin)
+ R.category=CAT_COIN
+ coin_records += R
+ else
+ R.category=CAT_NORMAL
+ product_records += R
+
+ var/obj/item/seeds/S = new typepath(src)
+ R.product_name = S.name
+ del(S)
+ return
/obj/machinery/vending/magivend
name = "MagiVend"
@@ -877,7 +897,7 @@
icon_state = "robotics"
icon_deny = "robotics-deny"
req_access_txt = "29"
- products = list(/obj/item/clothing/suit/storage/labcoat = 4,/obj/item/clothing/under/rank/roboticist = 4,/obj/item/stack/cable_coil = 4,/obj/item/device/flash = 4,
+ products = list(/obj/item/clothing/suit/storage/toggle/labcoat = 4,/obj/item/clothing/under/rank/roboticist = 4,/obj/item/stack/cable_coil = 4,/obj/item/device/flash = 4,
/obj/item/weapon/cell/high = 12, /obj/item/device/assembly/prox_sensor = 3,/obj/item/device/assembly/signaler = 3,/obj/item/device/healthanalyzer = 3,
/obj/item/weapon/scalpel = 2,/obj/item/weapon/circular_saw = 2,/obj/item/weapon/tank/anesthetic = 2,/obj/item/clothing/mask/breath/medical = 5,
/obj/item/weapon/screwdriver = 5,/obj/item/weapon/crowbar = 5)
diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm
index 20703363ff8..d3c249b7473 100644
--- a/code/game/mecha/mech_bay.dm
+++ b/code/game/mecha/mech_bay.dm
@@ -46,8 +46,8 @@
return
// temporary fix for broken icon until somebody gets around to make these player-buildable
-/turf/simulated/floor/mech_bay_recharge_floor/attackby(obj/item/C as obj, mob/user as mob)
- ..()
+/turf/simulated/floor/mech_bay_recharge_floor/attackby(obj/item/C as obj, mob/user as mob)
+ ..()
if(floor_type)
icon_state = "recharge_floor"
else
@@ -190,45 +190,28 @@
var/turf/simulated/floor/mech_bay_recharge_floor/F = locate() in range(1,src)
if(F)
F.init_devices()
-
- var/output = "[src.name]"
- if(!recharge_floor)
- output += "Mech Bay Recharge Station not initialized.
"
+ ui_interact(user)
+
+/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ var/list/data = list()
+ data["has_floor"] = recharge_floor
+ data["has_port"] = recharge_port
+ if(recharge_floor && recharge_floor.recharging_mecha && recharge_floor.recharging_mecha.cell)
+ data["has_mech"] = 1
+ data["mecha_name"] = recharge_floor.recharging_mecha || "None"
+ data["mecha_charge"] = isnull(recharge_floor.recharging_mecha) ? 0 : recharge_floor.recharging_mecha.cell.charge
+ data["mecha_maxcharge"] = isnull(recharge_floor.recharging_mecha) ? 0 : recharge_floor.recharging_mecha.cell.maxcharge
+ data["mecha_charge_percentage"] = isnull(recharge_floor.recharging_mecha) ? 0 : round(recharge_floor.recharging_mecha.cell.percent())
else
- output += {"Mech Bay Recharge Station Data:
- Mecha: [recharge_floor.recharging_mecha||"None"]
"}
- if(recharge_floor.recharging_mecha)
- var/cell_charge = recharge_floor.recharging_mecha.get_charge()
- output += "Cell charge: [isnull(cell_charge)?"No powercell found":"[recharge_floor.recharging_mecha.cell.charge]/[recharge_floor.recharging_mecha.cell.maxcharge]"]
"
- output += "
"
- if(!recharge_port)
- output += "Mech Bay Power Port not initialized.
"
- else
- output += "Mech Bay Power Port Status: [recharge_port.active()?"Now charging":"On hold"]
"
-
- /*
- output += {"
- Settings:
- "}
- */
-
- output += " body>"
- user << browse(output, "window=mech_bay_console")
- onclose(user, "mech_bay_console")
- return
-
-// unused at the moment, also lacks any kind of exploit prevention
-/*
-/obj/machinery/computer/mech_bay_power_console/Topic(href, href_list)
- if(href_list["autostart"])
- autostart = !autostart
- if(href_list["voltage"])
- voltage = text2num(href_list["voltage"])
- if(recharge_port)
- recharge_port.set_voltage(voltage)
- updateUsrDialog()
- return
-*/
+ data["has_mech"] = 0
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ // the ui does not exist, so we'll create a new() one
+ // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
+ ui = new(user, src, ui_key, "mech_bay_console.tmpl", "Mech Bay Control Console", 500, 325)
+ // when the ui is first opened this is the data it will use
+ ui.set_initial_data(data)
+ // open the new ui window
+ ui.open()
+ // auto update every Master Controller tick
+ ui.set_auto_update(1)
\ No newline at end of file
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index ba4493522f6..e56dbe71e86 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -453,10 +453,10 @@
for(var/datum/design/D in files.known_designs)
if(D.build_type&16)
if(D.category in part_sets)//Checks if it's a valid category
- if(add_part_to_set(D.category, text2path(D.build_path)))//Adds it to said category
+ if(add_part_to_set(D.category, D.build_path))//Adds it to said category
i++
else
- if(add_part_to_set("Misc", text2path(D.build_path)))//If in doubt, chunk it into the Misc
+ if(add_part_to_set("Misc", D.build_path))//If in doubt, chunk it into the Misc
i++
return i
diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm
index d50d595d3ea..8d8328bc9f5 100644
--- a/code/game/objects/effects/decals/remains.dm
+++ b/code/game/objects/effects/decals/remains.dm
@@ -1,23 +1,28 @@
-/obj/effect/decal/remains/human
+/obj/effect/decal/remains
name = "remains"
- desc = "They look like human remains. They have a strange aura about them."
gender = PLURAL
icon = 'icons/effects/blood.dmi'
icon_state = "remains"
- anchored = 1
+ anchored = 0
+
+/obj/effect/decal/remains/human
+ desc = "They look like human remains. They have a strange aura about them."
/obj/effect/decal/remains/xeno
- name = "remains"
desc = "They look like the remains of something... alien. They have a strange aura about them."
- gender = PLURAL
- icon = 'icons/effects/blood.dmi'
icon_state = "remainsxeno"
- anchored = 1
/obj/effect/decal/remains/robot
- name = "remains"
desc = "They look like the remains of something mechanical. They have a strange aura about them."
- gender = PLURAL
icon = 'icons/mob/robots.dmi'
icon_state = "remainsrobot"
- anchored = 1
\ No newline at end of file
+
+/obj/effect/decal/remains/attack_hand(mob/user as mob)
+ user << "[src] sinks together into a pile of ash."
+ var/turf/simulated/floor/F = get_turf(src)
+ if (istype(F))
+ new /obj/effect/decal/cleanable/ash(F)
+ del(src)
+
+/obj/effect/decal/remains/robot/attack_hand(mob/user as mob)
+ return
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 16bde74e693..b69f85af388 100755
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -1052,7 +1052,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message)
var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" (Reply)"
- new_info(news_silent, newstone, reception_message)
+ new_info(message_silent, newstone, reception_message)
log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
new_message = 1
diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm
index 99c4f960b0f..f64473ba549 100644
--- a/code/game/objects/items/weapons/manuals.dm
+++ b/code/game/objects/items/weapons/manuals.dm
@@ -1,6 +1,5 @@
/*********************MANUALS (BOOKS)***********************/
-//Oh god what the fuck I am not good at computer
/obj/item/weapon/book/manual
icon = 'icons/obj/library.dmi'
due_date = 0 // Game time in 1/10th seconds
@@ -13,26 +12,29 @@
author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned
title = "Station Repairs and Construction"
+/obj/item/weapon/book/manual/engineering_construction/New()
+ ..()
dat = {"
-
+
"}
-
/obj/item/weapon/book/manual/engineering_particle_accelerator
name = "Particle Accelerator User's Guide"
icon_state ="bookParticleAccelerator"
author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned
title = "Particle Accelerator User's Guide"
+/obj/item/weapon/book/manual/engineering_particle_accelerator/New()
+ ..()
dat = {"