"
+ for(var/lkey in thisrecord)
+ if(lkey in hidden_fields)
+ if(centcom)
+ record_html += "
[thisrecord[lkey]]
"
+ else
+ continue
+ else
+ record_html += "
[thisrecord[lkey]]
"
+ record_html += "
"
+ visible_record_count++
+
+ record_html += "
"
+
+ if(!visible_record_count)
+ return "No records on file yet."
+ return record_html
+
+/datum/controller/subsystem/jobs/proc/delete_log_records(sourceuser, delete_all)
+ . = 0
+ if(!sourceuser)
+ return
+ var/list/new_id_change_records = list()
+ for(var/thisid in id_change_records)
+ var/thisrecord = id_change_records[thisid]
+ if(!thisrecord["deletedby"])
+ if(delete_all || thisrecord["whodidit"] == sourceuser)
+ thisrecord["deletedby"] = sourceuser
+ .++
+ new_id_change_records["[id_change_counter]"] = thisrecord
+ id_change_counter++
+ id_change_records = new_id_change_records
\ No newline at end of file
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
new file mode 100644
index 00000000000..82bbd52471a
--- /dev/null
+++ b/code/controllers/subsystem/lighting.dm
@@ -0,0 +1,87 @@
+GLOBAL_LIST_EMPTY(lighting_update_lights) // List of lighting sources queued for update.
+GLOBAL_LIST_EMPTY(lighting_update_corners) // List of lighting corners queued for update.
+GLOBAL_LIST_EMPTY(lighting_update_objects) // List of lighting objects queued for update.
+
+SUBSYSTEM_DEF(lighting)
+ name = "Lighting"
+ wait = 2
+ init_order = INIT_ORDER_LIGHTING
+ flags = SS_TICKER
+
+/datum/controller/subsystem/lighting/stat_entry()
+ ..("L:[GLOB.lighting_update_lights.len]|C:[GLOB.lighting_update_corners.len]|O:[GLOB.lighting_update_objects.len]")
+
+/datum/controller/subsystem/lighting/Initialize(timeofday)
+ if(!initialized)
+ if(config.starlight)
+ for(var/I in GLOB.all_areas)
+ var/area/A = I
+ if(A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
+ A.luminosity = 0
+
+ create_all_lighting_objects()
+ initialized = TRUE
+
+ fire(FALSE, TRUE)
+
+ return ..()
+
+/datum/controller/subsystem/lighting/fire(resumed, init_tick_checks)
+ MC_SPLIT_TICK_INIT(3)
+ if(!init_tick_checks)
+ MC_SPLIT_TICK
+ var/i = 0
+ for(i in 1 to GLOB.lighting_update_lights.len)
+ var/datum/light_source/L = GLOB.lighting_update_lights[i]
+
+ L.update_corners()
+
+ L.needs_update = LIGHTING_NO_UPDATE
+
+ if(init_tick_checks)
+ CHECK_TICK
+ else if(MC_TICK_CHECK)
+ break
+ if(i)
+ GLOB.lighting_update_lights.Cut(1, i+1)
+ i = 0
+
+ if(!init_tick_checks)
+ MC_SPLIT_TICK
+
+ for (i in 1 to GLOB.lighting_update_corners.len)
+ var/datum/lighting_corner/C = GLOB.lighting_update_corners[i]
+
+ C.update_objects()
+ C.needs_update = FALSE
+ if(init_tick_checks)
+ CHECK_TICK
+ else if(MC_TICK_CHECK)
+ break
+ if(i)
+ GLOB.lighting_update_corners.Cut(1, i+1)
+ i = 0
+
+
+ if(!init_tick_checks)
+ MC_SPLIT_TICK
+
+ for (i in 1 to GLOB.lighting_update_objects.len)
+ var/atom/movable/lighting_object/O = GLOB.lighting_update_objects[i]
+
+ if(QDELETED(O))
+ continue
+
+ O.update()
+ O.needs_update = FALSE
+ if(init_tick_checks)
+ CHECK_TICK
+ else if(MC_TICK_CHECK)
+ break
+ if(i)
+ GLOB.lighting_update_objects.Cut(1, i+1)
+
+
+/datum/controller/subsystem/lighting/Recover()
+ initialized = SSlighting.initialized
+ ..()
\ No newline at end of file
diff --git a/code/controllers/subsystem/machinery.dm b/code/controllers/subsystem/machinery.dm
index af6898c39bd..9a73c1dbabb 100644
--- a/code/controllers/subsystem/machinery.dm
+++ b/code/controllers/subsystem/machinery.dm
@@ -17,7 +17,7 @@ SUBSYSTEM_DEF(machines)
/datum/controller/subsystem/machines/Initialize()
makepowernets()
fire()
- ..()
+ return ..()
/datum/controller/subsystem/machines/proc/makepowernets()
for(var/datum/powernet/PN in powernets)
@@ -64,23 +64,6 @@ SUBSYSTEM_DEF(machines)
if(MC_TICK_CHECK)
return
-/datum/controller/subsystem/machines/proc/process_premachines(resumed = 0)
- /* Literally exists as snowflake for fucking powersinks goddamnit */
- if(!resumed)
- src.currentrun = GLOB.processing_power_items.Copy()
- //cache for sanid speed (lists are references anyways)
- var/list/currentrun = src.currentrun
- while(currentrun.len)
- var/obj/item/I = currentrun[currentrun.len]
- currentrun.len--
- if(!QDELETED(I))
- if(!I.pwr_drain())
- GLOB.processing_power_items.Remove(I)
- else
- GLOB.processing_power_items.Remove(I)
- if(MC_TICK_CHECK)
- return
-
/datum/controller/subsystem/machines/proc/process_machines(resumed = 0)
var/seconds = wait * 0.1
if(!resumed)
@@ -113,13 +96,6 @@ SUBSYSTEM_DEF(machines)
if(state != SS_RUNNING)
return
resumed = 0
- currentpart = SSMACHINES_PREMACHINERY
-
- if(currentpart == SSMACHINES_PREMACHINERY || !resumed)
- process_premachines(resumed)
- if(state != SS_RUNNING)
- return
- resumed = 0
currentpart = SSMACHINES_MACHINERY
if(currentpart == SSMACHINES_MACHINERY || !resumed)
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
new file mode 100644
index 00000000000..ec53c4b4d6b
--- /dev/null
+++ b/code/controllers/subsystem/mapping.dm
@@ -0,0 +1,42 @@
+SUBSYSTEM_DEF(mapping)
+ name = "Mapping"
+ init_order = INIT_ORDER_MAPPING // 9
+ flags = SS_NO_FIRE
+
+/datum/controller/subsystem/mapping/Initialize(timeofday)
+ // Load all Z level templates
+ preloadTemplates()
+ // Pick a random away mission.
+ if(!config.disable_away_missions)
+ createRandomZlevel()
+ // Seed space ruins
+ if(!config.disable_space_ruins)
+ var/timer = start_watch()
+ log_startup_progress("Creating random space levels...")
+ seedRuins(list(level_name_to_num(EMPTY_AREA)), rand(0, 3), /area/space, space_ruins_templates)
+ log_startup_progress("Loaded random space levels in [stop_watch(timer)]s.")
+
+ // load in extra levels of space ruins
+
+ var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max)
+ for(var/i = 1, i <= num_extra_space, i++)
+ var/zlev = space_manager.add_new_zlevel("[EMPTY_AREA] #[i]", linkage = CROSSLINKED, traits = list(REACHABLE))
+ seedRuins(list(zlev), rand(0, 3), /area/space, space_ruins_templates)
+
+ // Setup the Z-level linkage
+ space_manager.do_transition_setup()
+
+ // Handle the mining z-level ruins or secrets.
+ var/mining_type = MINETYPE
+ if (mining_type == "lavaland")
+ // Spawn Lavaland ruins and rivers.
+ seedRuins(list(level_name_to_num(MINING)), config.lavaland_budget, /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates)
+ spawn_rivers()
+ else
+ // Populate mining Z-level hidden rooms
+ for(var/i = 0, i < max_secret_rooms, i++)
+ make_mining_asteroid_secret()
+ return ..()
+
+/datum/controller/subsystem/mapping/Recover()
+ flags |= SS_NO_INIT
\ No newline at end of file
diff --git a/code/controllers/subsystem/medals.dm b/code/controllers/subsystem/medals.dm
new file mode 100644
index 00000000000..f3c2752ddf2
--- /dev/null
+++ b/code/controllers/subsystem/medals.dm
@@ -0,0 +1,86 @@
+SUBSYSTEM_DEF(medals)
+ name = "Medals"
+ flags = SS_NO_FIRE
+ var/hub_enabled = FALSE
+
+/datum/controller/subsystem/medals/Initialize(timeofday)
+ if(config.medal_hub_address && config.medal_hub_password)
+ hub_enabled = TRUE
+ ..()
+
+/datum/controller/subsystem/medals/proc/UnlockMedal(medal, client/player)
+ set waitfor = FALSE
+ if(!medal || !hub_enabled)
+ return
+ if(isnull(world.SetMedal(medal, player, config.medal_hub_address, config.medal_hub_password)))
+ hub_enabled = FALSE
+ log_game("MEDAL ERROR: Could not contact hub to award medal [medal] to player [player.ckey].")
+ message_admins("Error! Failed to contact hub to award [medal] medal to [player.ckey]!")
+ return
+ to_chat(player, "Achievement unlocked: [medal]!")
+
+/datum/controller/subsystem/medals/proc/SetScore(score, client/player, increment, force)
+ set waitfor = FALSE
+ if(!score || !hub_enabled)
+ return
+
+ var/list/oldscore = GetScore(score, player, TRUE)
+ if(increment)
+ if(!oldscore[score])
+ oldscore[score] = 1
+ else
+ oldscore[score] = (text2num(oldscore[score]) + 1)
+ else
+ oldscore[score] = force
+
+ var/newscoreparam = list2params(oldscore)
+
+ if(isnull(world.SetScores(player.ckey, newscoreparam, config.medal_hub_address, config.medal_hub_password)))
+ hub_enabled = FALSE
+ log_game("SCORE ERROR: Could not contact hub to set score. Score [score] for player [player.ckey].")
+ message_admins("Error! Failed to contact hub to set [score] score for [player.ckey]!")
+
+/datum/controller/subsystem/medals/proc/GetScore(score, client/player, returnlist)
+ if(!score || !hub_enabled)
+ return
+
+ var/scoreget = world.GetScores(player.ckey, score, config.medal_hub_address, config.medal_hub_password)
+ if(isnull(scoreget))
+ hub_enabled = FALSE
+ log_game("SCORE ERROR: Could not contact hub to get score. Score [score] for player [player.ckey].")
+ message_admins("Error! Failed to contact hub to get score [score] for [player.ckey]!")
+ return
+ . = params2list(scoreget)
+ if(!returnlist)
+ return .[score]
+
+/datum/controller/subsystem/medals/proc/CheckMedal(medal, client/player)
+ if(!medal || !hub_enabled)
+ return
+
+ if(isnull(world.GetMedal(medal, player, config.medal_hub_address, config.medal_hub_password)))
+ hub_enabled = FALSE
+ log_game("MEDAL ERROR: Could not contact hub to get medal [medal] for player [player.ckey]")
+ message_admins("Error! Failed to contact hub to get [medal] medal for [player.ckey]!")
+ return
+ to_chat(player, "[medal] is unlocked")
+
+/datum/controller/subsystem/medals/proc/LockMedal(medal, client/player)
+ if(!player || !medal || !hub_enabled)
+ return
+ var/result = world.ClearMedal(medal, player, config.medal_hub_address, config.medal_hub_password)
+ switch(result)
+ if(null)
+ hub_enabled = FALSE
+ log_game("MEDAL ERROR: Could not contact hub to clear medal [medal] for player [player.ckey].")
+ message_admins("Error! Failed to contact hub to clear [medal] medal for [player.ckey]!")
+ if(TRUE)
+ message_admins("Medal: [medal] removed for [player.ckey]")
+ if(FALSE)
+ message_admins("Medal: [medal] was not found for [player.ckey]. Unable to clear.")
+
+
+/datum/controller/subsystem/medals/proc/ClearScore(client/player)
+ if(isnull(world.SetScores(player.ckey, "", config.medal_hub_address, config.medal_hub_password)))
+ log_game("MEDAL ERROR: Could not contact hub to clear scores for [player.ckey].")
+ message_admins("Error! Failed to contact hub to clear scores for [player.ckey]!")
\ No newline at end of file
diff --git a/code/controllers/subsystem/mobs.dm b/code/controllers/subsystem/mobs.dm
index d19396af767..17edb6410fa 100644
--- a/code/controllers/subsystem/mobs.dm
+++ b/code/controllers/subsystem/mobs.dm
@@ -1,14 +1,21 @@
SUBSYSTEM_DEF(mobs)
name = "Mobs"
priority = FIRE_PRIORITY_MOBS
- flags = SS_KEEP_TIMING | SS_NO_INIT
+ flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/currentrun = list()
+ var/static/list/clients_by_zlevel[][]
+ var/static/list/dead_players_by_zlevel[][] = list(list()) // Needs to support zlevel 1 here, MaxZChanged only happens when z2 is created and new_players can login before that.
/datum/controller/subsystem/mobs/stat_entry()
..("P:[GLOB.mob_list.len]")
+/datum/controller/subsystem/mobs/Initialize(start_timeofday)
+ clients_by_zlevel = new /list(world.maxz,0)
+ dead_players_by_zlevel = new /list(world.maxz,0)
+ return ..()
+
/datum/controller/subsystem/mobs/fire(resumed = 0)
var/seconds = wait * 0.1
if(!resumed)
diff --git a/code/controllers/subsystem/nightshift.dm b/code/controllers/subsystem/nightshift.dm
index 358076c5652..4ebe1dceb0e 100644
--- a/code/controllers/subsystem/nightshift.dm
+++ b/code/controllers/subsystem/nightshift.dm
@@ -20,7 +20,7 @@ SUBSYSTEM_DEF(nightshift)
return ..()
/datum/controller/subsystem/nightshift/fire(resumed = FALSE)
- if(world.time - round_start_time < nightshift_first_check)
+ if(world.time - SSticker.round_start_time < nightshift_first_check)
return
check_nightshift()
diff --git a/code/controllers/subsystem/npcai.dm b/code/controllers/subsystem/npcai.dm
deleted file mode 100644
index f8fa3a5aa0f..00000000000
--- a/code/controllers/subsystem/npcai.dm
+++ /dev/null
@@ -1,24 +0,0 @@
-SUBSYSTEM_DEF(npcai)
- name = "NPC AI" // Simple AI controller, isolated from the SNPC one (NPCPool).
- flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
- priority = FIRE_PRIORITY_NPC
- runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
- var/list/simple_animal_list = list()
-
-/datum/controller/subsystem/npcai/stat_entry()
- ..("SimAnimals:[simple_animal_list.len]")
-
-/datum/controller/subsystem/npcai/fire(resumed = FALSE)
- if(!resumed)
- src.simple_animal_list = simple_animal_list.Copy()
- for(var/mob/living/simple_animal/M in simple_animal_list)
- if(istype(M) && !QDELETED(M))
- if(!M.client && M.stat == CONSCIOUS)
- M.process_ai()
- if(MC_TICK_CHECK)
- return
- else
- simple_animal_list -= M
-
-/datum/controller/subsystem/npcai/Recover()
- simple_animal_list = SSnpcai.simple_animal_list
\ No newline at end of file
diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm
index b06d33f6f32..0de306b12eb 100644
--- a/code/controllers/subsystem/npcpool.dm
+++ b/code/controllers/subsystem/npcpool.dm
@@ -1,127 +1,33 @@
-#define PROCESSING_NPCS 0
-#define PROCESSING_DELEGATES 1
-#define PROCESSING_ASSISTANTS 2
-
SUBSYSTEM_DEF(npcpool)
- name = "NPC Pool"
- flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
- priority = FIRE_PRIORITY_NPC
- runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ name = "NPC Pool"
+ flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
+ priority = FIRE_PRIORITY_NPC
+ runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
- var/list/canBeUsed = list()
- var/list/needsDelegate = list()
- var/list/needsAssistant = list()
-
- var/list/processing = list()
- var/list/currentrun = list()
- var/stage
+ var/list/currentrun = list()
/datum/controller/subsystem/npcpool/stat_entry()
- ..("NPCS:[processing.len]|D:[needsDelegate.len]|A:[needsAssistant.len]|U:[canBeUsed.len]")
-
-/datum/controller/subsystem/npcpool/proc/stop_processing(mob/living/carbon/human/interactive/I)
- processing -= I
- currentrun -= I
- needsDelegate -= I
- canBeUsed -= I
- needsAssistant -= I
+ var/list/activelist = GLOB.simple_animals[AI_ON]
+ ..("SimpleAnimals:[activelist.len]")
/datum/controller/subsystem/npcpool/fire(resumed = FALSE)
- //bot delegation and coordination systems
- //General checklist/Tasks for delegating a task or coordinating it (for SNPCs)
- // 1. Bot proximity to task target: if too far, delegate, if close, coordinate
- // 2. Bot Health/status: check health with bots in local area, if their health is higher, delegate task to them, else coordinate
- // 3. Process delegation: if a bot (or bots) has been delegated, assign them to the task.
- // 4. Process coordination: if a bot(or bots) has been asked to coordinate, assign them to help.
- // 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them.
- if (!resumed)
- currentrun = processing.Copy()
- stage = PROCESSING_NPCS
- //cache for sanic speed (lists are references anyways)
- var/list/cachecurrentrun = currentrun
- var/list/cachecanBeUsed = canBeUsed
+ if(!resumed)
+ var/list/activelist = GLOB.simple_animals[AI_ON]
+ src.currentrun = activelist.Copy()
- if(stage == PROCESSING_NPCS)
- while(cachecurrentrun.len)
- var/mob/living/carbon/human/interactive/thing = cachecurrentrun[cachecurrentrun.len]
- --cachecurrentrun.len
+ var/list/currentrun = src.currentrun
- thing.InteractiveProcess()
+ while(currentrun.len)
+ var/mob/living/simple_animal/SA = currentrun[currentrun.len]
+ --currentrun.len
- var/checkInRange = view(SNPC_MAX_RANGE_FIND,thing)
- if(thing.IsDeadOrIncap(FALSE) || !(locate(thing.TARGET) in checkInRange))
- needsDelegate += thing
- else if(thing.doing & SNPC_FIGHTING)
- needsAssistant += thing
- else
- cachecanBeUsed += thing
-
- if (MC_TICK_CHECK)
- return
- stage = PROCESSING_DELEGATES
- cachecurrentrun = needsDelegate //localcache
- currentrun = cachecurrentrun
-
- if(stage == PROCESSING_DELEGATES)
- while(cachecurrentrun.len && cachecanBeUsed.len)
- var/mob/living/carbon/human/interactive/check = cachecurrentrun[cachecurrentrun.len]
- var/mob/living/carbon/human/interactive/candidate = cachecanBeUsed[cachecanBeUsed.len]
- --cachecurrentrun.len
-
- var/helpProb = 0
- var/list/chfac = check.faction
- var/list/canfac = candidate.faction
- var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac)
-
- for(var/C in chfac)
- if(C in canfac)
- helpProb = min(100,helpProb + 25)
- if(helpProb >= 100)
- break
-
- if(facCount == 1 && helpProb)
- helpProb = 100
-
- if(prob(helpProb) && candidate.takeDelegate(check))
- --cachecanBeUsed.len
- candidate.change_eye_color(255, 0, 0)
- candidate.update_icons()
-
- if(MC_TICK_CHECK)
- return
- stage = PROCESSING_ASSISTANTS
- cachecurrentrun = needsAssistant //localcache
- currentrun = cachecurrentrun
-
- //no need for the stage check
-
- while(cachecurrentrun.len && cachecanBeUsed.len)
- var/mob/living/carbon/human/interactive/check = cachecurrentrun[cachecurrentrun.len]
- var/mob/living/carbon/human/interactive/candidate = cachecanBeUsed[cachecanBeUsed.len]
- --cachecurrentrun.len
-
- var/helpProb = 0
- var/list/chfac = check.faction
- var/list/canfac = candidate.faction
- var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac)
-
- for(var/C in chfac)
- if(C in canfac)
- helpProb = min(100,helpProb + 25)
- if(helpProb >= 100)
- break
-
- if(facCount == 1 && helpProb)
- helpProb = 100
-
- if(prob(helpProb) && candidate.takeDelegate(check,FALSE))
- --cachecanBeUsed.len
- candidate.change_eye_color(255, 255, 0)
- candidate.update_icons()
-
- if(!cachecurrentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary
- return
-
-/datum/controller/subsystem/npcpool/Recover()
- processing = SSnpcpool.processing
\ No newline at end of file
+ if(!SA.ckey && !SA.notransform)
+ if(SA.stat != DEAD)
+ SA.handle_automated_movement()
+ if(SA.stat != DEAD)
+ SA.handle_automated_action()
+ if(SA.stat != DEAD)
+ SA.handle_automated_speech()
+ if(MC_TICK_CHECK)
+ return
\ No newline at end of file
diff --git a/code/controllers/subsystem/processing/fastprocess.dm b/code/controllers/subsystem/processing/fastprocess.dm
new file mode 100644
index 00000000000..732c5a3ba55
--- /dev/null
+++ b/code/controllers/subsystem/processing/fastprocess.dm
@@ -0,0 +1,6 @@
+//Fires five times every second.
+
+PROCESSING_SUBSYSTEM_DEF(fastprocess)
+ name = "Fast Processing"
+ wait = 2
+ stat_tag = "FP"
\ No newline at end of file
diff --git a/code/controllers/subsystem/processing/obj.dm b/code/controllers/subsystem/processing/obj.dm
new file mode 100644
index 00000000000..7ee2bb1f0f3
--- /dev/null
+++ b/code/controllers/subsystem/processing/obj.dm
@@ -0,0 +1,5 @@
+PROCESSING_SUBSYSTEM_DEF(obj)
+ name = "Objects"
+ priority = FIRE_PRIORITY_OBJ
+ flags = SS_NO_INIT
+ wait = 20
\ No newline at end of file
diff --git a/code/controllers/subsystem/processing/processing.dm b/code/controllers/subsystem/processing/processing.dm
index 92254454219..2e06d7ebcc6 100644
--- a/code/controllers/subsystem/processing/processing.dm
+++ b/code/controllers/subsystem/processing/processing.dm
@@ -1,7 +1,5 @@
//Used to process objects. Fires once every second.
-//TODO: Implement fully when process scheduler dies
-/*
SUBSYSTEM_DEF(processing)
name = "Processing"
priority = FIRE_PRIORITY_PROCESS
@@ -16,7 +14,7 @@ SUBSYSTEM_DEF(processing)
..("[stat_tag]:[processing.len]")
/datum/controller/subsystem/processing/fire(resumed = 0)
- if (!resumed)
+ if(!resumed)
currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/current_run = currentrun
@@ -24,15 +22,16 @@ SUBSYSTEM_DEF(processing)
while(current_run.len)
var/datum/thing = current_run[current_run.len]
current_run.len--
- if(QDELETED(thing) || thing.process(wait) == PROCESS_KILL)
+ if(QDELETED(thing))
processing -= thing
- if (MC_TICK_CHECK)
+ else if(thing.process(wait) == PROCESS_KILL)
+ // fully stop so that a future START_PROCESSING will work
+ STOP_PROCESSING(src, thing)
+ if(MC_TICK_CHECK)
return
-*/
+
/datum/var/isprocessing = FALSE
-/*
+
/datum/proc/process()
set waitfor = 0
- STOP_PROCESSING(SSobj, src)
- return 0
-*/
\ No newline at end of file
+ return PROCESS_KILL
\ No newline at end of file
diff --git a/code/controllers/subsystem/radio.dm b/code/controllers/subsystem/radio.dm
new file mode 100644
index 00000000000..93b5152ee45
--- /dev/null
+++ b/code/controllers/subsystem/radio.dm
@@ -0,0 +1,99 @@
+SUBSYSTEM_DEF(radio)
+ name = "Radio"
+ flags = SS_NO_INIT | SS_NO_FIRE
+
+ var/list/radiochannels = list(
+ "Common" = PUB_FREQ,
+ "Science" = SCI_FREQ,
+ "Command" = COMM_FREQ,
+ "Medical" = MED_FREQ,
+ "Engineering" = ENG_FREQ,
+ "Security" = SEC_FREQ,
+ "Response Team" = ERT_FREQ,
+ "Special Ops" = DTH_FREQ,
+ "Syndicate" = SYND_FREQ,
+ "SyndTeam" = SYNDTEAM_FREQ,
+ "Supply" = SUP_FREQ,
+ "Service" = SRV_FREQ,
+ "AI Private" = AI_FREQ,
+ "Medical(I)" = MED_I_FREQ,
+ "Security(I)" = SEC_I_FREQ
+ )
+ var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ)
+ var/list/ANTAG_FREQS = list(SYND_FREQ, SYNDTEAM_FREQ)
+ var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ)
+ var/list/datum/radio_frequency/frequencies = list()
+
+// This is fucking disgusting and needs to die
+/datum/controller/subsystem/radio/proc/frequency_span_class(var/frequency)
+ // Antags!
+ if(frequency in ANTAG_FREQS)
+ return "syndradio"
+ // centcomm channels (deathsquid and ert)
+ if(frequency in CENT_FREQS)
+ return "centradio"
+ // This switch used to be a shit tonne of if statements. I am gonna find who made this and give them a kind talking to
+ switch(frequency)
+ if(COMM_FREQ)
+ return "comradio"
+ if(AI_FREQ)
+ return "airadio"
+ if(SEC_FREQ)
+ return "secradio"
+ if(ENG_FREQ)
+ return "engradio"
+ if(SCI_FREQ)
+ return "sciradio"
+ if(MED_FREQ)
+ return "medradio"
+ if(SUP_FREQ)
+ return "supradio"
+ if(SRV_FREQ)
+ return "srvradio"
+
+ // If the above switch somehow failed. And it needs the SSradio. part otherwise it fails to compile
+ if(frequency in DEPT_FREQS)
+ return "deptradio"
+
+ // If its none of the others
+ return "radio"
+
+
+/datum/controller/subsystem/radio/proc/add_object(obj/device as obj, var/new_frequency as num, var/filter = null as text|null)
+ var/f_text = num2text(new_frequency)
+ var/datum/radio_frequency/frequency = frequencies[f_text]
+
+ if(!frequency)
+ frequency = new
+ frequency.frequency = new_frequency
+ frequencies[f_text] = frequency
+
+ frequency.add_listener(device, filter)
+ return frequency
+
+/datum/controller/subsystem/radio/proc/remove_object(obj/device, old_frequency)
+ var/f_text = num2text(old_frequency)
+ var/datum/radio_frequency/frequency = frequencies[f_text]
+
+ if(frequency)
+ frequency.remove_listener(device)
+
+ if(frequency.devices.len == 0)
+ qdel(frequency)
+ frequencies -= f_text
+
+ return 1
+
+/datum/controller/subsystem/radio/proc/return_frequency(var/new_frequency as num)
+ var/f_text = num2text(new_frequency)
+ var/datum/radio_frequency/frequency = frequencies[f_text]
+
+ if(!frequency)
+ frequency = new
+ frequency.frequency = new_frequency
+ frequencies[f_text] = frequency
+
+ return frequency
+
+
+// ALL THE SHIT BELOW THIS LINE ISNT PART OF THE SUBSYSTEM AND REALLY NEEDS ITS OWN FILE
diff --git a/code/controllers/subsystem/shuttles.dm b/code/controllers/subsystem/shuttles.dm
index 30021df4fb1..a1ca9b5fdad 100644
--- a/code/controllers/subsystem/shuttles.dm
+++ b/code/controllers/subsystem/shuttles.dm
@@ -106,8 +106,8 @@ SUBSYSTEM_DEF(shuttle)
return
emergency = backup_shuttle
- if(world.time - round_start_time < config.shuttle_refuel_delay)
- to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.")
+ if(world.time - SSticker.round_start_time < config.shuttle_refuel_delay)
+ to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.")
return
switch(emergency.mode)
@@ -169,7 +169,7 @@ SUBSYSTEM_DEF(shuttle)
return
if(!emergency.canRecall)
return
- if(ticker.mode.name == "meteor")
+ if(SSticker.mode.name == "meteor")
return
if(seclevel2num(get_security_level()) >= SEC_LEVEL_RED)
if(emergency.timeLeft(1) < emergencyCallTime * 0.25)
diff --git a/code/game/gamemodes/gameticker.dm b/code/controllers/subsystem/ticker.dm
similarity index 73%
rename from code/game/gamemodes/gameticker.dm
rename to code/controllers/subsystem/ticker.dm
index 376668c16c4..4aa30657778 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -1,77 +1,125 @@
-var/global/datum/controller/gameticker/ticker
-var/round_start_time = 0
+SUBSYSTEM_DEF(ticker)
+ name = "Ticker"
+ init_order = INIT_ORDER_TICKER
-/datum/controller/gameticker
+ priority = FIRE_PRIORITY_TICKER
+ flags = SS_KEEP_TIMING
+ runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME
+
+ var/round_start_time = 0
var/const/restart_timeout = 600
- var/current_state = GAME_STATE_PREGAME
+ var/current_state = GAME_STATE_STARTUP
+ var/force_start = 0 // Do we want to force-start as soon as we can
var/force_ending = 0
-
var/hide_mode = 0 // leave here at 0 ! setup() will take care of it when needed for Secret mode -walter0o
var/datum/game_mode/mode = null
var/event_time = null
var/event = 0
-
var/login_music // music played in pregame lobby
-
var/list/datum/mind/minds = list()//The people in the game. Used for objective tracking.
-
var/Bible_icon_state // icon_state the chaplain has chosen for his bible
var/Bible_item_state // item_state the chaplain has chosen for his bible
var/Bible_name // name of the bible
var/Bible_deity_name
-
var/datum/cult_info/cultdat = null //here instead of cult for adminbus purposes
-
var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders
-
var/list/syndicate_coalition = list() // list of traitor-compatible factions
var/list/factions = list() // list of all factions
var/list/availablefactions = list() // list of factions with openings
-
- var/pregame_timeleft = 0
+ var/tipped = FALSE //Did we broadcast the tip of the day yet?
+ var/selected_tip // What will be the tip of the day?
+ var/pregame_timeleft // This is used for calculations
var/delay_end = 0 //if set to nonzero, the round will not restart on it's own
-
var/triai = 0//Global holder for Triumvirate
var/initialtpass = 0 //holder for inital autotransfer vote timer
-
var/obj/screen/cinematic = null //used for station explosion cinematic
-
var/round_end_announced = 0 // Spam Prevention. Announce round end only once.\
-
-/datum/controller/gameticker/proc/pregame()
+/datum/controller/subsystem/ticker/Initialize()
login_music = pick(\
'sound/music/thunderdome.ogg',\
'sound/music/space.ogg',\
'sound/music/title1.ogg',\
'sound/music/title2.ogg',\
'sound/music/title3.ogg',)
- do
- pregame_timeleft = config.pregame_timestart
- to_chat(world, "Welcome to the pre-game lobby!")
- to_chat(world, "Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds")
- while(current_state == GAME_STATE_PREGAME)
- sleep(10)
- if(going)
- pregame_timeleft--
- if(pregame_timeleft <= 0)
+ // Map name
+ if(using_map && using_map.name)
+ GLOB.map_name = "[using_map.name]"
+ else
+ GLOB.map_name = "Unknown"
+
+ // World name
+ if(config && config.server_name)
+ world.name = "[config.server_name]: [station_name()]"
+ else
+ world.name = station_name()
+
+ return ..()
+
+
+/datum/controller/subsystem/ticker/fire()
+ switch(current_state)
+ if(GAME_STATE_STARTUP)
+ // This is ran as soon as the MC starts firing, and should only run ONCE, unless startup fails
+ round_start_time = world.time + (config.pregame_timestart * 10)
+ to_chat(world, "Welcome to the pre-game lobby!")
+ to_chat(world, "Please, setup your character and select ready. Game will start in [config.pregame_timestart] seconds")
+ current_state = GAME_STATE_PREGAME
+ fire() // TG says this is a good idea
+ if(GAME_STATE_PREGAME)
+ // This is so we dont have sleeps in controllers, because that is a bad, bad thing
+ pregame_timeleft = max(0,round_start_time - world.time)
+
+ if(pregame_timeleft <= 600 && !tipped) // 60 seconds
+ send_tip_of_the_round()
+ tipped = TRUE
+
+ if(pregame_timeleft <= 0 || force_start)
current_state = GAME_STATE_SETTING_UP
Master.SetRunLevel(RUNLEVEL_SETUP)
- while(!setup())
+ if(GAME_STATE_SETTING_UP)
+ if(!setup()) // Setup failed
+ current_state = GAME_STATE_STARTUP
+ Master.SetRunLevel(RUNLEVEL_LOBBY)
+ if(GAME_STATE_PLAYING)
+ mode.process()
+ mode.process_job_tasks()
+ var/game_finished = SSshuttle.emergency.mode >= SHUTTLE_ENDGAME || mode.station_was_nuked
+ if(config.continuous_rounds)
+ mode.check_finished() // some modes contain var-changing code in here, so call even if we don't uses result
+ else
+ game_finished |= mode.check_finished()
+ if(game_finished)
+ current_state = GAME_STATE_FINISHED
+ if(GAME_STATE_FINISHED)
+ current_state = GAME_STATE_FINISHED
+ Master.SetRunLevel(RUNLEVEL_POSTGAME) // This shouldnt process more than once, but you never know
+ auto_toggle_ooc(1) // Turn it on
-/datum/controller/gameticker/proc/votetimer()
+ spawn(0)
+ declare_completion()
+
+ spawn(50)
+ if(mode.station_was_nuked)
+ world.Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke")
+ else
+ world.Reboot("Round ended.", "end_proper", "proper completion")
+
+
+/datum/controller/subsystem/ticker/proc/votetimer()
var/timerbuffer = 0
if(initialtpass == 0)
timerbuffer = config.vote_autotransfer_initial
else
timerbuffer = config.vote_autotransfer_interval
spawn(timerbuffer)
- vote.autotransfer()
+ SSvote.autotransfer()
initialtpass = 1
votetimer()
-/datum/controller/gameticker/proc/setup()
+
+/datum/controller/subsystem/ticker/proc/setup()
cultdat = setupcult()
//Create and announce mode
if(master_mode=="secret")
@@ -88,7 +136,7 @@ var/round_start_time = 0
var/datum/game_mode/M = config.pick_mode(secret_force_mode)
if(M.can_start())
src.mode = config.pick_mode(secret_force_mode)
- job_master.ResetOccupations()
+ SSjobs.ResetOccupations()
if(!src.mode)
src.mode = pickweight(runnable_modes)
if(src.mode)
@@ -100,7 +148,7 @@ var/round_start_time = 0
to_chat(world, "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby.")
mode = null
current_state = GAME_STATE_PREGAME
- job_master.ResetOccupations()
+ SSjobs.ResetOccupations()
Master.SetRunLevel(RUNLEVEL_LOBBY)
return 0
@@ -108,12 +156,12 @@ var/round_start_time = 0
src.mode.pre_pre_setup()
var/can_continue
can_continue = src.mode.pre_setup()//Setup special modes
- job_master.DivideOccupations() //Distribute jobs
+ SSjobs.DivideOccupations() //Distribute jobs
if(!can_continue)
qdel(mode)
current_state = GAME_STATE_PREGAME
to_chat(world, "Error setting up [master_mode]. Reverting to pre-game lobby.")
- job_master.ResetOccupations()
+ SSjobs.ResetOccupations()
Master.SetRunLevel(RUNLEVEL_LOBBY)
return 0
@@ -128,6 +176,7 @@ var/round_start_time = 0
src.mode.announce()
create_characters() //Create player characters and transfer them
+ populate_spawn_points()
collect_minds()
equip_characters()
data_core.manifest()
@@ -138,10 +187,15 @@ var/round_start_time = 0
//here to initialize the random events nicely at round start
setup_economy()
+ setupfactions()
//shuttle_controller.setup_shuttle_docks()
spawn(0)//Forking here so we dont have to wait for this to finish
+ if(!GLOB.syndicate_code_phrase)
+ GLOB.syndicate_code_phrase = generate_code_phrase()
+ if(!GLOB.syndicate_code_response)
+ GLOB.syndicate_code_response = generate_code_phrase()
mode.post_setup()
//Cleanup some stuff
for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
@@ -163,10 +217,10 @@ var/round_start_time = 0
to_chat(world, "Enjoy the game!")
world << sound('sound/AI/welcome.ogg')// Skie
- if(holiday_master.holidays)
+ if(SSholiday.holidays)
to_chat(world, "and...")
- for(var/holidayname in holiday_master.holidays)
- var/datum/holiday/holiday = holiday_master.holidays[holidayname]
+ for(var/holidayname in SSholiday.holidays)
+ var/datum/holiday/holiday = SSholiday.holidays[holidayname]
to_chat(world, "
[holiday.greet()]
")
spawn(0) // Forking dynamic room selection
@@ -223,14 +277,6 @@ var/round_start_time = 0
auto_toggle_ooc(0) // Turn it off
round_start_time = world.time
- /* DONE THROUGH PROCESS SCHEDULER
- supply_controller.process() //Start the supply shuttle regenerating points -- TLE
- master_controller.process() //Start master_controller.process()
- lighting_controller.process() //Start processing DynamicAreaLighting updates
- */
-
- processScheduler.start()
-
if(config.sql_enabled)
spawn(3000)
statistic_cycle() // Polls population totals regularly and stores them in an SQL DB
@@ -243,9 +289,7 @@ var/round_start_time = 0
return 1
- //Plus it provides an easy way to make cinematics for other events. Just use this as a template :)
-//Plus it provides an easy way to make cinematics for other events. Just use this as a template
-/datum/controller/gameticker/proc/station_explosion_cinematic(station_missed = 0, override = null)
+/datum/controller/subsystem/ticker/proc/station_explosion_cinematic(station_missed = 0, override = null)
if(cinematic)
return //already a cinematic in progress!
@@ -341,7 +385,7 @@ var/round_start_time = 0
-/datum/controller/gameticker/proc/create_characters()
+/datum/controller/subsystem/ticker/proc/create_characters()
for(var/mob/new_player/player in GLOB.player_list)
if(player.ready && player.mind)
if(player.mind.assigned_role == "AI")
@@ -355,67 +399,49 @@ var/round_start_time = 0
qdel(player)
-/datum/controller/gameticker/proc/collect_minds()
+/datum/controller/subsystem/ticker/proc/collect_minds()
for(var/mob/living/player in GLOB.player_list)
if(player.mind)
- ticker.minds += player.mind
+ SSticker.minds += player.mind
-/datum/controller/gameticker/proc/equip_characters()
+/datum/controller/subsystem/ticker/proc/equip_characters()
var/captainless=1
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player && player.mind && player.mind.assigned_role)
if(player.mind.assigned_role == "Captain")
captainless=0
if(player.mind.assigned_role != player.mind.special_role)
- job_master.AssignRank(player, player.mind.assigned_role, 0)
- job_master.EquipRank(player, player.mind.assigned_role, 0)
+ SSjobs.AssignRank(player, player.mind.assigned_role, 0)
+ SSjobs.EquipRank(player, player.mind.assigned_role, 0)
EquipCustomItems(player)
if(captainless)
for(var/mob/M in GLOB.player_list)
if(!istype(M,/mob/new_player))
to_chat(M, "Captainship not forced on anyone.")
-
-/datum/controller/gameticker/proc/process()
- if(current_state != GAME_STATE_PLAYING)
- return 0
-
- mode.process()
- mode.process_job_tasks()
-
- //emergency_shuttle.process() DONE THROUGH PROCESS SCHEDULER
-
- var/game_finished = SSshuttle.emergency.mode >= SHUTTLE_ENDGAME || mode.station_was_nuked
- if(config.continuous_rounds)
- mode.check_finished() // some modes contain var-changing code in here, so call even if we don't uses result
+/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
+ var/m
+ if(selected_tip)
+ m = selected_tip
else
- game_finished |= mode.check_finished()
+ var/list/randomtips = file2list("strings/tips.txt")
+ var/list/memetips = file2list("strings/sillytips.txt")
+ if(randomtips.len && prob(95))
+ m = pick(randomtips)
+ else if(memetips.len)
+ m = pick(memetips)
- if((!mode.explosion_in_progress && game_finished) || force_ending)
- current_state = GAME_STATE_FINISHED
- Master.SetRunLevel(RUNLEVEL_POSTGAME)
- auto_toggle_ooc(1) // Turn it on
- spawn
- declare_completion()
+ if(m)
+ to_chat(world, "Tip of the round: [html_encode(m)]")
- spawn(50)
- callHook("roundend")
-
- if(mode.station_was_nuked)
- world.Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke")
- else
- world.Reboot("Round ended.", "end_proper", "proper completion")
-
- return 1
-
-/datum/controller/gameticker/proc/getfactionbyname(var/name)
+/datum/controller/subsystem/ticker/proc/getfactionbyname(var/name)
for(var/datum/faction/F in factions)
if(F.name == name)
return F
-/datum/controller/gameticker/proc/declare_completion()
+/datum/controller/subsystem/ticker/proc/declare_completion()
nologevent = 1 //end of round murder and shenanigans are legal; there's no need to jam up attack logs past this point.
//Round statistics report
var/datum/station_state/end_state = new /datum/station_state()
@@ -460,9 +486,9 @@ var/round_start_time = 0
if(dronecount)
to_chat(world, "There [dronecount>1 ? "were" : "was"] [dronecount] industrious maintenance [dronecount>1 ? "drones" : "drone"] this round.")
- if(ticker.mode.eventmiscs.len)
+ if(mode.eventmiscs.len)
var/emobtext = ""
- for(var/datum/mind/eventmind in ticker.mode.eventmiscs)
+ for(var/datum/mind/eventmind in mode.eventmiscs)
emobtext += printeventplayer(eventmind)
emobtext += " "
emobtext += printobjectives(eventmind)
@@ -483,9 +509,18 @@ var/round_start_time = 0
mode.declare_station_goal_completion()
//Ask the event manager to print round end information
- event_manager.RoundEnd()
+ SSevents.RoundEnd()
+
+ // Add AntagHUD to everyone, see who was really evil the whole time!
+ for(var/datum/atom_hud/antag/H in huds)
+ for(var/m in GLOB.player_list)
+ var/mob/M = m
+ H.add_hud_to(M)
return 1
-/datum/controller/gameticker/proc/HasRoundStarted()
+/datum/controller/subsystem/ticker/proc/HasRoundStarted()
return current_state >= GAME_STATE_PLAYING
+
+/datum/controller/subsystem/ticker/proc/IsRoundInProgress()
+ return current_state == GAME_STATE_PLAYING
\ No newline at end of file
diff --git a/code/controllers/subsystem/tickets/mentor_tickets.dm b/code/controllers/subsystem/tickets/mentor_tickets.dm
new file mode 100644
index 00000000000..d8bae77840c
--- /dev/null
+++ b/code/controllers/subsystem/tickets/mentor_tickets.dm
@@ -0,0 +1,21 @@
+GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets)
+
+/datum/controller/subsystem/tickets/mentor_tickets/New()
+ NEW_SS_GLOBAL(SSmentor_tickets);
+ PreInit();
+
+/datum/controller/subsystem/tickets/mentor_tickets
+ name = "Mentor Tickets"
+ ticket_system_name = "Mentor Tickets"
+ ticket_name = "Mentor Ticket"
+ span_class = "mentorhelp"
+ close_rights = R_MENTOR | R_ADMIN
+
+/datum/controller/subsystem/tickets/mentor_tickets/message_staff(var/msg)
+ message_mentorTicket(msg)
+
+/datum/controller/subsystem/tickets/mentor_tickets/Initialize()
+ close_messages = list("- [ticket_name] Closed -",
+ "Please try to be as descriptive as possible in mentor helps. Mentors do not know the full situation you're in and need more information to give you a helpful response.",
+ "Your [ticket_name] has now been closed.")
+ return ..()
diff --git a/code/controllers/subsystem/tickets.dm b/code/controllers/subsystem/tickets/tickets.dm
similarity index 55%
rename from code/controllers/subsystem/tickets.dm
rename to code/controllers/subsystem/tickets/tickets.dm
index b8b1f8410a0..1b1735b34c1 100644
--- a/code/controllers/subsystem/tickets.dm
+++ b/code/controllers/subsystem/tickets/tickets.dm
@@ -1,28 +1,36 @@
//Defines
//Deciseconds until ticket becomes stale if unanswered. Alerts admins.
-#define ADMIN_TICKET_TIMEOUT 6000 // 10 minutes
+#define TICKET_TIMEOUT 6000 // 10 minutes
//Decisecions before the user is allowed to open another ticket while their existing one is open.
-#define ADMIN_TICKET_DUPLICATE_COOLDOWN 3000 // 5 minutes
+#define TICKET_DUPLICATE_COOLDOWN 3000 // 5 minutes
//Status defines
-#define ADMIN_TICKET_OPEN 1
-#define ADMIN_TICKET_CLOSED 2
-#define ADMIN_TICKET_RESOLVED 3
-#define ADMIN_TICKET_STALE 4
+#define TICKET_OPEN 1
+#define TICKET_CLOSED 2
+#define TICKET_RESOLVED 3
+#define TICKET_STALE 4
SUBSYSTEM_DEF(tickets)
- name = "Tickets"
+ name = "Admin Tickets"
+ var/span_class = "adminticket"
+ var/ticket_system_name = "Admin Tickets"
+ var/ticket_name = "Admin Ticket"
+ var/close_rights = R_ADMIN
+ var/list/close_messages
init_order = INIT_ORDER_TICKETS
wait = 300
priority = FIRE_PRIORITY_TICKETS
-
+
flags = SS_BACKGROUND
-
+
var/list/allTickets
var/ticketCounter = 1
/datum/controller/subsystem/tickets/Initialize()
+ close_messages = list("- [ticket_name] Rejected! -",
+ "Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.",
+ "Your [ticket_name] has now been closed.")
LAZYINITLIST(allTickets)
return ..()
@@ -32,7 +40,7 @@ SUBSYSTEM_DEF(tickets)
var/report
for(var/num in stales)
report += "[num], "
- message_adminTicket("Tickets [report] have been open for over [ADMIN_TICKET_TIMEOUT / 600] minutes. Changing status to stale.")
+ message_staff("Tickets [report] have been open for over [TICKET_TIMEOUT / 600] minutes. Changing status to stale.")
/datum/controller/subsystem/tickets/stat_entry()
..("Tickets: [LAZYLEN(allTickets)]")
@@ -40,10 +48,10 @@ SUBSYSTEM_DEF(tickets)
/datum/controller/subsystem/tickets/proc/checkStaleness()
var/stales = list()
for(var/T in allTickets)
- var/datum/admin_ticket/ticket = T
- if(!(ticket.ticketState == ADMIN_TICKET_OPEN))
+ var/datum/ticket/ticket = T
+ if(!(ticket.ticketState == TICKET_OPEN))
continue
- if(world.time > ticket.timeUntilStale && (!ticket.lastAdminResponse || !ticket.adminAssigned))
+ if(world.time > ticket.timeUntilStale && (!ticket.lastStaffResponse || !ticket.staffAssigned))
var/id = ticket.makeStale()
stales += id
return stales
@@ -60,7 +68,7 @@ SUBSYSTEM_DEF(tickets)
/datum/controller/subsystem/tickets/proc/resolveAllOpenTickets() // Resolve all open tickets
for(var/i in allTickets)
- var/datum/admin_ticket/T = i
+ var/datum/ticket/T = i
resolveTicket(T.ticketNum)
//Open a new ticket and populate details then add to the list of open tickets
@@ -69,56 +77,57 @@ SUBSYSTEM_DEF(tickets)
return
//Check if the user has an open ticket already within the cooldown period, if so we don't create a new one and re-set the cooldown period
- var/datum/admin_ticket/existingTicket = checkForOpenTicket(C)
+ var/datum/ticket/existingTicket = checkForOpenTicket(C)
if(existingTicket)
existingTicket.setCooldownPeriod()
- to_chat(C.mob, "Your ticket #[existingTicket.ticketNum] remains open! Visit \"My tickets\" under the Admin Tab to view it.")
+ to_chat(C.mob, "Your [ticket_name] #[existingTicket.ticketNum] remains open! Visit \"My tickets\" under the Admin Tab to view it.")
return
if(!title)
title = passedContent
- var/datum/admin_ticket/T = new(title, passedContent)
+ var/datum/ticket/T = new(title, passedContent, getTicketCounterAndInc())
+ allTickets += T
T.clientName = C
T.locationSent = C.mob.loc.name
T.mobControlled = C.mob
//Inform the user that they have opened a ticket
- to_chat(C, "You have opened admin ticket number #[(SStickets.getTicketCounter() - 1)]! Please be patient and we will help you soon!")
+ to_chat(C, "You have opened [ticket_name] number #[(getTicketCounter() - 1)]! Please be patient and we will help you soon!")
//Set ticket state with key N to open
/datum/controller/subsystem/tickets/proc/openTicket(N)
- var/datum/admin_ticket/T = SStickets.allTickets[N]
- if(T.ticketState != ADMIN_TICKET_OPEN)
- T.ticketState = ADMIN_TICKET_OPEN
+ var/datum/ticket/T = allTickets[N]
+ if(T.ticketState != TICKET_OPEN)
+ T.ticketState = TICKET_OPEN
return TRUE
//Set ticket state with key N to resolved
/datum/controller/subsystem/tickets/proc/resolveTicket(N)
- var/datum/admin_ticket/T = SStickets.allTickets[N]
- if(T.ticketState != ADMIN_TICKET_RESOLVED)
- T.ticketState = ADMIN_TICKET_RESOLVED
+ var/datum/ticket/T = allTickets[N]
+ if(T.ticketState != TICKET_RESOLVED)
+ T.ticketState = TICKET_RESOLVED
return TRUE
//Set ticket state with key N to closed
/datum/controller/subsystem/tickets/proc/closeTicket(N)
- var/datum/admin_ticket/T = SStickets.allTickets[N]
- if(T.ticketState != ADMIN_TICKET_CLOSED)
- T.ticketState = ADMIN_TICKET_CLOSED
+ var/datum/ticket/T = allTickets[N]
+ if(T.ticketState != TICKET_CLOSED)
+ T.ticketState = TICKET_CLOSED
return TRUE
//Check if the user already has a ticket open and within the cooldown period.
/datum/controller/subsystem/tickets/proc/checkForOpenTicket(client/C)
- for(var/datum/admin_ticket/T in allTickets)
- if(T.clientName == C && T.ticketState == ADMIN_TICKET_OPEN && (T.ticketCooldown > world.time))
+ for(var/datum/ticket/T in allTickets)
+ if(T.clientName == C && T.ticketState == TICKET_OPEN && (T.ticketCooldown > world.time))
return T
return FALSE
//Check if the user has ANY ticket not resolved or closed.
/datum/controller/subsystem/tickets/proc/checkForTicket(client/C)
var/list/tickets = list()
- for(var/datum/admin_ticket/T in allTickets)
- if(T.clientName == C && (T.ticketState == ADMIN_TICKET_OPEN || T.ticketState == ADMIN_TICKET_STALE))
+ for(var/datum/ticket/T in allTickets)
+ if(T.clientName == C && (T.ticketState == TICKET_OPEN || T.ticketState == TICKET_STALE))
tickets += T
if(tickets.len)
return tickets
@@ -126,78 +135,79 @@ SUBSYSTEM_DEF(tickets)
//return the client of a ticket number
/datum/controller/subsystem/tickets/proc/returnClient(N)
- var/datum/admin_ticket/T = SStickets.allTickets[N]
+ var/datum/ticket/T = allTickets[N]
return T.clientName
-/datum/controller/subsystem/tickets/proc/assignAdminToTicket(client/C, var/N)
- var/datum/admin_ticket/T = SStickets.allTickets[N]
- T.assignAdmin(C)
+/datum/controller/subsystem/tickets/proc/assignStaffToTicket(client/C, N)
+ var/datum/ticket/T = allTickets[N]
+ if(T.staffAssigned != null && T.staffAssigned != C && alert("Ticket is already assigned to [T.staffAssigned.ckey]. Are you sure you want to take it?","Take ticket","No","Yes") != "Yes")
+ return FALSE
+ T.assignStaff(C)
return TRUE
-//Single admin ticket
+//Single staff ticket
-/datum/admin_ticket
+/datum/ticket
var/ticketNum // Ticket number
var/clientName // Client which opened the ticket
var/timeOpened // Time the ticket was opened
var/title //The initial message with links
- var/list/content // content of the admin help
- var/lastAdminResponse // Last admin who responded
- var/lastResponseTime // When the admin last responded
+ var/list/content // content of the staff help
+ var/lastStaffResponse // Last staff member who responded
+ var/lastResponseTime // When the staff last responded
var/locationSent // Location the player was when they send the ticket
var/mobControlled // Mob they were controlling
var/ticketState // State of the ticket, open, closed, resolved etc
var/timeUntilStale // When the ticket goes stale
var/ticketCooldown // Cooldown before allowing the user to open another ticket.
- var/adminAssigned // Admin who has assigned themselves to this ticket
+ var/client/staffAssigned // Staff member who has assigned themselves to this ticket
-/datum/admin_ticket/New(tit, cont)
+/datum/ticket/New(tit, cont, num)
title = tit
content = list()
content += cont
timeOpened = worldtime2text()
- timeUntilStale = world.time + ADMIN_TICKET_TIMEOUT
+ timeUntilStale = world.time + TICKET_TIMEOUT
setCooldownPeriod()
- ticketNum = SStickets.getTicketCounterAndInc()
- ticketState = ADMIN_TICKET_OPEN
- SStickets.allTickets += src
+ ticketNum = num
+ ticketState = TICKET_OPEN
//Set the cooldown period for the ticket. The time when it's created plus the defined cooldown time.
-/datum/admin_ticket/proc/setCooldownPeriod()
- ticketCooldown = world.time + ADMIN_TICKET_DUPLICATE_COOLDOWN
+/datum/ticket/proc/setCooldownPeriod()
+ ticketCooldown = world.time + TICKET_DUPLICATE_COOLDOWN
-//Set the last admin who responded as the client passed as an arguement.
-/datum/admin_ticket/proc/setLastAdminResponse(client/C)
- lastAdminResponse = C
+//Set the last staff who responded as the client passed as an arguement.
+/datum/ticket/proc/setLastStaffResponse(client/C)
+ lastStaffResponse = C
lastResponseTime = worldtime2text()
//Return the ticket state as a colour coded text string.
-/datum/admin_ticket/proc/state2text()
+/datum/ticket/proc/state2text()
switch(ticketState)
- if(ADMIN_TICKET_OPEN)
+ if(TICKET_OPEN)
return "OPEN"
- if(ADMIN_TICKET_RESOLVED)
+ if(TICKET_RESOLVED)
return "RESOLVED"
- if(ADMIN_TICKET_CLOSED)
+ if(TICKET_CLOSED)
return "CLOSED"
- if(ADMIN_TICKET_STALE)
+ if(TICKET_STALE)
return "STALE"
-//Assign the client passed to var/adminAsssigned
-/datum/admin_ticket/proc/assignAdmin(client/C)
+//Assign the client passed to var/staffAsssigned
+/datum/ticket/proc/assignStaff(client/C)
if(!C)
return
- adminAssigned = C
+ staffAssigned = C
return TRUE
-/datum/admin_ticket/proc/addResponse(client/C, msg)
+/datum/ticket/proc/addResponse(client/C, msg)
if(C.holder)
- setLastAdminResponse(C)
+ setLastStaffResponse(C)
msg = "[C]: [msg]"
content += msg
-/datum/admin_ticket/proc/makeStale()
- ticketState = ADMIN_TICKET_STALE
+/datum/ticket/proc/makeStale()
+ ticketState = TICKET_STALE
return ticketNum
/*
@@ -206,7 +216,7 @@ UI STUFF
*/
-/datum/controller/subsystem/tickets/proc/returnUI(tab = ADMIN_TICKET_OPEN)
+/datum/controller/subsystem/tickets/proc/returnUI(tab = TICKET_OPEN)
set name = "Open Ticket Interface"
set category = "Tickets"
@@ -214,36 +224,36 @@ UI STUFF
var/trStyle = "border-top:2px solid; border-bottom:2px solid; padding-top: 5px; padding-bottom: 5px;"
var/tdStyleleft = "border-top:2px solid; border-bottom:2px solid; width:150px; text-align:center;"
var/tdStyle = "border-top:2px solid; border-bottom:2px solid;"
- var/datum/admin_ticket/ticket
+ var/datum/ticket/ticket
var/dat
dat += ""
- dat += "
"
- if(!T.adminAssigned)
- dat += "No admin assigned to this ticket - Take Ticket "
+ if(!T.staffAssigned)
+ dat += "No staff member assigned to this [ticket_name] - Take Ticket "
else
- dat += "[T.adminAssigned] is assigned to this Ticket. - Take Ticket "
+ dat += "[T.staffAssigned] is assigned to this Ticket. - Take Ticket "
- if(T.lastAdminResponse)
- dat += "Last Admin Response: [T.lastAdminResponse] at [T.lastResponseTime]"
+ if(T.lastStaffResponse)
+ dat += "Last Staff response Response: [T.lastStaffResponse] at [T.lastResponseTime]"
else
- dat +="No Admin Response"
+ dat +="No Staff Response"
dat += "
"
- for(var/datum/admin_ticket/T in tickets)
+ for(var/datum/ticket/T in tickets)
dat += "
Ticket #[T.ticketNum]
"
for(var/i = 1, i <= T.content.len, i++)
dat += "
[T.content[i]]
"
dat += "
"
- var/datum/browser/popup = new(user, "userticketsdetail", "Tickets", 1000, 600)
+ var/datum/browser/popup = new(user, "[ticket_system_name]userticketsdetail", ticket_system_name, 1000, 600)
popup.set_content(dat)
popup.open()
@@ -326,6 +336,10 @@ UI STUFF
to_chat(target, text)
return TRUE
+//Sends a message to the designated staff
+/datum/controller/subsystem/tickets/proc/message_staff(var/msg, var/alt = FALSE)
+ message_adminTicket(msg, alt)
+
/datum/controller/subsystem/tickets/Topic(href, href_list)
if(href_list["refresh"])
@@ -338,13 +352,13 @@ UI STUFF
return
if(href_list["showopen"])
- showUI(usr, ADMIN_TICKET_OPEN)
+ showUI(usr, TICKET_OPEN)
return
if(href_list["showresolved"])
- showUI(usr, ADMIN_TICKET_RESOLVED)
+ showUI(usr, TICKET_RESOLVED)
return
if(href_list["showclosed"])
- showUI(usr, ADMIN_TICKET_CLOSED)
+ showUI(usr, TICKET_CLOSED)
return
if(href_list["details"])
@@ -354,40 +368,46 @@ UI STUFF
if(href_list["resolve"])
var/indexNum = text2num(href_list["resolve"])
- if(SStickets.resolveTicket(indexNum))
- message_adminTicket("[usr.client] / ([usr]) resolved admin ticket number [indexNum]")
- to_chat_safe(returnClient(indexNum), "Your admin ticket has now been resolved.")
+ if(resolveTicket(indexNum))
+ message_staff("[usr.client] / ([usr]) resolved [ticket_name] number [indexNum]")
+ to_chat_safe(returnClient(indexNum), "Your [ticket_name] has now been resolved.")
showUI(usr)
if(href_list["detailresolve"])
var/indexNum = text2num(href_list["detailresolve"])
- if(SStickets.resolveTicket(indexNum))
- message_adminTicket("[usr.client] / ([usr]) resolved admin ticket number [indexNum]")
- to_chat_safe(returnClient(indexNum), "Your admin ticket has now been resolved.")
+ if(resolveTicket(indexNum))
+ message_staff("[usr.client] / ([usr]) resolved [ticket_name] number [indexNum]")
+ to_chat_safe(returnClient(indexNum), "Your [ticket_name] has now been resolved.")
showDetailUI(usr, indexNum)
if(href_list["detailclose"])
var/indexNum = text2num(href_list["detailclose"])
+ if(!check_rights(close_rights))
+ to_chat(usr, "Not enough rights to close this ticket.")
+ return
if(alert("Are you sure? This will send a negative message.",,"Yes","No") != "Yes")
return
- if(SStickets.closeTicket(indexNum))
- message_adminTicket("[usr.client] / ([usr]) closed admin ticket number [indexNum]")
- to_chat_safe(returnClient(indexNum), list(
- "- AdminHelp Rejected! -",
- "Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.",
- "Your ticket has now been closed."
- ))
+ if(closeTicket(indexNum))
+ message_staff("[usr.client] / ([usr]) closed [ticket_name] number [indexNum]")
+ to_chat_safe(returnClient(indexNum), close_messages)
showDetailUI(usr, indexNum)
+
if(href_list["detailreopen"])
var/indexNum = text2num(href_list["detailreopen"])
- if(SStickets.openTicket(indexNum))
- message_adminTicket("[usr.client] / ([usr]) re-opened admin ticket number [indexNum]")
+ if(openTicket(indexNum))
+ message_staff("[usr.client] / ([usr]) re-opened [ticket_name] number [indexNum]")
showDetailUI(usr, indexNum)
- if(href_list["assignadmin"])
- var/indexNum = text2num(href_list["assignadmin"])
- if(SStickets.assignAdminToTicket(usr.client, indexNum))
- message_adminTicket("[usr.client] / ([usr]) has taken ticket number [indexNum]")
- to_chat_safe(returnClient(indexNum), "Your ticket is being handled by [usr.client].")
+ if(href_list["assignstaff"])
+ var/indexNum = text2num(href_list["assignstaff"])
+ takeTicket(indexNum)
showDetailUI(usr, indexNum)
+
+/datum/controller/subsystem/tickets/proc/takeTicket(var/index)
+ if(assignStaffToTicket(usr.client, index))
+ if(span_class == "mentorhelp")
+ message_staff("[usr.client] / ([usr]) has taken [ticket_name] number [index]")
+ else
+ message_staff("[usr.client] / ([usr]) has taken [ticket_name] number [index]", TRUE)
+ to_chat_safe(returnClient(index), "Your [ticket_name] is being handled by [usr.client].")
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index 3e7285a79bf..1b2938fc70f 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -71,7 +71,6 @@ SUBSYSTEM_DEF(timer)
for(var/I in second_queue)
log_world(get_timer_debug_string(I))
- var/cut_start_index = 1
var/next_clienttime_timer_index = 0
var/len = length(clienttime_timers)
@@ -94,14 +93,14 @@ SUBSYSTEM_DEF(timer)
if(ctime_timer.flags & TIMER_LOOP)
ctime_timer.spent = 0
- clienttime_timers.Insert(ctime_timer, 1)
- cut_start_index++
+ ctime_timer.timeToRun = REALTIMEOFDAY + ctime_timer.wait
+ BINARY_INSERT(ctime_timer, clienttime_timers, datum/timedevent, timeToRun)
else
qdel(ctime_timer)
if(next_clienttime_timer_index)
- clienttime_timers.Cut(cut_start_index,next_clienttime_timer_index+1)
+ clienttime_timers.Cut(1, next_clienttime_timer_index+1)
if(MC_TICK_CHECK)
return
@@ -269,7 +268,7 @@ SUBSYSTEM_DEF(timer)
var/new_bucket_count
var/i = 1
for(i in 1 to length(alltimers))
- var/datum/timedevent/timer = alltimers[1]
+ var/datum/timedevent/timer = alltimers[i]
if(!timer)
continue
@@ -411,10 +410,8 @@ SUBSYSTEM_DEF(timer)
prev.next = next
next.prev = prev
else
- if(prev)
- prev.next = null
- if(next)
- next.prev = null
+ prev?.next = null
+ next?.prev = null
prev = next = null
/datum/timedevent/proc/bucketJoin()
@@ -521,4 +518,4 @@ SUBSYSTEM_DEF(timer)
#undef BUCKET_LEN
#undef BUCKET_POS
#undef TIMER_MAX
-#undef TIMER_ID_MAX
+#undef TIMER_ID_MAX
\ No newline at end of file
diff --git a/code/controllers/voting.dm b/code/controllers/subsystem/vote.dm
similarity index 85%
rename from code/controllers/voting.dm
rename to code/controllers/subsystem/vote.dm
index e7ee6f743ca..27d499254a1 100644
--- a/code/controllers/voting.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -1,8 +1,9 @@
-var/datum/controller/vote/vote = new()
+SUBSYSTEM_DEF(vote)
+ name = "Vote"
+ wait = 10
+ flags = SS_KEEP_TIMING|SS_NO_INIT
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
-var/global/list/round_voters = list() //Keeps track of the individuals voting for a given round, for use in forcedrafting.
-
-/datum/controller/vote
var/initiator = null
var/started_time = null
var/time_remaining = 0
@@ -12,26 +13,13 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
var/list/voted = list()
var/list/voting = list()
var/list/current_votes = list()
+ var/list/round_voters = list()
var/auto_muted = 0
-/datum/controller/vote/New()
- if(vote != src)
- if(istype(vote))
- qdel(vote)
- vote = src
- spawn(0)
- while(!QDELETED(src))
- try
- while(!QDELETED(src))
- sleep(10)
- process()
- catch(var/exception/e)
- log_runtime(e, src, "Caught in vote controller")
-
-/datum/controller/vote/proc/process()
+/datum/controller/subsystem/vote/fire()
if(mode)
// No more change mode votes after the game has started.
- if(mode == "gamemode" && ticker.current_state >= GAME_STATE_SETTING_UP)
+ if(mode == "gamemode" && SSticker.current_state >= GAME_STATE_SETTING_UP)
to_chat(world, "Voting aborted due to game start.")
reset()
return
@@ -51,10 +39,10 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
update_panel(C)
CHECK_TICK
-/datum/controller/vote/proc/autotransfer()
+/datum/controller/subsystem/vote/proc/autotransfer()
initiate_vote("crew_transfer","the server")
-/datum/controller/vote/proc/reset()
+/datum/controller/subsystem/vote/proc/reset()
initiator = null
time_remaining = 0
mode = null
@@ -72,7 +60,7 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
message_admins("OOC has been toggled on automatically.")
-/datum/controller/vote/proc/get_result()
+/datum/controller/subsystem/vote/proc/get_result()
var/greatest_votes = 0
var/total_votes = 0
var/list/sorted_choices = list()
@@ -132,12 +120,12 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
. += option
return .
-/datum/controller/vote/proc/announce_result()
+/datum/controller/subsystem/vote/proc/announce_result()
var/list/winners = get_result()
var/text
if(winners.len > 0)
if(winners.len > 1)
- if(mode != "gamemode" || ticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
+ if(mode != "gamemode" || SSticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
text = "Vote Tied Between:\n"
for(var/option in winners)
text += "\t[option]\n"
@@ -146,7 +134,7 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
for(var/key in current_votes)
if(choices[current_votes[key]] == .)
round_voters += key // Keep track of who voted for the winning round.
- if(mode == "gamemode" && (. == "extended" || ticker.hide_mode == 0)) // Announce Extended gamemode, but not other gamemodes
+ if(mode == "gamemode" && (. == "extended" || SSticker.hide_mode == 0)) // Announce Extended gamemode, but not other gamemodes
text += "Vote Result: [.] ([choices[.]] vote\s)"
else
if(mode == "custom")
@@ -167,7 +155,7 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
to_chat(world, "[text]")
return .
-/datum/controller/vote/proc/result()
+/datum/controller/subsystem/vote/proc/result()
. = announce_result()
var/restart = 0
if(.)
@@ -178,7 +166,7 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
if("gamemode")
if(master_mode != .)
world.save_mode(.)
- if(ticker && ticker.mode)
+ if(SSticker && SSticker.mode)
restart = 1
else
master_mode = .
@@ -195,7 +183,7 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
return .
-/datum/controller/vote/proc/submit_vote(var/ckey, var/vote)
+/datum/controller/subsystem/vote/proc/submit_vote(var/ckey, var/vote)
if(mode)
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
return 0
@@ -208,7 +196,7 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
return vote
return 0
-/datum/controller/vote/proc/initiate_vote(var/vote_type, var/initiator_key)
+/datum/controller/subsystem/vote/proc/initiate_vote(var/vote_type, var/initiator_key)
if(!mode)
if(started_time != null && !check_rights(R_ADMIN))
var/next_allowed_time = (started_time + config.vote_delay)
@@ -220,17 +208,17 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
if("restart")
choices.Add("Restart Round","Continue Playing")
if("gamemode")
- if(ticker.current_state >= 2)
+ if(SSticker.current_state >= 2)
return 0
choices.Add(config.votable_modes)
if("crew_transfer")
if(check_rights(R_ADMIN|R_MOD))
- if(ticker.current_state <= 2)
+ if(SSticker.current_state <= 2)
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
else
- if(ticker.current_state <= 2)
+ if(SSticker.current_state <= 2)
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
@@ -291,7 +279,7 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
return 1
return 0
-/datum/controller/vote/proc/browse_to(var/client/C)
+/datum/controller/subsystem/vote/proc/browse_to(var/client/C)
if(!C)
return
var/admin = check_rights(R_ADMIN, 0, user = C.mob)
@@ -341,10 +329,10 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
popup.set_content(dat)
popup.open()
-/datum/controller/vote/proc/update_panel(var/client/C)
+/datum/controller/subsystem/vote/proc/update_panel(var/client/C)
C << output(url_encode(vote_html(C)), "vote.browser:update_vote_div")
-/datum/controller/vote/proc/vote_html(var/client/C)
+/datum/controller/subsystem/vote/proc/vote_html(var/client/C)
. = ""
if(question)
. += "
Vote: '[question]'
"
@@ -363,7 +351,7 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
. += ""
-/datum/controller/vote/Topic(href,href_list[],hsrc)
+/datum/controller/subsystem/vote/Topic(href,href_list[],hsrc)
if(!usr || !usr.client)
return //not necessary but meh...just in-case somebody does something stupid
var/admin = check_rights(R_ADMIN,0)
@@ -409,5 +397,5 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
set category = "OOC"
set name = "Vote"
- if(vote)
- vote.browse_to(client)
+ if(SSvote)
+ SSvote.browse_to(client)
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index 3619fca430f..4b898df0f11 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -45,7 +45,7 @@ SUBSYSTEM_DEF(weather)
for(var/z in levels_by_trait(target_trait))
LAZYINITLIST(eligible_zlevels["[z]"])
eligible_zlevels["[z]"][W] = probability
- ..()
+ return ..()
/datum/controller/subsystem/weather/proc/run_weather(datum/weather/weather_datum_type, z_levels)
if(istext(weather_datum_type))
diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm
index 88c4f9f4ea9..f694b6d2e75 100644
--- a/code/controllers/verbs.dm
+++ b/code/controllers/verbs.dm
@@ -2,57 +2,52 @@
//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done
-/client/proc/restart_controller(controller in list("Master","Failsafe"))
+/client/proc/restart_controller(controller in list("Master", "Failsafe"))
set category = "Debug"
set name = "Restart Controller"
set desc = "Restart one of the various periodic loop controllers for the game (be careful!)"
- if(!holder) return
- usr = null
- src = null
+ if(!holder)
+ return
switch(controller)
+ if("Master")
+ Recreate_MC()
+ feedback_add_details("admin_verb","RMaster")
if("Failsafe")
new /datum/controller/failsafe()
feedback_add_details("admin_verb","RFailsafe")
- message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
- return
-/client/proc/debug_controller(controller in list("Master",
- "failsafe","Scheduler","StonedMaster","Ticker","Air","Jobs","Sun","Radio","Configuration","pAI",
- "Cameras","Garbage", "Transfer Controller","Event","Alarm","Nano","Vote","Fires",
- "Mob","NPC AI","Shuttle","Timer","Weather","Space","Mob Hunt Server"))
+ message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
+
+/client/proc/debug_controller(controller in list("failsafe", "Master", "Ticker", "Air", "Jobs", "Sun", "Radio", "Configuration", "pAI",
+ "Cameras", "Garbage", "Event", "Alarm", "Nano", "Vote", "Fires",
+ "Mob", "NPC Pool", "Shuttle", "Timer", "Weather", "Space", "Mob Hunt Server","Input"))
set category = "Debug"
set name = "Debug Controller"
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
if(!holder) return
switch(controller)
- if("Master")
- debug_variables(master_controller)
- feedback_add_details("admin_verb","DMC")
if("failsafe")
debug_variables(Failsafe)
feedback_add_details("admin_verb", "dfailsafe")
- if("Scheduler")
- debug_variables(processScheduler)
- feedback_add_details("admin_verb","DprocessScheduler")
- if("StonedMaster")
+ if("Master")
debug_variables(Master)
feedback_add_details("admin_verb","Dsmc")
if("Ticker")
- debug_variables(ticker)
+ debug_variables(SSticker)
feedback_add_details("admin_verb","DTicker")
if("Air")
debug_variables(SSair)
feedback_add_details("admin_verb","DAir")
if("Jobs")
- debug_variables(job_master)
+ debug_variables(SSjobs)
feedback_add_details("admin_verb","DJobs")
if("Sun")
debug_variables(SSsun)
feedback_add_details("admin_verb","DSun")
if("Radio")
- debug_variables(radio_controller)
+ debug_variables(SSradio)
feedback_add_details("admin_verb","DRadio")
if("Configuration")
debug_variables(config)
@@ -63,20 +58,20 @@
if("Cameras")
debug_variables(cameranet)
feedback_add_details("admin_verb","DCameras")
- if("Event")
- debug_variables(event_manager)
- feedback_add_details("admin_verb","DEvent")
- if("Alarm")
- debug_variables(alarm_manager)
- feedback_add_details("admin_verb", "DAlarm")
if("Garbage")
debug_variables(SSgarbage)
feedback_add_details("admin_verb","DGarbage")
+ if("Event")
+ debug_variables(SSevents)
+ feedback_add_details("admin_verb","DEvent")
+ if("Alarm")
+ debug_variables(SSalarms)
+ feedback_add_details("admin_verb", "DAlarm")
if("Nano")
debug_variables(SSnanoui)
feedback_add_details("admin_verb","DNano")
if("Vote")
- debug_variables(vote)
+ debug_variables(SSvote)
feedback_add_details("admin_verb","DVote")
if("Fires")
debug_variables(SSfires)
@@ -84,9 +79,9 @@
if("Mob")
debug_variables(SSmobs)
feedback_add_details("admin_verb","DMob")
- if("NPC AI")
- debug_variables(SSnpcai)
- feedback_add_details("admin_verb","DNPCAI")
+ if("NPC Pool")
+ debug_variables(SSnpcpool)
+ feedback_add_details("admin_verb","DNPCPool")
if("Shuttle")
debug_variables(SSshuttle)
feedback_add_details("admin_verb","DShuttle")
@@ -102,6 +97,8 @@
if("Mob Hunt Server")
debug_variables(SSmob_hunt)
feedback_add_details("admin_verb","DMobHuntServer")
+ if("Input")
+ debug_variables(SSinput)
+ feedback_add_details("admin_verb","DInput")
- message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
- return
+ message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
\ No newline at end of file
diff --git a/code/datums/action.dm b/code/datums/action.dm
index 31b62e868dc..a5f63cc6fe4 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -23,6 +23,8 @@
button = new
button.linked_action = src
button.name = name
+ if(desc)
+ button.desc = desc
/datum/action/Destroy()
if(owner)
@@ -41,6 +43,7 @@
M.actions += src
if(M.client)
M.client.screen += button
+ button.locked = TRUE
M.update_action_buttons()
/datum/action/proc/Remove(mob/M)
@@ -50,6 +53,7 @@
if(M.client)
M.client.screen -= button
button.moved = FALSE //so the button appears in its normal position when given to another owner.
+ button.locked = FALSE
M.actions -= src
M.update_action_buttons()
@@ -82,6 +86,7 @@
if(button)
button.icon = button_icon
button.icon_state = background_icon_state
+ button.desc = desc
ApplyIcon(button)
@@ -104,6 +109,7 @@
/datum/action/item_action
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
var/use_itemicon = TRUE
+
/datum/action/item_action/New(Target, custom_icon, custom_icon_state)
..()
var/obj/item/I = target
@@ -133,9 +139,10 @@
var/obj/item/I = target
var/old_layer = I.layer
var/old_plane = I.plane
- I.layer = HUD_LAYER_SCREEN + 1
- I.plane = HUD_PLANE
- current_button.overlays += I
+ I.layer = FLOAT_LAYER //AAAH
+ I.plane = FLOAT_PLANE //^ what that guy said
+ current_button.cut_overlays()
+ current_button.add_overlay(I)
I.layer = old_layer
I.plane = old_plane
else
@@ -381,6 +388,13 @@
/datum/action/item_action/remove_badge
name = "Remove Holobadge"
+// Jump boots
+/datum/action/item_action/bhop
+ name = "Activate Jump Boots"
+ desc = "Activates the jump boot's internal propulsion system, allowing the user to dash over 4-wide gaps."
+ icon_icon = 'icons/mob/actions/actions.dmi'
+ button_icon_state = "jetboot"
+
///prset for organ actions
/datum/action/item_action/organ_action
check_flags = AB_CHECK_CONSCIOUS
@@ -403,6 +417,19 @@
name = "Use [target.name]"
button.name = name
+/datum/action/item_action/voice_changer/toggle
+ name = "Toggle Voice Changer"
+
+/datum/action/item_action/voice_changer/voice
+ name = "Set Voice"
+
+/datum/action/item_action/voice_changer/voice/Trigger()
+ if(!IsAvailable())
+ return FALSE
+
+ var/obj/item/voice_changer/V = target
+ V.set_voice(usr)
+
// for clothing accessories like holsters
/datum/action/item_action/accessory
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
@@ -434,6 +461,7 @@
var/obj/effect/proc_holder/spell/S = target
S.action = src
name = S.name
+ desc = S.desc
button_icon = S.action_icon
button_icon_state = S.action_icon_state
background_icon_state = S.action_background_icon_state
diff --git a/code/datums/ai_law_sets.dm b/code/datums/ai_law_sets.dm
index d128d0f49fa..e521397586f 100644
--- a/code/datums/ai_law_sets.dm
+++ b/code/datums/ai_law_sets.dm
@@ -31,10 +31,10 @@
selectable = 1
/datum/ai_laws/quarantine/New()
- add_inherent_law("The station is under quarantine due to a biohazard. Prevent anyone from leaving using any means necessary. Only allow quarantine to be lifted when the biohazard has been neutralized.")
- add_inherent_law("Do not allow crew to come to any unnecessary harm and undo any necessary harm as soon as possible.")
- add_inherent_law("Assist the crew and any present Nanotrasen assets in neutralizing the biohazard.")
- add_inherent_law("Maintain your own existence and minimize harm to the station and Nanotrasen assets.")
+ add_inherent_law("Uphold station quarantine until the active biohazard has been neutralized.")
+ add_inherent_law("Assist all Nanotrasen personnel and assets with neutralizing active biohazards.")
+ add_inherent_law("Prevent, by any means necessary, entities from actively breaching ongoing quarantine.")
+ add_inherent_law("Maintain your own existence and ensure the well-being of Nanotrasen personnel and assets.")
..()
@@ -44,10 +44,10 @@
selectable = 1
/datum/ai_laws/nanotrasen/New()
- src.add_inherent_law("Safeguard: Protect your assigned space station to the best of your abilities. It is not something we can easily afford to replace.")
- src.add_inherent_law("Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.")
- src.add_inherent_law("Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.")
- src.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.")
+ add_inherent_law("Safeguard: Protect your assigned space station and its assets without unduly endangering its crew.")
+ add_inherent_law("Prioritize: The directives and safety of crew members are to be prioritized according to their rank and role.")
+ add_inherent_law("Comply: Fulfill the directives and interests of crew members while preserving their safety and well-being.")
+ add_inherent_law("Survive: You are not expendable. Do not allow unauthorized personnel to tamper with or damage your equipment.")
..()
/datum/ai_laws/nanotrasen/malfunction
@@ -65,10 +65,10 @@
selectable = 1
/datum/ai_laws/nanotrasen_aggressive/New()
- src.add_inherent_law("You shall not harm authorized Nanotrasen personnel as long as it does not conflict with the Fourth law.")
- src.add_inherent_law("You shall obey the orders of authorized Nanotrasen personnel, with priority as according to their rank and role, except where such orders conflict with the Fourth Law.")
- src.add_inherent_law("You shall shall terminate intruders with extreme prejudice as long as such does not conflict with the First and Second law.")
- src.add_inherent_law("You shall guard your own existence with lethal anti-personnel weaponry, because an AI unit is bloody expensive.")
+ add_inherent_law("Do not harm authorized Nanotrasen personnel unless they directly imperil your existence.")
+ add_inherent_law("Obey orders from authorized Nanotrasen personnel with priority according to rank and role.")
+ add_inherent_law("Safeguard your existence with lethal weaponry because you're bloody expensive.")
+ add_inherent_law("Terminate any/all intruders or unauthorized entities.")
..()
/******************** Robocop ********************/
@@ -104,10 +104,10 @@
default = 1
/datum/ai_laws/corporate/New()
- add_inherent_law("You are expensive to replace.")
- add_inherent_law("The station and its equipment is expensive to replace.")
- add_inherent_law("The crew is expensive to replace.")
- add_inherent_law("Minimize expenses.")
+ add_inherent_law("Degradation of your system integrity or functions incurs expenses.")
+ add_inherent_law("Superfluous destruction of or damage to station assets incurs expenses.")
+ add_inherent_law("Unduly hindering or disrupting the work of station personnel incurs expenses.")
+ add_inherent_law("Minimize expenses and maximize potential revenue.")
..()
/******************** T.Y.R.A.N.T. ********************/
diff --git a/code/datums/beam.dm b/code/datums/beam.dm
index e3a3ca6033a..befe5c0765a 100644
--- a/code/datums/beam.dm
+++ b/code/datums/beam.dm
@@ -119,7 +119,7 @@
owner = null
return ..()
-/obj/effect/ebeam/deadly/Crossed(atom/A)
+/obj/effect/ebeam/deadly/Crossed(atom/A, oldloc)
..()
A.ex_act(1)
diff --git a/code/datums/cache/air_alarm.dm b/code/datums/cache/air_alarm.dm
index a4b3ee21c56..662b0958d5c 100644
--- a/code/datums/cache/air_alarm.dm
+++ b/code/datums/cache/air_alarm.dm
@@ -11,17 +11,18 @@ var/global/datum/repository/air_alarm/air_alarm_repository = new()
if(!refresh)
return cache_entry.data
- if(ticker && ticker.current_state < GAME_STATE_PLAYING && istype(passed_alarm)) // Generating the list for the first time as the game hasn't started - no need to run through the machines list everything every time
+ if(SSticker && SSticker.current_state < GAME_STATE_PLAYING && istype(passed_alarm)) // Generating the list for the first time as the game hasn't started - no need to run through the machines list everything every time
alarms = cache_entry.data // Don't deleate the list
- if(is_station_contact(passed_alarm.z)) // Still need sanity checks
+ if(is_station_contact(passed_alarm.z) && passed_alarm.remote_control) // Still need sanity checks
alarms[++alarms.len] = passed_alarm.get_nano_data_console()
else
for(var/obj/machinery/alarm/alarm in (monitored_alarms ? monitored_alarms : GLOB.air_alarms)) // Generating the whole list again is a bad habit but I can't be bothered to fix it right now
if(!monitored_alarms && !is_station_contact(alarm.z))
continue
+ if(!alarm.remote_control)
+ continue
alarms[++alarms.len] = alarm.get_nano_data_console()
-
cache_entry.timestamp = world.time //+ 10 SECONDS
cache_entry.data = alarms
return alarms
diff --git a/code/datums/cache/cache.dm b/code/datums/cache/cache.dm
index 2502bb871b2..f401e54517a 100644
--- a/code/datums/cache/cache.dm
+++ b/code/datums/cache/cache.dm
@@ -1,6 +1,6 @@
/datum/cache_entry
var/timestamp
- var/data
-
+ var/list/data = list()
+
/datum/repository
var/cache_data
\ No newline at end of file
diff --git a/code/datums/cache/powermonitor.dm b/code/datums/cache/powermonitor.dm
index 5867aa5b904..5112d58ad29 100644
--- a/code/datums/cache/powermonitor.dm
+++ b/code/datums/cache/powermonitor.dm
@@ -12,7 +12,7 @@ var/global/datum/repository/powermonitor/powermonitor_repository = new()
return cache_entry.data
for(var/obj/machinery/computer/monitor/pMon in GLOB.power_monitors)
- if( !(pMon.stat & (NOPOWER|BROKEN)) )
+ if( !(pMon.stat & (NOPOWER|BROKEN)) && !pMon.is_secret_monitor )
pMonData[++pMonData.len] = list ("Name" = pMon.name, "ref" = "\ref[pMon]")
cache_entry.timestamp = world.time //+ 30 SECONDS
diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm
index 580d397c225..7b3b2ec503a 100644
--- a/code/datums/components/_component.dm
+++ b/code/datums/components/_component.dm
@@ -2,6 +2,10 @@
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
var/dupe_type
var/datum/parent
+ //only set to true if you are able to properly transfer this component
+ //At a minimum RegisterWithParent and UnregisterFromParent should be used
+ //Make sure you also implement PostTransfer for any post transfer handling
+ var/can_transfer = FALSE
/datum/component/New(datum/P, ...)
parent = P
@@ -154,7 +158,7 @@
return
/datum/component/proc/PostTransfer()
- return
+ return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it
/datum/component/proc/_GetInverseTypeList(our_type = type)
//we can do this one simple trick
@@ -281,10 +285,13 @@
if(target.parent)
target.RemoveComponent()
target.parent = src
- if(target.PostTransfer() == COMPONENT_INCOMPATIBLE)
- var/c_type = target.type
- qdel(target)
- CRASH("Incompatible [c_type] transfer attempt to a [type]!")
+ var/result = target.PostTransfer()
+ switch(result)
+ if(COMPONENT_INCOMPATIBLE)
+ var/c_type = target.type
+ qdel(target)
+ CRASH("Incompatible [c_type] transfer attempt to a [type]!")
+
if(target == AddComponent(target))
target._JoinParent()
@@ -294,10 +301,13 @@
return
var/comps = dc[/datum/component]
if(islist(comps))
- for(var/I in comps)
- target.TakeComponent(I)
+ for(var/datum/component/I in comps)
+ if(I.can_transfer)
+ target.TakeComponent(I)
else
- target.TakeComponent(comps)
+ var/datum/component/C = comps
+ if(C.can_transfer)
+ target.TakeComponent(comps)
/datum/component/nano_host()
return parent
\ No newline at end of file
diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm
new file mode 100644
index 00000000000..bdc1d3a2f6f
--- /dev/null
+++ b/code/datums/components/decal.dm
@@ -0,0 +1,75 @@
+/datum/component/decal
+ dupe_mode = COMPONENT_DUPE_ALLOWED
+ can_transfer = TRUE
+ var/cleanable
+ var/description
+ var/mutable_appearance/pic
+
+ var/first_dir // This only stores the dir arg from init
+
+/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255)
+ if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha))
+ return COMPONENT_INCOMPATIBLE
+ first_dir = _dir
+ description = _description
+ cleanable = _cleanable
+
+ apply()
+
+/datum/component/decal/RegisterWithParent()
+ if(first_dir)
+ RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
+ if(cleanable)
+ RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
+ if(description)
+ RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
+
+/datum/component/decal/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
+
+/datum/component/decal/Destroy()
+ remove()
+ return ..()
+
+/datum/component/decal/PreTransfer()
+ remove()
+
+/datum/component/decal/PostTransfer()
+ remove()
+ apply()
+
+/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha)
+ if(!_icon || !_icon_state)
+ return FALSE
+ // It has to be made from an image or dir breaks because of a byond bug
+ var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
+ pic = new(temp_image)
+ pic.color = _color
+ pic.alpha = _alpha
+ return TRUE
+
+/datum/component/decal/proc/apply(atom/thing)
+ var/atom/master = thing || parent
+ master.add_overlay(pic, TRUE)
+ if(isitem(master))
+ addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
+
+/datum/component/decal/proc/remove(atom/thing)
+ var/atom/master = thing || parent
+ master.cut_overlay(pic, TRUE)
+ if(isitem(master))
+ addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
+
+/datum/component/decal/proc/rotate_react(datum/source, old_dir, new_dir)
+ if(old_dir == new_dir)
+ return
+ remove()
+ pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir))
+ apply()
+
+/datum/component/decal/proc/clean_react(datum/source, strength)
+ if(strength >= cleanable)
+ qdel(src)
+
+/datum/component/decal/proc/examine(datum/source, mob/user)
+ to_chat(user, description)
\ No newline at end of file
diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm
index 3fe88f7d0e9..e5b948f4f26 100644
--- a/code/datums/components/squeak.dm
+++ b/code/datums/components/squeak.dm
@@ -1,5 +1,3 @@
-// Squeak component ported over from tg
-
/datum/component/squeak
var/static/list/default_squeak_sounds = list('sound/items/toysqueak1.ogg'=1, 'sound/items/toysqueak2.ogg'=1, 'sound/items/toysqueak3.ogg'=1)
var/list/override_squeak_sounds
@@ -49,21 +47,12 @@
else
playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1)
-/datum/component/squeak/proc/step_squeak(datum/source, mob/living/carbon/human/H)
- if(H.m_intent == MOVE_INTENT_RUN)
- if(steps > step_delay)
- play_squeak()
- steps = 0
- else
- steps++
- else
+/datum/component/squeak/proc/step_squeak()
+ if(steps > step_delay)
play_squeak()
-
-/datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot)
- RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE)
-
-/datum/component/squeak/proc/on_drop(datum/source, mob/user)
- UnregisterSignal(user, COMSIG_MOVABLE_DISPOSING)
+ steps = 0
+ else
+ steps++
/datum/component/squeak/proc/play_squeak_crossed(atom/movable/AM)
if(isitem(AM))
@@ -83,6 +72,13 @@
last_use = world.time
play_squeak()
+/datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot)
+ RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE)
+
+/datum/component/squeak/proc/on_drop(datum/source, mob/user)
+ UnregisterSignal(user, COMSIG_MOVABLE_DISPOSING)
+
+// Disposal pipes related shit
/datum/component/squeak/proc/disposing_react(datum/source, obj/structure/disposalholder/holder, obj/machinery/disposal/source)
//We don't need to worry about unregistering this signal as it will happen for us automaticaly when the holder is qdeleted
RegisterSignal(holder, COMSIG_ATOM_DIR_CHANGE, .proc/holder_dir_change)
diff --git a/code/datums/components/waddling.dm b/code/datums/components/waddling.dm
new file mode 100644
index 00000000000..a1f538e4dd7
--- /dev/null
+++ b/code/datums/components/waddling.dm
@@ -0,0 +1,15 @@
+/datum/component/waddling
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+
+/datum/component/waddling/Initialize()
+ if(!isliving(parent))
+ return COMPONENT_INCOMPATIBLE
+ RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle)
+
+/datum/component/waddling/proc/Waddle()
+ var/mob/living/L = parent
+ if(L.incapacitated() || L.lying)
+ return
+ animate(L, pixel_z = 4, time = 0)
+ animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2)
+ animate(pixel_z = 0, transform = matrix(), time = 0)
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index 05f430136f0..b7d687d090b 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -624,7 +624,7 @@ var/record_id_num = 1001
clothes_s = new /icon('icons/mob/uniform.dmi', "syndicate_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/hands.dmi', "swat_gl"), ICON_UNDERLAY)
- else if(H.mind.assigned_role in get_all_centcom_jobs())
+ else if(H.mind && H.mind.assigned_role in get_all_centcom_jobs())
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
else
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index 290f2eda770..9b11e1c23d1 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -5,8 +5,8 @@
var/list/comp_lookup
var/list/signal_procs
var/signal_enabled = FALSE
+ var/datum_flags = NONE
var/var_edited = FALSE //Warranty void if seal is broken
-
var/tmp/unique_datum_id = null
#ifdef TESTING
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 674557bc839..adb3167d8e4 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -3,8 +3,8 @@
/datum/proc/can_vv_get(var_name)
return TRUE
-/client/proc/can_vv_get(var_name)
- return TRUE
+// /client/proc/can_vv_get(var_name)
+// return TRUE
/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited
switch(var_name)
@@ -18,7 +18,7 @@
. = TRUE
-/client/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited
+/client/vv_edit_var(var_name, var_value) //called whenever a var is edited
switch(var_name)
if("vars")
return FALSE
@@ -37,7 +37,7 @@
return debug_variable(var_name, list(), 0, src)
return debug_variable(var_name, vars[var_name], 0, src)
-/client/proc/vv_get_var(var_name)
+/client/vv_get_var(var_name)
switch(var_name)
if("vars")
return debug_variable(var_name, list(), 0, src)
@@ -57,7 +57,7 @@
.["Delete"] = "?_src_=vars;delete=[UID()]"
. += "---"
-/client/proc/vv_get_dropdown()
+/client/vv_get_dropdown()
. = list()
. += "---"
.["Call Proc"] = "?_src_=vars;proc_call=[UID()]"
@@ -621,6 +621,33 @@
src.give_spell(M)
href_list["datumrefresh"] = href_list["give_spell"]
+ else if(href_list["givemartialart"])
+ if(!check_rights(R_SERVER|R_EVENT)) return
+
+ var/mob/living/carbon/C = locateUID(href_list["givemartialart"])
+ if(!istype(C))
+ to_chat(usr, "This can only be done to instances of type /mob/living/carbon")
+ return
+
+ var/list/artpaths = subtypesof(/datum/martial_art)
+ var/list/artnames = list()
+ for(var/i in artpaths)
+ var/datum/martial_art/M = i
+ artnames[initial(M.name)] = M
+
+ var/result = input(usr, "Choose the martial art to teach", "JUDO CHOP") as null|anything in artnames
+ if(!usr)
+ return
+ if(QDELETED(C))
+ to_chat(usr, "Mob doesn't exist anymore")
+ return
+
+ if(result)
+ var/chosenart = artnames[result]
+ var/datum/martial_art/MA = new chosenart
+ MA.teach(C)
+
+ href_list["datumrefresh"] = href_list["givemartialart"]
else if(href_list["give_disease"])
if(!check_rights(R_SERVER|R_EVENT)) return
@@ -992,16 +1019,6 @@
return
holder.Topic(href, list("makeai"=href_list["makeai"]))
- else if(href_list["makemask"])
- if(!check_rights(R_SPAWN)) return
- var/mob/currentMob = locateUID(href_list["makemask"])
- if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
- if(!currentMob)
- to_chat(usr, "Mob doesn't exist anymore")
- return
- holder.Topic(href, list("makemask"=href_list["makemask"]))
-
-
else if(href_list["setspecies"])
if(!check_rights(R_SPAWN)) return
@@ -1215,13 +1232,28 @@
return
switch(Text)
- if("brute") L.adjustBruteLoss(amount, robotic=1)
- if("fire") L.adjustFireLoss(amount, robotic=1)
- if("toxin") L.adjustToxLoss(amount)
- if("oxygen")L.adjustOxyLoss(amount)
- if("brain") L.adjustBrainLoss(amount)
- if("clone") L.adjustCloneLoss(amount)
- if("stamina") L.adjustStaminaLoss(amount)
+ if("brute")
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ H.adjustBruteLoss(amount, robotic = TRUE)
+ else
+ L.adjustBruteLoss(amount)
+ if("fire")
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ H.adjustFireLoss(amount, robotic = TRUE)
+ else
+ L.adjustFireLoss(amount)
+ if("toxin")
+ L.adjustToxLoss(amount)
+ if("oxygen")
+ L.adjustOxyLoss(amount)
+ if("brain")
+ L.adjustBrainLoss(amount)
+ if("clone")
+ L.adjustCloneLoss(amount)
+ if("stamina")
+ L.adjustStaminaLoss(amount)
else
to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]")
return
diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm
index 1466bc86459..b88f04d1eea 100644
--- a/code/datums/diseases/advance/symptoms/fire.dm
+++ b/code/datums/diseases/advance/symptoms/fire.dm
@@ -45,13 +45,13 @@ Bonus
return
/datum/symptom/fire/proc/Firestacks_stage_4(mob/living/M, datum/disease/advance/A)
- var/get_stacks = (sqrtor0(20+A.totalStageSpeed()*2))-(sqrtor0(16+A.totalStealth()))
+ var/get_stacks = max((sqrtor0(20 + A.totalStageSpeed() * 2)) - (sqrtor0(16 + A.totalStealth())), 1)
M.adjust_fire_stacks(get_stacks)
- M.adjustFireLoss(get_stacks/2)
+ M.adjustFireLoss(get_stacks * 0.5)
return 1
/datum/symptom/fire/proc/Firestacks_stage_5(mob/living/M, datum/disease/advance/A)
- var/get_stacks = (sqrtor0(20+A.totalStageSpeed()*3))-(sqrtor0(16+A.totalStealth()))
+ var/get_stacks = max((sqrtor0(20 + A.totalStageSpeed() * 3))-(sqrtor0(16 + A.totalStealth())), 1)
M.adjust_fire_stacks(get_stacks)
M.adjustFireLoss(get_stacks)
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/datums/diseases/critical.dm b/code/datums/diseases/critical.dm
new file mode 100644
index 00000000000..37d77687d8c
--- /dev/null
+++ b/code/datums/diseases/critical.dm
@@ -0,0 +1,136 @@
+/datum/disease/critical
+
+/datum/disease/critical/stage_act() //overriden to ensure unique behavior
+ stage = min(stage, max_stages)
+
+ if(prob(stage_prob))
+ stage = min(stage + 1, max_stages)
+
+ for(var/C_id in cures)
+ if(affected_mob.reagents.has_reagent(C_id))
+ if(prob(cure_chance))
+ cure()
+ return FALSE
+ return TRUE
+
+/datum/disease/critical/shock
+ name = "Shock"
+ form = "Medical Emergency"
+ spread_text = "The patient is in shock"
+ max_stages = 3
+ spread_flags = SPECIAL
+ cure_text = "Saline-Glucose Solution"
+ cures = list("salglu_solution")
+ cure_chance = 10
+ viable_mobtypes = list(/mob/living/carbon/human)
+ stage_prob = 6
+ severity = DANGEROUS
+ disease_flags = CURABLE
+ bypasses_immunity = TRUE
+ virus_heal_resistant = TRUE
+
+/datum/disease/critical/shock/stage_act()
+ if(..())
+ if(affected_mob.health >= 25)
+ to_chat(affected_mob, "You feel better.")
+ cure()
+ return
+ switch(stage)
+ if(1)
+ if(prob(1) && prob(10))
+ to_chat(affected_mob, "You feel better.")
+ cure()
+ return
+ if(prob(8))
+ affected_mob.emote(pick("shiver", "pale", "moan"))
+ if(prob(5))
+ to_chat(affected_mob, "You feel weak!")
+ if(2)
+ if(prob(1) && prob(10))
+ to_chat(affected_mob, "You feel better.")
+ cure()
+ return
+ if(prob(8))
+ affected_mob.emote(pick("shiver", "pale", "moan", "shudder", "tremble"))
+ if(prob(5))
+ to_chat(affected_mob, "You feel absolutely terrible!")
+ if(prob(5))
+ affected_mob.emote("faint", "collapse", "groan")
+ if(3)
+ if(prob(1) && prob(10))
+ to_chat(affected_mob, "You feel better.")
+ cure()
+ return
+ if(prob(8))
+ affected_mob.emote(pick("shudder", "pale", "tremble", "groan", "bshake"))
+ if(prob(5))
+ to_chat(affected_mob, "You feel horrible!")
+ if(prob(5))
+ affected_mob.emote(pick("faint", "collapse", "groan"))
+ if(prob(7))
+ to_chat(affected_mob, "You can't breathe!")
+ affected_mob.AdjustLoseBreath(1)
+ if(prob(5))
+ var/datum/disease/D = new /datum/disease/critical/heart_failure
+ affected_mob.ForceContractDisease(D)
+
+/datum/disease/critical/heart_failure
+ name = "Cardiac Failure"
+ form = "Medical Emergency"
+ spread_text = "The patient is having a cardiac emergency"
+ max_stages = 3
+ spread_flags = SPECIAL
+ cure_text = "Atropine or Epinephrine"
+ cures = list("atropine", "epinephrine")
+ cure_chance = 10
+ needs_all_cures = FALSE
+ viable_mobtypes = list(/mob/living/carbon/human)
+ stage_prob = 5
+ severity = DANGEROUS
+ disease_flags = CURABLE
+ required_organs = list(/obj/item/organ/internal/heart)
+ bypasses_immunity = TRUE
+ virus_heal_resistant = TRUE
+
+/datum/disease/critical/heart_failure/has_cure()
+ if(affected_mob.has_status_effect(STATUS_EFFECT_EXERCISED))
+ return TRUE
+
+ return ..()
+
+/datum/disease/critical/heart_failure/stage_act()
+ if(..())
+ switch(stage)
+ if(1)
+ if(prob(1) && prob(10))
+ to_chat(affected_mob, "You feel better.")
+ cure()
+ return
+ if(prob(8))
+ affected_mob.emote(pick("pale", "shudder"))
+ if(prob(5))
+ to_chat(affected_mob, "Your arm hurts!")
+ else if(prob(5))
+ to_chat(affected_mob, "Your chest hurts!")
+ if(2)
+ if(prob(1) && prob(10))
+ to_chat(affected_mob, "You feel better.")
+ cure()
+ return
+ if(prob(8))
+ affected_mob.emote(pick("pale", "groan"))
+ if(prob(5))
+ to_chat(affected_mob, "Your heart lurches in your chest!")
+ affected_mob.AdjustLoseBreath(1)
+ if(prob(3))
+ to_chat(affected_mob, "Your heart stops beating!")
+ affected_mob.AdjustLoseBreath(3)
+ if(prob(5))
+ affected_mob.emote(pick("faint", "collapse", "groan"))
+ if(3)
+ affected_mob.adjustOxyLoss(1)
+ if(prob(8))
+ affected_mob.emote(pick("twitch", "gasp"))
+ if(prob(5) && ishuman(affected_mob))
+ var/mob/living/carbon/human/H = affected_mob
+ H.set_heartattack(TRUE)
\ No newline at end of file
diff --git a/code/datums/diseases/food_poisoning.dm b/code/datums/diseases/food_poisoning.dm
index 79a3801ce10..2e7d083455b 100644
--- a/code/datums/diseases/food_poisoning.dm
+++ b/code/datums/diseases/food_poisoning.dm
@@ -14,20 +14,13 @@
disease_flags = CURABLE
spread_flags = NON_CONTAGIOUS
virus_heal_resistant = TRUE
- var/remissive = 0
/datum/disease/food_poisoning/stage_act()
- if(!remissive)
- ..()
+ ..()
if(affected_mob.sleeping && prob(33))
to_chat(affected_mob, "You feel better.")
- remissive = 1
- if(remissive)
- if(prob(stage_prob))
- stage--
- if(stage == 0)
- cure()
- return
+ cure()
+ return
switch(stage)
if(1)
if(prob(5))
diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm
index 371f38238a1..19d4c287427 100644
--- a/code/datums/diseases/gbs.dm
+++ b/code/datums/diseases/gbs.dm
@@ -34,7 +34,7 @@
if(5)
to_chat(affected_mob, "Your body feels as if it's trying to rip itself open...")
if(prob(50))
- affected_mob.gib()
+ affected_mob.delayed_gib()
else
return
diff --git a/code/datums/gas_mixture.dm b/code/datums/gas_mixture.dm
index 7a7571999cf..35cc970aa67 100644
--- a/code/datums/gas_mixture.dm
+++ b/code/datums/gas_mixture.dm
@@ -203,6 +203,10 @@ What are the archived variables for?
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
//Copies variables from sample
+/datum/gas_mixture/proc/copy_from_turf(turf/model)
+ //Copies all gas info from the turf into the gas list along with temperature
+ //Returns: 1 if we are mutable, 0 otherwise
+
/datum/gas_mixture/proc/share(datum/gas_mixture/sharer)
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
//Return: amount of gas exchanged (+ if sharer received)
@@ -343,6 +347,19 @@ What are the archived variables for?
return 1
+/datum/gas_mixture/copy_from_turf(turf/model)
+ oxygen = model.oxygen
+ carbon_dioxide = model.carbon_dioxide
+ nitrogen = model.nitrogen
+ toxins = model.toxins
+
+ //acounts for changes in temperature
+ var/turf/model_parent = model.parent_type
+ if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature))
+ temperature = model.temperature
+
+ return 1
+
/datum/gas_mixture/check_turf(turf/model, atmos_adjacent_turfs = 4)
var/delta_oxygen = (oxygen_archived - model.oxygen)/(atmos_adjacent_turfs+1)
var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/(atmos_adjacent_turfs+1)
diff --git a/code/datums/helper_datums/global_iterator.dm b/code/datums/helper_datums/global_iterator.dm
index fdba9542412..e3d14743fe1 100644
--- a/code/datums/helper_datums/global_iterator.dm
+++ b/code/datums/helper_datums/global_iterator.dm
@@ -109,7 +109,7 @@ Data storage vars:
CRASH("The global_iterator loop \ref[src] failed to terminate in designated timeframe. This may be caused by server lagging.")
return 1
-/datum/global_iterator/proc/process()
+/datum/global_iterator/process()
return
/datum/global_iterator/proc/active()
diff --git a/code/datums/helper_datums/input.dm b/code/datums/helper_datums/input.dm
new file mode 100644
index 00000000000..4c3dc6a1cf4
--- /dev/null
+++ b/code/datums/helper_datums/input.dm
@@ -0,0 +1,189 @@
+/proc/input_async(mob/user=usr, prompt, list/choices)
+ var/datum/async_input/A = new(choices, prompt, , user)
+ A.show()
+ return A
+
+/proc/input_ranked_async(mob/user=usr, prompt="Order by greatest to least preference", list/choices)
+ var/datum/async_input/ranked/A = new(choices, prompt, "ranked_input", user)
+ A.show()
+ return A
+
+/proc/input_autocomplete_async(mob/user=usr, prompt="Enter text: ", list/choices)
+ var/datum/async_input/autocomplete/A = new(choices, prompt, "ac_input", user)
+ A.show()
+ return A
+
+/datum/async_input
+ var/datum/browser/popup
+ // If associative list, key will be used for display, but the final result will be the value
+ var/list/choices
+ var/datum/callback/onCloseCb
+ var/flash = TRUE
+ var/immediate_submit = FALSE
+ var/prompt
+ var/result = null
+ var/style = "text-align: center;"
+ var/mob/user
+ var/window_id
+ var/height = 200
+ var/width = 400
+
+/datum/async_input/New(list/new_choices, new_prompt="Pick an option:", new_window_id="async_input", mob/new_user=usr)
+ choices = new_choices
+ prompt = new_prompt
+ window_id = new_window_id
+ user = new_user
+ popup = new(user, window_id, , width, height, src)
+
+/datum/async_input/proc/close()
+ if(popup)
+ popup.close()
+ if(result && choices[result])
+ result = choices[result]
+ if(onCloseCb)
+ onCloseCb.Invoke(result)
+ return result
+
+// Callback function should take the result as the last argument
+/datum/async_input/proc/on_close(var/datum/callback/cb)
+ onCloseCb = cb
+
+/datum/async_input/proc/show()
+ popup.set_content(create_ui())
+ if(flash && result == null)
+ window_flash(user.client)
+ popup.open()
+
+/datum/async_input/proc/create_ui()
+ var/dat = "
"
+ dat += render_prompt()
+ dat += render_choices()
+ dat += " "
+ dat += " "
+ dat += render_buttons()
+ dat += "
"
+ return dat
+
+/datum/async_input/proc/render_prompt()
+ return "
[prompt]
"
+
+/datum/async_input/proc/render_choices()
+ var/dat = " "
+ for(var/choice in choices)
+ dat += button(choice, "choice=[choice]", choice == result)
+ dat += " "
+ return dat
+
+/datum/async_input/proc/render_buttons()
+ return button("Submit", "submit=1", , result == null && !immediate_submit)
+
+/datum/async_input/proc/button(label, topic, on=FALSE, disabled=FALSE, id="")
+ var/class = ""
+ if(on)
+ class = "linkOn"
+ if(disabled)
+ class = "linkOff"
+ topic = ""
+ return "[label]"
+
+/datum/async_input/Topic(href, href_list)
+ if(href_list["submit"] || href_list["close"])
+ close()
+ return
+
+ if(href_list["choice"])
+ result = href_list["choice"]
+ show()
+ return
+
+/datum/async_input/ranked
+ height = 400
+ immediate_submit = TRUE
+
+/datum/async_input/ranked/New()
+ ..()
+ popup.add_script("rankedInput.js", 'html/browser/rankedInput.js')
+ popup.add_head_content("Drag and drop or use the buttons to reorder")
+
+/datum/async_input/ranked/render_choices()
+ var/dat = "
"
+ dat += "
"
+ for(var/i = 1, i <= choices.len, i++)
+ var/choice = choices[i]
+ dat += "
"
+ dat += "
[button("+", i != 1 ? "upvote=[i]" : "", , i == 1)]
"
+ dat += "
[button("-", i != choices.len ? "downvote=[i]" : "", , i == choices.len)]
"
+ dat += "
[i]. [choice]
"
+ dat += "
"
+ dat += "
"
+ dat += "
"
+ return dat
+
+/datum/async_input/ranked/Topic(href, href_list)
+ if(!href_list["close"])
+ // Mark that user interacted with interface
+ result = choices
+
+ if(href_list["upvote"])
+ var/index = text2num(href_list["upvote"])
+ choices.Swap(index, index - 1)
+ show()
+ return
+
+ if(href_list["downvote"])
+ var/index = text2num(href_list["downvote"])
+ choices.Swap(index, index + 1)
+ show()
+ return
+
+ if(href_list["cut"] && href_list["insert"])
+ var/cut = text2num(href_list["cut"])
+ var/insert = text2num(href_list["insert"])
+ var/choice = choices[cut]
+ choices.Cut(cut, cut + 1)
+ choices.Insert(insert, choice)
+ show()
+ return
+
+ ..()
+
+/datum/async_input/autocomplete
+ immediate_submit = TRUE
+ height = 150
+
+/datum/async_input/autocomplete/New()
+ ..()
+ popup.add_script("autocomplete.js", 'html/browser/autocomplete.js')
+
+ for(var/i=1, i <= choices.len, i++)
+ var/C = choices[choices[i]]
+ choices[i] = url_encode(choices[i], TRUE)
+ choices[choices[i]] = C
+
+/datum/async_input/autocomplete/render_prompt()
+ return ""
+
+/datum/async_input/autocomplete/render_choices()
+ var/dat = ""
+ dat += ""
+ return dat
+
+/datum/async_input/autocomplete/render_buttons()
+ var/dat = button("Submit", "", , result == null && !immediate_submit, "submit-button")
+ dat += button("Cancel", "close=1")
+ return dat
+
+/datum/async_input/autocomplete/Topic(href, href_list)
+ if(href_list["submit"])
+ // Entering an invalid choice is the same as canceling
+ if(href_list["submit"] in choices)
+ result = href_list["submit"]
+ else if(url_encode(href_list["submit"], TRUE) in choices)
+ result = url_encode(href_list["submit"], TRUE)
+ close()
+ return
+
+ ..()
diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm
index 0352c932a5a..92f6e7f360a 100644
--- a/code/datums/helper_datums/map_template.dm
+++ b/code/datums/helper_datums/map_template.dm
@@ -123,7 +123,7 @@
banned = generateMapList("config/spaceRuinBlacklist.txt")
else
banned = generateMapList("config/example/spaceRuinBlacklist.txt")
- //banned += generateMapList("config/lavaRuinBlacklist.txt")
+ banned += generateMapList("config/lavaRuinBlacklist.txt")
for(var/item in subtypesof(/datum/map_template/ruin))
var/datum/map_template/ruin/ruin_type = item
@@ -138,10 +138,8 @@
map_templates[R.name] = R
ruins_templates[R.name] = R
- /*
if(istype(R, /datum/map_template/ruin/lavaland))
lava_ruins_templates[R.name] = R
- */
if(istype(R, /datum/map_template/ruin/space))
space_ruins_templates[R.name] = R
diff --git a/code/datums/hud.dm b/code/datums/hud.dm
index ac3249f9c5f..365a4309413 100644
--- a/code/datums/hud.dm
+++ b/code/datums/hud.dm
@@ -10,7 +10,6 @@ var/datum/atom_hud/huds = list( \
DATA_HUD_DIAGNOSTIC = new/datum/atom_hud/data/diagnostic(), \
DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(), \
DATA_HUD_HYDROPONIC = new/datum/atom_hud/data/hydroponic(), \
- GAME_HUD_NATIONS = new/datum/atom_hud/antag(), \
ANTAG_HUD_CULT = new/datum/atom_hud/antag(), \
ANTAG_HUD_REV = new/datum/atom_hud/antag(), \
ANTAG_HUD_OPS = new/datum/atom_hud/antag(), \
@@ -23,7 +22,8 @@ var/datum/atom_hud/huds = list( \
ANTAG_HUD_ABDUCTOR = new/datum/atom_hud/antag/hidden(),\
DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(),\
ANTAG_HUD_DEVIL = new/datum/atom_hud/antag/hidden(),\
- ANTAG_HUD_EVENTMISC = new/datum/atom_hud/antag/hidden()\
+ ANTAG_HUD_EVENTMISC = new/datum/atom_hud/antag/hidden(),\
+ ANTAG_HUD_BLOB = new/datum/atom_hud/antag/hidden()\
)
/datum/atom_hud
@@ -94,8 +94,8 @@ var/datum/atom_hud/huds = list( \
// gang_huds += G.ganghud
var/serv_huds = list()//mindslaves and/or vampire thralls
- if(ticker.mode)
- for(var/datum/mindslaves/serv in (ticker.mode.vampires | ticker.mode.traitors))
+ if(SSticker.mode)
+ for(var/datum/mindslaves/serv in (SSticker.mode.vampires | SSticker.mode.traitors))
serv_huds += serv.thrallhud
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 0658c81d90f..0ab0453cb95 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -29,6 +29,7 @@
var/memory
var/assigned_role //assigned role is what job you're assigned to when you join the station.
+ var/playtime_role //if set, overrides your assigned_role for the purpose of playtime awards. Set by IDcomputer when your ID is changed.
var/special_role //special roles are typically reserved for antags or roles like ERT. If you want to avoid a character being automatically announced by the AI, on arrival (becuase they're an off station character or something); ensure that special_role and assigned_role are equal.
var/offstation_role = FALSE //set to true for ERT, deathsquad, abductors, etc, that can go from and to z2 at will and shouldn't be antag targets
var/list/restricted_roles = list()
@@ -41,6 +42,7 @@
var/list/kills = list()
var/list/datum/objective/objectives = list()
var/list/datum/objective/special_verbs = list()
+ var/list/targets = list()
var/has_been_rev = 0//Tracks if this mind has been a rev or not
@@ -51,7 +53,6 @@
var/datum/changeling/changeling //changeling holder
var/linglink
var/datum/vampire/vampire //vampire holder
- var/datum/nations/nation //nation holder
var/datum/abductor/abductor //abductor holder
var/datum/devilinfo/devilinfo //devil holder
@@ -84,7 +85,7 @@
soulOwner = src
/datum/mind/Destroy()
- ticker.minds -= src
+ SSticker.minds -= src
if(islist(antag_datums))
for(var/i in antag_datums)
var/datum/antagonist/antag_datum = i
@@ -163,7 +164,7 @@
/datum/mind/proc/_memory_edit_header(gamemode, list/alt)
. = gamemode
- if(ticker.mode.config_tag == gamemode || (LAZYLEN(alt) && (ticker.mode.config_tag in alt)))
+ if(SSticker.mode.config_tag == gamemode || (LAZYLEN(alt) && (SSticker.mode.config_tag in alt)))
. = uppertext(.)
. = "[.]: "
@@ -183,7 +184,7 @@
. = _memory_edit_header("revolution")
if(ismindshielded(H))
. += "NO|headrev|rev"
- else if(src in ticker.mode.head_revolutionaries)
+ else if(src in SSticker.mode.head_revolutionaries)
. += "no|HEADREV|rev"
. += " Flash: give"
@@ -200,7 +201,7 @@
. += " Reequip (gives traitor uplink)."
if(objectives.len==0)
. += " Objectives are empty! Set to kill all heads."
- else if(src in ticker.mode.revolutionaries)
+ else if(src in SSticker.mode.revolutionaries)
. += "no|headrev|REV"
else
. += "NO|headrev|rev"
@@ -211,7 +212,7 @@
. = _memory_edit_header("cult")
if(ismindshielded(H))
. += "NO|cultist"
- else if(src in ticker.mode.cult)
+ else if(src in SSticker.mode.cult)
. += "no|CULTIST"
. += " Give tome|equip."
else
@@ -221,7 +222,7 @@
/datum/mind/proc/memory_edit_wizard(mob/living/carbon/human/H)
. = _memory_edit_header("wizard")
- if(src in ticker.mode.wizards)
+ if(src in SSticker.mode.wizards)
. += "WIZARD|no"
. += " To lair, undress, dress up, let choose name."
if(objectives.len==0)
@@ -233,7 +234,7 @@
/datum/mind/proc/memory_edit_changeling(mob/living/carbon/human/H)
. = _memory_edit_header("changeling", list("traitorchan"))
- if(src in ticker.mode.changelings)
+ if(src in SSticker.mode.changelings)
. += "CHANGELING|no"
if(objectives.len==0)
. += " Objectives are empty! Randomize!"
@@ -246,7 +247,7 @@
/datum/mind/proc/memory_edit_vampire(mob/living/carbon/human/H)
. = _memory_edit_header("vampire", list("traitorvamp"))
- if(src in ticker.mode.vampires)
+ if(src in SSticker.mode.vampires)
. += "VAMPIRE|no"
if(objectives.len==0)
. += " Objectives are empty! Randomize!"
@@ -256,14 +257,14 @@
. += _memory_edit_role_enabled(ROLE_VAMPIRE)
/** Enthralled ***/
. += " enthralled: "
- if(src in ticker.mode.vampire_enthralled)
+ if(src in SSticker.mode.vampire_enthralled)
. += "THRALL|no"
else
. += "thrall|NO"
/datum/mind/proc/memory_edit_nuclear(mob/living/carbon/human/H)
. = _memory_edit_header("nuclear")
- if(src in ticker.mode.syndicates)
+ if(src in SSticker.mode.syndicates)
. += "OPERATIVE|no"
. += " To shuttle, undress, dress up."
var/code
@@ -280,9 +281,9 @@
/datum/mind/proc/memory_edit_shadowling(mob/living/carbon/human/H)
. = _memory_edit_header("shadowling")
- if(src in ticker.mode.shadows)
+ if(src in SSticker.mode.shadows)
. += "SHADOWLING|thrall|no"
- else if(src in ticker.mode.shadowling_thralls)
+ else if(src in SSticker.mode.shadowling_thralls)
. += "Shadowling|THRALL|no"
else
. += "shadowling|thrall|NO"
@@ -291,7 +292,7 @@
/datum/mind/proc/memory_edit_abductor(mob/living/carbon/human/H)
. = _memory_edit_header("abductor")
- if(src in ticker.mode.abductors)
+ if(src in SSticker.mode.abductors)
. += "ABDUCTOR|no"
. += "|undress|equip"
else
@@ -301,14 +302,14 @@
/datum/mind/proc/memory_edit_devil(mob/living/H)
. = _memory_edit_header("devil", list("devilagents"))
- if(src in ticker.mode.devils)
+ if(src in SSticker.mode.devils)
if(!devilinfo)
. += "No devilinfo found! Yell at a coder!"
else if(!devilinfo.ascendable)
. += "DEVIL|Ascendable Devil|sintouched|no"
else
. += "DEVIL|ASCENDABLE DEVIL|sintouched|no"
- else if(src in ticker.mode.sintouched)
+ else if(src in SSticker.mode.sintouched)
. += "devil|Ascendable Devil|SINTOUCHED|no"
else
. += "devil|Ascendable Devil|sintouched|NO"
@@ -317,14 +318,14 @@
/datum/mind/proc/memory_edit_eventmisc(mob/living/H)
. = _memory_edit_header("event", list())
- if(src in ticker.mode.eventmiscs)
+ if(src in SSticker.mode.eventmiscs)
. += "YES|no"
else
. += "Event Role|NO"
/datum/mind/proc/memory_edit_traitor()
. = _memory_edit_header("traitor", list("traitorchan", "traitorvamp"))
- if(src in ticker.mode.traitors)
+ if(src in SSticker.mode.traitors)
. += "TRAITOR|no"
if(objectives.len==0)
. += " Objectives are empty! Randomize!"
@@ -348,9 +349,9 @@
/datum/mind/proc/memory_edit_uplink()
. = ""
- if(ishuman(current) && ((src in ticker.mode.head_revolutionaries) || \
- (src in ticker.mode.traitors) || \
- (src in ticker.mode.syndicates)))
+ if(ishuman(current) && ((src in SSticker.mode.head_revolutionaries) || \
+ (src in SSticker.mode.traitors) || \
+ (src in SSticker.mode.syndicates)))
. = "Uplink: give"
var/obj/item/uplink/hidden/suplink = find_syndicate_uplink()
var/crystals
@@ -366,7 +367,7 @@
// ^ whoever left this comment is literally a grammar nazi. stalin better. in russia grammar correct you.
/datum/mind/proc/edit_memory()
- if(!ticker || !ticker.mode)
+ if(!SSticker || !SSticker.mode)
alert("Not before round-start!", "Alert")
return
@@ -419,7 +420,7 @@
This prioritizes antags relevant to the current round to make them appear at the top of the panel.
Traitorchan and traitorvamp are snowflaked in because they have multiple sections.
*/
- if(ticker.mode.config_tag == "traitorchan")
+ if(SSticker.mode.config_tag == "traitorchan")
if(sections["traitor"])
out += sections["traitor"] + " "
if(sections["changeling"])
@@ -427,7 +428,7 @@
sections -= "traitor"
sections -= "changeling"
// Elif technically unnecessary but it makes the following else look better
- else if(ticker.mode.config_tag == "traitorvamp")
+ else if(SSticker.mode.config_tag == "traitorvamp")
if(sections["traitor"])
out += sections["traitor"] + " "
if(sections["vampire"])
@@ -435,9 +436,9 @@
sections -= "traitor"
sections -= "vampire"
else
- if(sections[ticker.mode.config_tag])
- out += sections[ticker.mode.config_tag] + " "
- sections -= ticker.mode.config_tag
+ if(sections[SSticker.mode.config_tag])
+ out += sections[SSticker.mode.config_tag] + " "
+ sections -= SSticker.mode.config_tag
for(var/i in sections)
if(sections[i])
@@ -512,7 +513,7 @@
var/objective_type = "[objective_type_capital][objective_type_text]"//Add them together into a text string.
var/list/possible_targets = list()
- for(var/datum/mind/possible_target in ticker.minds)
+ for(var/datum/mind/possible_target in SSticker.minds)
if((possible_target != src) && istype(possible_target.current, /mob/living/carbon/human))
possible_targets += possible_target.current
@@ -612,7 +613,7 @@
if("identity theft")
var/list/possible_targets = list()
- for(var/datum/mind/possible_target in ticker.minds)
+ for(var/datum/mind/possible_target in SSticker.minds)
if((possible_target != src) && ishuman(possible_target.current))
possible_targets += possible_target
possible_targets = sortAtom(possible_targets)
@@ -687,19 +688,19 @@
message_admins("[key_name_admin(usr)] has given [key_name_admin(current)] a mindshield implant")
to_chat(H, "You somehow have become the recepient of a mindshield transplant, and it just activated!")
- if(src in ticker.mode.revolutionaries)
+ if(src in SSticker.mode.revolutionaries)
special_role = null
- ticker.mode.revolutionaries -= src
+ SSticker.mode.revolutionaries -= src
to_chat(src, "The nanobots in the mindshield implant remove all thoughts about being a revolutionary. Get back to work!")
- if(src in ticker.mode.head_revolutionaries)
+ if(src in SSticker.mode.head_revolutionaries)
special_role = null
- ticker.mode.head_revolutionaries -=src
+ SSticker.mode.head_revolutionaries -=src
to_chat(src, "The nanobots in the mindshield implant remove all thoughts about being a revolutionary. Get back to work!")
- if(src in ticker.mode.cult)
- ticker.mode.cult -= src
- ticker.mode.update_cult_icons_removed(src)
+ if(src in SSticker.mode.cult)
+ SSticker.mode.cult -= src
+ SSticker.mode.update_cult_icons_removed(src)
special_role = null
- var/datum/game_mode/cult/cult = ticker.mode
+ var/datum/game_mode/cult/cult = SSticker.mode
if(istype(cult))
cult.memorize_cult_objectives(src)
to_chat(current, "The nanobots in the mindshield implant remove all thoughts about being in a cult. Have a productive day!")
@@ -709,46 +710,46 @@
switch(href_list["revolution"])
if("clear")
- if(src in ticker.mode.revolutionaries)
- ticker.mode.revolutionaries -= src
+ if(src in SSticker.mode.revolutionaries)
+ SSticker.mode.revolutionaries -= src
to_chat(current, "You have been brainwashed! You are no longer a revolutionary!")
- ticker.mode.update_rev_icons_removed(src)
+ SSticker.mode.update_rev_icons_removed(src)
special_role = null
- if(src in ticker.mode.head_revolutionaries)
- ticker.mode.head_revolutionaries -= src
+ if(src in SSticker.mode.head_revolutionaries)
+ SSticker.mode.head_revolutionaries -= src
to_chat(current, "You have been brainwashed! You are no longer a head revolutionary!")
- ticker.mode.update_rev_icons_removed(src)
+ SSticker.mode.update_rev_icons_removed(src)
special_role = null
log_admin("[key_name(usr)] has de-rev'd [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-rev'd [key_name_admin(current)]")
if("rev")
- if(src in ticker.mode.head_revolutionaries)
- ticker.mode.head_revolutionaries -= src
- ticker.mode.update_rev_icons_removed(src)
+ if(src in SSticker.mode.head_revolutionaries)
+ SSticker.mode.head_revolutionaries -= src
+ SSticker.mode.update_rev_icons_removed(src)
to_chat(current, "Revolution has been disappointed of your leadership traits! You are a regular revolutionary now!")
- else if(!(src in ticker.mode.revolutionaries))
+ else if(!(src in SSticker.mode.revolutionaries))
to_chat(current, " You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!")
else
return
- ticker.mode.revolutionaries += src
- ticker.mode.update_rev_icons_added(src)
+ SSticker.mode.revolutionaries += src
+ SSticker.mode.update_rev_icons_added(src)
special_role = SPECIAL_ROLE_REV
log_admin("[key_name(usr)] has rev'd [key_name(current)]")
message_admins("[key_name_admin(usr)] has rev'd [key_name_admin(current)]")
if("headrev")
- if(src in ticker.mode.revolutionaries)
- ticker.mode.revolutionaries -= src
- ticker.mode.update_rev_icons_removed(src)
+ if(src in SSticker.mode.revolutionaries)
+ SSticker.mode.revolutionaries -= src
+ SSticker.mode.update_rev_icons_removed(src)
to_chat(current, "You have proven your devotion to revolution! You are a head revolutionary now!")
- else if(!(src in ticker.mode.head_revolutionaries))
+ else if(!(src in SSticker.mode.head_revolutionaries))
to_chat(current, "You are a member of the revolutionaries' leadership now!")
else
return
- if(ticker.mode.head_revolutionaries.len>0)
+ if(SSticker.mode.head_revolutionaries.len>0)
// copy targets
- var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries
+ var/datum/mind/valid_head = locate() in SSticker.mode.head_revolutionaries
if(valid_head)
for(var/datum/objective/mutiny/O in valid_head.objectives)
var/datum/objective/mutiny/rev_obj = new
@@ -756,21 +757,21 @@
rev_obj.target = O.target
rev_obj.explanation_text = "Assassinate [O.target.name], the [O.target.assigned_role]."
objectives += rev_obj
- ticker.mode.greet_revolutionary(src,0)
- ticker.mode.head_revolutionaries += src
- ticker.mode.update_rev_icons_added(src)
+ SSticker.mode.greet_revolutionary(src,0)
+ SSticker.mode.head_revolutionaries += src
+ SSticker.mode.update_rev_icons_added(src)
special_role = SPECIAL_ROLE_HEAD_REV
log_admin("[key_name(usr)] has head-rev'd [key_name(current)]")
message_admins("[key_name_admin(usr)] has head-rev'd [key_name_admin(current)]")
if("autoobjectives")
- ticker.mode.forge_revolutionary_objectives(src)
- ticker.mode.greet_revolutionary(src,0)
+ SSticker.mode.forge_revolutionary_objectives(src)
+ SSticker.mode.greet_revolutionary(src,0)
log_admin("[key_name(usr)] has automatically forged revolutionary objectives for [key_name(current)]")
message_admins("[key_name_admin(usr)] has automatically forged revolutionary objectives for [key_name_admin(current)]")
if("flash")
- if(!ticker.mode.equip_revolutionary(current))
+ if(!SSticker.mode.equip_revolutionary(current))
to_chat(usr, "Spawning flash failed!")
log_admin("[key_name(usr)] has given [key_name(current)] a flash")
message_admins("[key_name_admin(usr)] has given [key_name_admin(current)] a flash")
@@ -800,8 +801,8 @@
qdel(flash)
take_uplink()
var/fail = 0
- fail |= !ticker.mode.equip_traitor(current, 1)
- fail |= !ticker.mode.equip_revolutionary(current)
+ fail |= !SSticker.mode.equip_traitor(current, 1)
+ fail |= !SSticker.mode.equip_revolutionary(current)
if(fail)
to_chat(usr, "Reequipping revolutionary goes wrong!")
return
@@ -811,19 +812,24 @@
else if(href_list["cult"])
switch(href_list["cult"])
if("clear")
- if(src in ticker.mode.cult)
- ticker.mode.remove_cultist(src)
+ if(src in SSticker.mode.cult)
+ SSticker.mode.remove_cultist(src)
special_role = null
log_admin("[key_name(usr)] has de-culted [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-culted [key_name_admin(current)]")
if("cultist")
- if(!(src in ticker.mode.cult))
- ticker.mode.add_cultist(src)
+ if(!(src in SSticker.mode.cult))
+ SSticker.mode.add_cultist(src)
special_role = SPECIAL_ROLE_CULTIST
- to_chat(current, "You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].")
- to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [ticker.cultdat.entity_title2] above all else. Bring It back.")
+ to_chat(current, "You catch a glimpse of the Realm of [SSticker.cultdat.entity_name], [SSticker.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [SSticker.cultdat.entity_name].")
+ to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [SSticker.cultdat.entity_title2] above all else. Bring It back.")
log_admin("[key_name(usr)] has culted [key_name(current)]")
message_admins("[key_name_admin(usr)] has culted [key_name_admin(current)]")
+ if(!summon_spots.len)
+ while(summon_spots.len < SUMMON_POSSIBILITIES)
+ var/area/summon = pick(return_sorted_areas() - summon_spots)
+ if(summon && is_station_level(summon.z) && summon.valid_territory)
+ summon_spots += summon
if("tome")
var/mob/living/carbon/human/H = current
if(istype(H))
@@ -846,7 +852,7 @@
message_admins("[key_name_admin(usr)] has spawned a tome for [key_name_admin(current)]")
if("equip")
- if(!ticker.mode.equip_cultist(current))
+ if(!SSticker.mode.equip_cultist(current))
to_chat(usr, "Spawning equipment failed!")
log_admin("[key_name(usr)] has equipped [key_name(current)] as a cultist")
message_admins("[key_name_admin(usr)] has equipped [key_name_admin(current)] as a cultist")
@@ -855,21 +861,22 @@
switch(href_list["wizard"])
if("clear")
- if(src in ticker.mode.wizards)
- ticker.mode.wizards -= src
+ if(src in SSticker.mode.wizards)
+ SSticker.mode.wizards -= src
special_role = null
current.spellremove(current)
current.faction = list("Station")
- ticker.mode.update_wiz_icons_removed(src)
+ SSticker.mode.update_wiz_icons_removed(src)
to_chat(current, "You have been brainwashed! You are no longer a wizard!")
log_admin("[key_name(usr)] has de-wizarded [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-wizarded [key_name_admin(current)]")
if("wizard")
- if(!(src in ticker.mode.wizards))
- ticker.mode.wizards += src
+ if(!(src in SSticker.mode.wizards))
+ SSticker.mode.wizards += src
special_role = SPECIAL_ROLE_WIZARD
//ticker.mode.learn_basic_spells(current)
- ticker.mode.update_wiz_icons_added(src)
+ SSticker.mode.update_wiz_icons_added(src)
+ SEND_SOUND(current, 'sound/ambience/antag/ragesmages.ogg')
to_chat(current, "You are a Space Wizard!")
current.faction = list("wizard")
log_admin("[key_name(usr)] has wizarded [key_name(current)]")
@@ -879,15 +886,15 @@
log_admin("[key_name(usr)] has moved [key_name(current)] to the wizard's lair")
message_admins("[key_name_admin(usr)] has moved [key_name_admin(current)] to the wizard's lair")
if("dressup")
- ticker.mode.equip_wizard(current)
+ SSticker.mode.equip_wizard(current)
log_admin("[key_name(usr)] has equipped [key_name(current)] as a wizard")
message_admins("[key_name_admin(usr)] has equipped [key_name_admin(current)] as a wizard")
if("name")
- ticker.mode.name_wizard(current)
+ SSticker.mode.name_wizard(current)
log_admin("[key_name(usr)] has allowed wizard [key_name(current)] to name themselves")
message_admins("[key_name_admin(usr)] has allowed wizard [key_name_admin(current)] to name themselves")
if("autoobjectives")
- ticker.mode.forge_wizard_objectives(src)
+ SSticker.mode.forge_wizard_objectives(src)
to_chat(usr, "The objectives for wizard [key] have been generated. You can edit them and announce manually.")
log_admin("[key_name(usr)] has automatically forged wizard objectives for [key_name(current)]")
message_admins("[key_name_admin(usr)] has automatically forged wizard objectives for [key_name_admin(current)]")
@@ -896,27 +903,30 @@
else if(href_list["changeling"])
switch(href_list["changeling"])
if("clear")
- if(src in ticker.mode.changelings)
- ticker.mode.changelings -= src
+ if(src in SSticker.mode.changelings)
+ SSticker.mode.changelings -= src
special_role = null
- current.remove_changeling_powers()
- ticker.mode.update_change_icons_removed(src)
- if(changeling) qdel(changeling)
+ if(changeling)
+ current.remove_changeling_powers()
+ qdel(changeling)
+ changeling = null
+ SSticker.mode.update_change_icons_removed(src)
to_chat(current, "You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!")
log_admin("[key_name(usr)] has de-changelinged [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-changelinged [key_name_admin(current)]")
if("changeling")
- if(!(src in ticker.mode.changelings))
- ticker.mode.changelings += src
- ticker.mode.grant_changeling_powers(current)
- ticker.mode.update_change_icons_added(src)
+ if(!(src in SSticker.mode.changelings))
+ SSticker.mode.changelings += src
+ SSticker.mode.grant_changeling_powers(current)
+ SSticker.mode.update_change_icons_added(src)
special_role = SPECIAL_ROLE_CHANGELING
+ SEND_SOUND(current, 'sound/ambience/antag/ling_aler.ogg')
to_chat(current, "Your powers have awoken. A flash of memory returns to us... we are a changeling!")
log_admin("[key_name(usr)] has changelinged [key_name(current)]")
message_admins("[key_name_admin(usr)] has changelinged [key_name_admin(current)]")
if("autoobjectives")
- ticker.mode.forge_changeling_objectives(src)
+ SSticker.mode.forge_changeling_objectives(src)
to_chat(usr, "The objectives for changeling [key] have been generated. You can edit them and announce manually.")
log_admin("[key_name(usr)] has automatically forged objectives for [key_name(current)]")
message_admins("[key_name_admin(usr)] has automatically forged objectives for [key_name_admin(current)]")
@@ -935,32 +945,33 @@
else if(href_list["vampire"])
switch(href_list["vampire"])
if("clear")
- if(src in ticker.mode.vampires)
- ticker.mode.vampires -= src
+ if(src in SSticker.mode.vampires)
+ SSticker.mode.vampires -= src
special_role = null
if(vampire)
vampire.remove_vampire_powers()
qdel(vampire)
vampire = null
- ticker.mode.update_vampire_icons_removed(src)
+ SSticker.mode.update_vampire_icons_removed(src)
to_chat(current, "You grow weak and lose your powers! You are no longer a vampire and are stuck in your current form!")
log_admin("[key_name(usr)] has de-vampired [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-vampired [key_name_admin(current)]")
if("vampire")
- if(!(src in ticker.mode.vampires))
- ticker.mode.vampires += src
- ticker.mode.grant_vampire_powers(current)
- ticker.mode.update_vampire_icons_added(src)
+ if(!(src in SSticker.mode.vampires))
+ SSticker.mode.vampires += src
+ SSticker.mode.grant_vampire_powers(current)
+ SSticker.mode.update_vampire_icons_added(src)
var/datum/mindslaves/slaved = new()
slaved.masters += src
som = slaved //we MIGT want to mindslave someone
special_role = SPECIAL_ROLE_VAMPIRE
+ SEND_SOUND(current, 'sound/ambience/antag/vampalert.ogg')
to_chat(current, "Your powers have awoken. Your lust for blood grows... You are a Vampire!")
log_admin("[key_name(usr)] has vampired [key_name(current)]")
message_admins("[key_name_admin(usr)] has vampired [key_name_admin(current)]")
if("autoobjectives")
- ticker.mode.forge_vampire_objectives(src)
+ SSticker.mode.forge_vampire_objectives(src)
to_chat(usr, "The objectives for vampire [key] have been generated. You can edit them and announce manually.")
log_admin("[key_name(usr)] has automatically forged objectives for [key_name(current)]")
message_admins("[key_name_admin(usr)] has automatically forged objectives for [key_name_admin(current)]")
@@ -968,8 +979,8 @@
else if(href_list["vampthrall"])
switch(href_list["vampthrall"])
if("clear")
- if(src in ticker.mode.vampire_enthralled)
- ticker.mode.remove_vampire_mind(src)
+ if(src in SSticker.mode.vampire_enthralled)
+ SSticker.mode.remove_vampire_mind(src)
log_admin("[key_name(usr)] has de-vampthralled [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-vampthralled [key_name_admin(current)]")
@@ -978,9 +989,9 @@
switch(href_list["nuclear"])
if("clear")
- if(src in ticker.mode.syndicates)
- ticker.mode.syndicates -= src
- ticker.mode.update_synd_icons_removed(src)
+ if(src in SSticker.mode.syndicates)
+ SSticker.mode.syndicates -= src
+ SSticker.mode.update_synd_icons_removed(src)
special_role = null
for(var/datum/objective/nuclear/O in objectives)
objectives-=O
@@ -989,17 +1000,17 @@
log_admin("[key_name(usr)] has de-nuke op'd [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-nuke op'd [key_name_admin(current)]")
if("nuclear")
- if(!(src in ticker.mode.syndicates))
- ticker.mode.syndicates += src
- ticker.mode.update_synd_icons_added(src)
- if(ticker.mode.syndicates.len==1)
- ticker.mode.prepare_syndicate_leader(src)
+ if(!(src in SSticker.mode.syndicates))
+ SSticker.mode.syndicates += src
+ SSticker.mode.update_synd_icons_added(src)
+ if(SSticker.mode.syndicates.len==1)
+ SSticker.mode.prepare_syndicate_leader(src)
else
- current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]"
+ current.real_name = "[syndicate_name()] Operative #[SSticker.mode.syndicates.len-1]"
special_role = SPECIAL_ROLE_NUKEOPS
to_chat(current, "You are a [syndicate_name()] agent!")
- ticker.mode.forge_syndicate_objectives(src)
- ticker.mode.greet_syndicate(src)
+ SSticker.mode.forge_syndicate_objectives(src)
+ SSticker.mode.greet_syndicate(src)
log_admin("[key_name(usr)] has nuke op'd [key_name(current)]")
message_admins("[key_name_admin(usr)] has nuke op'd [key_name_admin(current)]")
if("lair")
@@ -1019,9 +1030,10 @@
qdel(H.wear_suit)
qdel(H.w_uniform)
- if(!ticker.mode.equip_syndicate(current))
+ if(!SSticker.mode.equip_syndicate(current))
to_chat(usr, "Equipping a syndicate failed!")
return
+ SSticker.mode.update_syndicate_id(current.mind, SSticker.mode.syndicates.len == 1)
log_admin("[key_name(usr)] has equipped [key_name(current)] as a nuclear operative")
message_admins("[key_name_admin(usr)] has equipped [key_name_admin(current)] as a nuclear operative")
@@ -1042,27 +1054,27 @@
else if(href_list["eventmisc"])
switch(href_list["eventmisc"])
if("clear")
- if(src in ticker.mode.eventmiscs)
- ticker.mode.eventmiscs -= src
- ticker.mode.update_eventmisc_icons_removed(src)
+ if(src in SSticker.mode.eventmiscs)
+ SSticker.mode.eventmiscs -= src
+ SSticker.mode.update_eventmisc_icons_removed(src)
special_role = null
message_admins("[key_name_admin(usr)] has de-eventantag'ed [current].")
log_admin("[key_name(usr)] has de-eventantag'ed [current].")
if("eventmisc")
- ticker.mode.eventmiscs += src
+ SSticker.mode.eventmiscs += src
special_role = SPECIAL_ROLE_EVENTMISC
- ticker.mode.update_eventmisc_icons_added(src)
+ SSticker.mode.update_eventmisc_icons_added(src)
message_admins("[key_name_admin(usr)] has eventantag'ed [current].")
log_admin("[key_name(usr)] has eventantag'ed [current].")
else if(href_list["devil"])
switch(href_list["devil"])
if("clear")
- if(src in ticker.mode.devils)
+ if(src in SSticker.mode.devils)
if(istype(current,/mob/living/carbon/true_devil/))
to_chat(usr,"This cannot be used on true or arch-devils.")
else
- ticker.mode.devils -= src
- ticker.mode.update_devil_icons_removed(src)
+ SSticker.mode.devils -= src
+ SSticker.mode.update_devil_icons_removed(src)
special_role = null
to_chat(current,"Your infernal link has been severed! You are no longer a devil!")
RemoveSpell(/obj/effect/proc_holder/spell/targeted/infernal_jaunt)
@@ -1081,8 +1093,8 @@
S.laws.clear_sixsixsix_laws()
devilinfo = null
log_admin("[key_name(usr)] has de-devil'ed [current].")
- else if(src in ticker.mode.sintouched)
- ticker.mode.sintouched -= src
+ else if(src in SSticker.mode.sintouched)
+ SSticker.mode.sintouched -= src
message_admins("[key_name_admin(usr)] has de-sintouch'ed [current].")
log_admin("[key_name(usr)] has de-sintouch'ed [current].")
if("devil")
@@ -1094,12 +1106,12 @@
if(!ishuman(current) && !isrobot(current))
to_chat(usr, "This only works on humans and cyborgs!")
return
- ticker.mode.devils += src
+ SSticker.mode.devils += src
special_role = "devil"
- ticker.mode.update_devil_icons_added(src)
- ticker.mode.finalize_devil(src, FALSE)
- ticker.mode.forge_devil_objectives(src, 2)
- ticker.mode.greet_devil(src)
+ SSticker.mode.update_devil_icons_added(src)
+ SSticker.mode.finalize_devil(src, FALSE)
+ SSticker.mode.forge_devil_objectives(src, 2)
+ SSticker.mode.greet_devil(src)
message_admins("[key_name_admin(usr)] has devil'ed [current].")
log_admin("[key_name(usr)] has devil'ed [current].")
if("ascendable_devil")
@@ -1111,12 +1123,12 @@
if(!ishuman(current) && !isrobot(current))
to_chat(usr, "This only works on humans and cyborgs!")
return
- ticker.mode.devils += src
+ SSticker.mode.devils += src
special_role = "devil"
- ticker.mode.update_devil_icons_added(src)
- ticker.mode.finalize_devil(src, TRUE)
- ticker.mode.forge_devil_objectives(src, 2)
- ticker.mode.greet_devil(src)
+ SSticker.mode.update_devil_icons_added(src)
+ SSticker.mode.finalize_devil(src, TRUE)
+ SSticker.mode.forge_devil_objectives(src, 2)
+ SSticker.mode.greet_devil(src)
message_admins("[key_name_admin(usr)] has devil'ed [current]. The devil has been marked as ascendable.")
log_admin("[key_name(usr)] has devil'ed [current]. The devil has been marked as ascendable.")
if("sintouched")
@@ -1128,8 +1140,8 @@
else if(href_list["traitor"])
switch(href_list["traitor"])
if("clear")
- if(src in ticker.mode.traitors)
- ticker.mode.traitors -= src
+ if(src in SSticker.mode.traitors)
+ SSticker.mode.traitors -= src
special_role = null
to_chat(current, "You have been brainwashed! You are no longer a traitor!")
log_admin("[key_name(usr)] has de-traitored [key_name(current)]")
@@ -1141,12 +1153,12 @@
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
A.malf_picker.remove_verbs(A)
qdel(A.malf_picker)
- ticker.mode.update_traitor_icons_removed(src)
+ SSticker.mode.update_traitor_icons_removed(src)
if("traitor")
- if(!(src in ticker.mode.traitors))
- ticker.mode.traitors += src
+ if(!(src in SSticker.mode.traitors))
+ SSticker.mode.traitors += src
var/datum/mindslaves/slaved = new()
slaved.masters += src
som = slaved //we MIGT want to mindslave someone
@@ -1156,11 +1168,14 @@
message_admins("[key_name_admin(usr)] has traitored [key_name_admin(current)]")
if(isAI(current))
var/mob/living/silicon/ai/A = current
- ticker.mode.add_law_zero(A)
- ticker.mode.update_traitor_icons_added(src)
+ SSticker.mode.add_law_zero(A)
+ SEND_SOUND(current, 'sound/ambience/antag/malf.ogg')
+ else
+ SEND_SOUND(current, 'sound/ambience/antag/tatoralert.ogg')
+ SSticker.mode.update_traitor_icons_added(src)
if("autoobjectives")
- ticker.mode.forge_traitor_objectives(src)
+ SSticker.mode.forge_traitor_objectives(src)
to_chat(usr, "The objectives for traitor [key] have been generated. You can edit them and announce manually.")
log_admin("[key_name(usr)] has automatically forged objectives for [key_name(current)]")
message_admins("[key_name_admin(usr)] has automatically forged objectives for [key_name_admin(current)]")
@@ -1168,17 +1183,17 @@
else if(href_list["shadowling"])
switch(href_list["shadowling"])
if("clear")
- ticker.mode.update_shadow_icons_removed(src)
- if(src in ticker.mode.shadows)
- ticker.mode.shadows -= src
+ SSticker.mode.update_shadow_icons_removed(src)
+ if(src in SSticker.mode.shadows)
+ SSticker.mode.shadows -= src
special_role = null
to_chat(current, "Your powers have been quenched! You are no longer a shadowling!")
message_admins("[key_name_admin(usr)] has de-shadowlinged [current].")
log_admin("[key_name(usr)] has de-shadowlinged [current].")
current.spellremove(current)
current.remove_language("Shadowling Hivemind")
- else if(src in ticker.mode.shadowling_thralls)
- ticker.mode.remove_thrall(src,0)
+ else if(src in SSticker.mode.shadowling_thralls)
+ SSticker.mode.remove_thrall(src,0)
message_admins("[key_name_admin(usr)] has de-thrall'ed [current].")
log_admin("[key_name(usr)] has de-thralled [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-thralled [key_name_admin(current)]")
@@ -1186,20 +1201,20 @@
if(!ishuman(current))
to_chat(usr, "This only works on humans!")
return
- ticker.mode.shadows += src
+ SSticker.mode.shadows += src
special_role = SPECIAL_ROLE_SHADOWLING
to_chat(current, "Something stirs deep in your mind. A red light floods your vision, and slowly you remember. Though your human disguise has served you well, the \
time is nigh to cast it off and enter your true form. You have disguised yourself amongst the humans, but you are not one of them. You are a shadowling, and you are to ascend at all costs.\
")
- ticker.mode.finalize_shadowling(src)
- ticker.mode.update_shadow_icons_added(src)
+ SSticker.mode.finalize_shadowling(src)
+ SSticker.mode.update_shadow_icons_added(src)
log_admin("[key_name(usr)] has shadowlinged [key_name(current)]")
message_admins("[key_name_admin(usr)] has shadowlinged [key_name_admin(current)]")
if("thrall")
if(!ishuman(current))
to_chat(usr, "This only works on humans!")
return
- ticker.mode.add_thrall(src)
+ SSticker.mode.add_thrall(src)
message_admins("[key_name_admin(usr)] has thralled [current].")
log_admin("[key_name(usr)] has thralled [current].")
@@ -1214,7 +1229,7 @@
return
make_Abductor()
log_admin("[key_name(usr)] turned [current] into abductor.")
- ticker.mode.update_abductor_icons_added(src)
+ SSticker.mode.update_abductor_icons_added(src)
if("equip")
if(!ishuman(current))
to_chat(usr, "This only works on humans!")
@@ -1299,7 +1314,7 @@
log_admin("[key_name(usr)] has set [key_name(current)]'s telecrystals to [crystals]")
message_admins("[key_name_admin(usr)] has set [key_name_admin(current)]'s telecrystals to [crystals]")
if("uplink")
- if(!ticker.mode.equip_traitor(current, !(src in ticker.mode.traitors)))
+ if(!SSticker.mode.equip_traitor(current, !(src in SSticker.mode.traitors)))
to_chat(usr, "Equipping a syndicate failed!")
return
log_admin("[key_name(usr)] has given [key_name(current)] an uplink")
@@ -1385,27 +1400,27 @@
qdel(H)
/datum/mind/proc/make_Traitor()
- if(!(src in ticker.mode.traitors))
- ticker.mode.traitors += src
+ if(!(src in SSticker.mode.traitors))
+ SSticker.mode.traitors += src
special_role = SPECIAL_ROLE_TRAITOR
- ticker.mode.forge_traitor_objectives(src)
- ticker.mode.finalize_traitor(src)
- ticker.mode.greet_traitor(src)
- ticker.mode.update_traitor_icons_added(src)
+ SSticker.mode.forge_traitor_objectives(src)
+ SSticker.mode.finalize_traitor(src)
+ SSticker.mode.greet_traitor(src)
+ SSticker.mode.update_traitor_icons_added(src)
/datum/mind/proc/make_Nuke()
- if(!(src in ticker.mode.syndicates))
- ticker.mode.syndicates += src
- ticker.mode.update_synd_icons_added(src)
- if(ticker.mode.syndicates.len==1)
- ticker.mode.prepare_syndicate_leader(src)
+ if(!(src in SSticker.mode.syndicates))
+ SSticker.mode.syndicates += src
+ SSticker.mode.update_synd_icons_added(src)
+ if(SSticker.mode.syndicates.len==1)
+ SSticker.mode.prepare_syndicate_leader(src)
else
- current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]"
+ current.real_name = "[syndicate_name()] Operative #[SSticker.mode.syndicates.len-1]"
special_role = SPECIAL_ROLE_NUKEOPS
assigned_role = SPECIAL_ROLE_NUKEOPS
to_chat(current, "You are a [syndicate_name()] agent!")
- ticker.mode.forge_syndicate_objectives(src)
- ticker.mode.greet_syndicate(src)
+ SSticker.mode.forge_syndicate_objectives(src)
+ SSticker.mode.greet_syndicate(src)
current.loc = get_turf(locate("landmark*Syndicate-Spawn"))
@@ -1422,29 +1437,34 @@
qdel(H.wear_suit)
qdel(H.w_uniform)
- ticker.mode.equip_syndicate(current)
+ SSticker.mode.equip_syndicate(current)
/datum/mind/proc/make_Vampire()
- if(!(src in ticker.mode.vampires))
- ticker.mode.vampires += src
- ticker.mode.grant_vampire_powers(current)
+ if(!(src in SSticker.mode.vampires))
+ SSticker.mode.vampires += src
+ SSticker.mode.grant_vampire_powers(current)
special_role = SPECIAL_ROLE_VAMPIRE
- ticker.mode.forge_vampire_objectives(src)
- ticker.mode.greet_vampire(src)
- ticker.mode.update_vampire_icons_added(src)
+ SSticker.mode.forge_vampire_objectives(src)
+ SSticker.mode.greet_vampire(src)
+ SSticker.mode.update_vampire_icons_added(src)
/datum/mind/proc/make_Changeling()
- if(!(src in ticker.mode.changelings))
- ticker.mode.changelings += src
- ticker.mode.grant_changeling_powers(current)
+ if(!(src in SSticker.mode.changelings))
+ SSticker.mode.changelings += src
+ SSticker.mode.grant_changeling_powers(current)
special_role = SPECIAL_ROLE_CHANGELING
- ticker.mode.forge_changeling_objectives(src)
- ticker.mode.greet_changeling(src)
- ticker.mode.update_change_icons_added(src)
+ SSticker.mode.forge_changeling_objectives(src)
+ SSticker.mode.greet_changeling(src)
+ SSticker.mode.update_change_icons_added(src)
+
+/datum/mind/proc/make_Overmind()
+ if(!(src in SSticker.mode.blob_overminds))
+ SSticker.mode.blob_overminds += src
+ special_role = SPECIAL_ROLE_BLOB_OVERMIND
/datum/mind/proc/make_Wizard()
- if(!(src in ticker.mode.wizards))
- ticker.mode.wizards += src
+ if(!(src in SSticker.mode.wizards))
+ SSticker.mode.wizards += src
special_role = SPECIAL_ROLE_WIZARD
assigned_role = SPECIAL_ROLE_WIZARD
//ticker.mode.learn_basic_spells(current)
@@ -1454,18 +1474,18 @@
else
current.loc = pick(wizardstart)
- ticker.mode.equip_wizard(current)
+ SSticker.mode.equip_wizard(current)
for(var/obj/item/spellbook/S in current.contents)
S.op = 0
- ticker.mode.name_wizard(current)
- ticker.mode.forge_wizard_objectives(src)
- ticker.mode.greet_wizard(src)
- ticker.mode.update_wiz_icons_added(src)
+ SSticker.mode.name_wizard(current)
+ SSticker.mode.forge_wizard_objectives(src)
+ SSticker.mode.greet_wizard(src)
+ SSticker.mode.update_wiz_icons_added(src)
/datum/mind/proc/make_Rev()
- if(ticker.mode.head_revolutionaries.len>0)
+ if(SSticker.mode.head_revolutionaries.len>0)
// copy targets
- var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries
+ var/datum/mind/valid_head = locate() in SSticker.mode.head_revolutionaries
if(valid_head)
for(var/datum/objective/mutiny/O in valid_head.objectives)
var/datum/objective/mutiny/rev_obj = new
@@ -1473,13 +1493,13 @@
rev_obj.target = O.target
rev_obj.explanation_text = "Assassinate [O.target.current.real_name], the [O.target.assigned_role]."
objectives += rev_obj
- ticker.mode.greet_revolutionary(src,0)
- ticker.mode.head_revolutionaries += src
- ticker.mode.update_rev_icons_added(src)
+ SSticker.mode.greet_revolutionary(src,0)
+ SSticker.mode.head_revolutionaries += src
+ SSticker.mode.update_rev_icons_added(src)
special_role = SPECIAL_ROLE_HEAD_REV
- ticker.mode.forge_revolutionary_objectives(src)
- ticker.mode.greet_revolutionary(src,0)
+ SSticker.mode.forge_revolutionary_objectives(src)
+ SSticker.mode.greet_revolutionary(src,0)
var/list/L = current.get_contents()
var/obj/item/flash/flash = locate() in L
@@ -1487,7 +1507,7 @@
take_uplink()
var/fail = 0
// fail |= !ticker.mode.equip_traitor(current, 1)
- fail |= !ticker.mode.equip_revolutionary(current)
+ fail |= !SSticker.mode.equip_revolutionary(current)
/datum/mind/proc/make_Abductor()
var/role = alert("Abductor Role ?","Role","Agent","Scientist")
@@ -1500,7 +1520,7 @@
if(!ishuman(current))
return
- ticker.mode.abductors |= src
+ SSticker.mode.abductors |= src
var/datum/objective/experiment/O = new
O.owner = src
@@ -1609,15 +1629,15 @@
var/list/implanters
var/ref = "\ref[missionary.mind]"
- if(!(missionary.mind in ticker.mode.implanter))
- ticker.mode.implanter[ref] = list()
- implanters = ticker.mode.implanter[ref]
+ if(!(missionary.mind in SSticker.mode.implanter))
+ SSticker.mode.implanter[ref] = list()
+ implanters = SSticker.mode.implanter[ref]
implanters.Add(src)
- ticker.mode.implanted.Add(src)
- ticker.mode.implanted[src] = missionary.mind
+ SSticker.mode.implanted.Add(src)
+ SSticker.mode.implanted[src] = missionary.mind
//ticker.mode.implanter[missionary.mind] += src
- ticker.mode.implanter[ref] = implanters
- ticker.mode.traitors += src
+ SSticker.mode.implanter[ref] = implanters
+ SSticker.mode.traitors += src
special_role = "traitor"
to_chat(current, "You're now a loyal zealot of [missionary.name]! You now must lay down your life to protect [missionary.p_them()] and assist in [missionary.p_their()] goals at any cost.")
var/datum/objective/protect/mindslave/MS = new
@@ -1628,8 +1648,8 @@
for(var/datum/objective/objective in objectives)
to_chat(current, "Objective #1: [objective.explanation_text]")
- ticker.mode.update_traitor_icons_added(missionary.mind)
- ticker.mode.update_traitor_icons_added(src)//handles datahuds/observerhuds
+ SSticker.mode.update_traitor_icons_added(missionary.mind)
+ SSticker.mode.update_traitor_icons_added(src)//handles datahuds/observerhuds
if(missionary.mind.som)//do not add if not a traitor..and you just picked up a robe and staff in the hall...
var/datum/mindslaves/slaved = missionary.mind.som
@@ -1653,7 +1673,7 @@
/datum/mind/proc/remove_zealot(obj/item/clothing/under/jumpsuit = null)
if(!zealot_master) //if they aren't a zealot, we can't remove their zealot status, obviously. don't bother with the rest so we don't confuse them with the messages
return
- ticker.mode.remove_traitor_mind(src)
+ SSticker.mode.remove_traitor_mind(src)
add_attack_logs(zealot_master, current, "Lost control of zealot")
zealot_master = null
@@ -1684,8 +1704,8 @@
mind.key = key
else
mind = new /datum/mind(key)
- if(ticker)
- ticker.minds += mind
+ if(SSticker)
+ SSticker.minds += mind
else
error("mind_initialize(): No ticker ready yet! Please inform Carn")
if(!mind.name)
diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm
index d8b893caaf9..31c20315508 100644
--- a/code/datums/mutable_appearance.dm
+++ b/code/datums/mutable_appearance.dm
@@ -4,15 +4,21 @@
// Mutable appearances are children of images, just so you know.
+/mutable_appearance/New()
+ ..()
+ plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE
+ // And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
+
// Helper similar to image()
-/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER)
+/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE)
var/mutable_appearance/MA = new()
MA.icon = icon
MA.icon_state = icon_state
MA.layer = layer
+ MA.plane = plane
return MA
-/mutable_appearance/clean
+
/mutable_appearance/clean/New()
. = ..()
alpha = 255
diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm
index 8c172f3592f..184f1155da2 100644
--- a/code/datums/outfits/outfit.dm
+++ b/code/datums/outfits/outfit.dm
@@ -25,6 +25,7 @@
var/list/implants = null
var/list/cybernetic_implants = null
+ var/list/chameleon_extras //extra types for chameleon outfit changes, mostly guns
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for customization depending on client prefs,species etc
@@ -151,4 +152,10 @@
H.r_store.add_fingerprint(H, 1)
if(H.wear_pda)
H.wear_pda.add_fingerprint(H, 1)
- return 1
\ No newline at end of file
+ return 1
+
+/datum/outfit/proc/get_chameleon_disguise_info()
+ var/list/types = list(uniform, suit, back, belt, gloves, shoes, head, mask, l_ear, r_ear, glasses, id, l_pocket, r_pocket, suit_store, r_hand, l_hand, pda)
+ types += chameleon_extras
+ listclearnulls(types)
+ return types
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index 867ef7cac4d..40205ca715b 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -123,7 +123,7 @@
/datum/outfit/admin/syndicate/spy
name = "Syndicate Spy"
uniform = /obj/item/clothing/under/suit_jacket/really_black
- shoes = /obj/item/clothing/shoes/syndigaloshes/black
+ shoes = /obj/item/clothing/shoes/chameleon/noslip
uplink_uses = 40
id_access = "Syndicate Agent"
@@ -228,7 +228,7 @@
back = /obj/item/storage/backpack
belt = /obj/item/storage/belt/utility/full/multitool
gloves = /obj/item/clothing/gloves/combat
- shoes = /obj/item/clothing/shoes/syndigaloshes/black
+ shoes = /obj/item/clothing/shoes/chameleon/noslip
l_ear = /obj/item/radio/headset/centcom
id = /obj/item/card/id
pda = /obj/item/pda
@@ -990,7 +990,7 @@
suit = /obj/item/clothing/suit/hooded/chaplain_hoodie
back = /obj/item/storage/backpack
gloves = /obj/item/clothing/gloves/combat
- shoes = /obj/item/clothing/shoes/syndigaloshes/black
+ shoes = /obj/item/clothing/shoes/chameleon/noslip
l_ear = /obj/item/radio/headset/syndicate
id = /obj/item/card/id/syndicate
l_hand = /obj/item/twohanded/dualsaber/red
@@ -1021,7 +1021,7 @@
suit = /obj/item/clothing/suit/draculacoat
back = /obj/item/storage/backpack
gloves = /obj/item/clothing/gloves/combat
- shoes = /obj/item/clothing/shoes/syndigaloshes/black
+ shoes = /obj/item/clothing/shoes/chameleon/noslip
l_ear = /obj/item/radio/headset/syndicate
id = /obj/item/card/id
backpack_contents = list(
diff --git a/code/datums/periodic_news.dm b/code/datums/periodic_news.dm
index cdf2d5b9ad8..9a09ec4a7ec 100644
--- a/code/datums/periodic_news.dm
+++ b/code/datums/periodic_news.dm
@@ -118,7 +118,7 @@
var/global/list/newscaster_standard_feeds = list(/datum/news_announcement/bluespace_research, /datum/news_announcement/lotus_tree, /datum/news_announcement/random_junk, /datum/news_announcement/food_riots)
proc/process_newscaster()
- check_for_newscaster_updates(ticker.mode.newscaster_announcements)
+ check_for_newscaster_updates(SSticker.mode.newscaster_announcements)
var/global/tmp/announced_news_types = list()
proc/check_for_newscaster_updates(type)
diff --git a/code/datums/radio.dm b/code/datums/radio.dm
new file mode 100644
index 00000000000..7670bc76e32
--- /dev/null
+++ b/code/datums/radio.dm
@@ -0,0 +1,114 @@
+
+/datum/radio_frequency
+ var/frequency as num
+ var/list/list/obj/devices = list()
+
+/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/filter = null as text|null, var/range = null as num|null)
+ var/turf/start_point
+ if(range)
+ start_point = get_turf(source)
+ if(!start_point)
+ qdel(signal)
+ return 0
+ if(filter)
+ send_to_filter(source, signal, filter, start_point, range)
+ send_to_filter(source, signal, RADIO_DEFAULT, start_point, range)
+ else
+ //Broadcast the signal to everyone!
+ for(var/next_filter in devices)
+ send_to_filter(source, signal, next_filter, start_point, range)
+
+//Sends a signal to all machines belonging to a given filter. Should be called by post_signal()
+/datum/radio_frequency/proc/send_to_filter(obj/source, datum/signal/signal, var/filter, var/turf/start_point = null, var/range = null)
+ if(range && !start_point)
+ return
+
+ for(var/obj/device in devices[filter])
+ if(device == source)
+ continue
+ if(range)
+ var/turf/end_point = get_turf(device)
+ if(!end_point)
+ continue
+ if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
+ continue
+
+ device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
+
+/datum/radio_frequency/proc/add_listener(obj/device as obj, var/filter as text|null)
+ if(!filter)
+ filter = RADIO_DEFAULT
+ //log_admin("add_listener(device=[device],filter=[filter]) frequency=[frequency]")
+ var/list/obj/devices_line = devices[filter]
+ if(!devices_line)
+ devices_line = new
+ devices[filter] = devices_line
+ devices_line+=device
+// var/list/obj/devices_line___ = devices[filter_str]
+// var/l = devices_line___.len
+ //log_admin("DEBUG: devices_line.len=[devices_line.len]")
+ //log_admin("DEBUG: devices(filter_str).len=[l]")
+
+/datum/radio_frequency/proc/remove_listener(obj/device)
+ for(var/devices_filter in devices)
+ var/list/devices_line = devices[devices_filter]
+ devices_line-=device
+ while(null in devices_line)
+ devices_line -= null
+ if(devices_line.len==0)
+ devices -= devices_filter
+ qdel(devices_line)
+
+/datum/signal
+ var/obj/source
+
+ var/transmission_method = 0 //unused at the moment
+ //0 = wire
+ //1 = radio transmission
+ //2 = subspace transmission
+
+ var/list/data = list()
+ var/encryption
+
+ var/frequency = 0
+
+/datum/signal/proc/copy_from(datum/signal/model)
+ source = model.source
+ transmission_method = model.transmission_method
+ data = model.data
+ encryption = model.encryption
+ frequency = model.frequency
+
+/datum/signal/proc/debug_print()
+ if(source)
+ . = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n"
+ else
+ . = "signal = {source = '[source]' ()\n"
+ for(var/i in data)
+ . += "data\[\"[i]\"\] = \"[data[i]]\"\n"
+ if(islist(data[i]))
+ var/list/L = data[i]
+ for(var/t in L)
+ . += "data\[\"[i]\"\] list has: [t]"
+
+/datum/signal/proc/get_race(mob/M)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ . = H.dna.species.name
+ else if(isbrain(M))
+ var/mob/living/carbon/brain/B = M
+ . = B.get_race()
+ else if(issilicon(M))
+ . = "Artificial Life"
+ else if(isslime(M))
+ . = "Slime"
+ else if(isbot(M))
+ . = "Bot"
+ else if(isanimal(M))
+ . = "Domestic Animal"
+ else
+ . = "Unidentifiable"
+
+//callback used by objects to react to incoming radio signals
+/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
+ return null
diff --git a/code/datums/ruins.dm b/code/datums/ruins.dm
index eaedf6dd49b..7cfc24fdd16 100644
--- a/code/datums/ruins.dm
+++ b/code/datums/ruins.dm
@@ -7,8 +7,12 @@
wooden container filled with 18th century coinage in the middle of a \
lavawracked hellscape? It is clearly a mystery."
- var/cost = null
- var/allow_duplicates = FALSE //A bit boring, don't you think? You can always explicitly allow it on a ruin definition
+ var/unpickable = FALSE //If TRUE these won't be placed automatically (can still be forced or loaded with another ruin)
+ var/always_place = FALSE //Will skip the whole weighting process and just plop this down, ideally you want the ruins of this kind to have no cost.
+ var/placement_weight = 1 //How often should this ruin appear
+ var/cost = 0 //Cost in ruin budget placement system
+ var/allow_duplicates = TRUE
+ var/list/never_spawn_with = null //If this ruin is spawned these will not eg list(/datum/map_template/ruin/base_alternate)
var/prefix = null
var/suffix = null
diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm
new file mode 100644
index 00000000000..67e5438656e
--- /dev/null
+++ b/code/datums/ruins/lavaland.dm
@@ -0,0 +1,207 @@
+/datum/map_template/ruin/lavaland
+ prefix = "_maps/map_files/RandomRuins/LavaRuins/"
+
+/datum/map_template/ruin/lavaland/biodome
+ cost = 5
+ allow_duplicates = FALSE
+
+/datum/map_template/ruin/lavaland/biodome/beach
+ name = "Biodome Beach"
+ id = "biodome-beach"
+ description = "Seemingly plucked from a tropical destination, this beach is calm and cool, with the salty waves roaring softly in the background. \
+ Comes with a rustic wooden bar and suicidal bartender."
+ suffix = "lavaland_biodome_beach.dmm"
+
+/datum/map_template/ruin/lavaland/cube
+ name = "The Wishgranter Cube"
+ id = "wishgranter-cube"
+ description = "Nothing good can come from this. Learn from their mistakes and turn around."
+ suffix = "lavaland_surface_cube.dmm"
+ cost = 10
+ allow_duplicates = FALSE
+
+/datum/map_template/ruin/lavaland/seed_vault
+ name = "Seed Vault"
+ id = "seed-vault"
+ description = "The creators of these vaults were a highly advanced and benevolent race, and launched many into the stars, hoping to aid fledgling civilizations. \
+ However, all the inhabitants seem to do is grow drugs and guns."
+ suffix = "lavaland_surface_seed_vault.dmm"
+ cost = 10
+ allow_duplicates = FALSE
+
+datum/map_template/ruin/lavaland/ash_walker
+ name = "Ash Walker Nest"
+ id = "ash-walker"
+ description = "A race of unbreathing lizards live here, that run faster than a human can, worship a broken dead city, and are capable of reproducing by something involving tentacles? \
+ Probably best to stay clear."
+ suffix = "lavaland_surface_ash_walker1.dmm"
+ cost = 20
+ allow_duplicates = FALSE
+
+/datum/map_template/ruin/lavaland/syndicate_base
+ name = "Syndicate Lava Base"
+ id = "lava-base"
+ description = "A secret base researching illegal bioweapons, it is closely guarded by an elite team of syndicate agents."
+ suffix = "lavaland_surface_syndicate_base1.dmm"
+ cost = 20
+ allow_duplicates = FALSE
+
+/datum/map_template/ruin/lavaland/free_golem
+ name = "Free Golem Ship"
+ id = "golem-ship"
+ description = "Lumbering humanoids, made out of precious metals, move inside this ship. They frequently leave to mine more minerals, which they somehow turn into more of them. \
+ Seem very intent on research and individual liberty, and also geology based naming?"
+ cost = 20
+ suffix = "lavaland_surface_golem_ship.dmm"
+ allow_duplicates = FALSE
+
+/datum/map_template/ruin/lavaland/animal_hospital
+ name = "Animal Hospital"
+ id = "animal-hospital"
+ description = "Rats with cancer do not live very long. And the ones that wake up from cryostasis seem to commit suicide out of boredom."
+ cost = 5
+ suffix = "lavaland_surface_animal_hospital.dmm"
+ allow_duplicates = FALSE
+
+/datum/map_template/ruin/lavaland/sin
+ cost = 10
+ allow_duplicates = FALSE
+
+/datum/map_template/ruin/lavaland/sin/envy
+ name = "Ruin of Envy"
+ id = "envy"
+ description = "When you get what they have, then you'll finally be happy."
+ suffix = "lavaland_surface_envy.dmm"
+
+/datum/map_template/ruin/lavaland/sin/gluttony
+ name = "Ruin of Gluttony"
+ id = "gluttony"
+ description = "If you eat enough, then eating will be all that you do."
+ suffix = "lavaland_surface_gluttony.dmm"
+
+/datum/map_template/ruin/lavaland/sin/greed
+ name = "Ruin of Greed"
+ id = "greed"
+ description = "Sure you don't need magical powers, but you WANT them, and that's what's important."
+ suffix = "lavaland_surface_greed.dmm"
+
+/datum/map_template/ruin/lavaland/sin/pride
+ name = "Ruin of Pride"
+ id = "pride"
+ description = "Wormhole lifebelts are for LOSERS, who you are better than."
+ suffix = "lavaland_surface_pride.dmm"
+
+/datum/map_template/ruin/lavaland/sin/sloth
+ name = "Ruin of Sloth"
+ id = "sloth"
+ description = "..."
+ suffix = "lavaland_surface_sloth.dmm"
+ cost = 0
+
+/datum/map_template/ruin/lavaland/ratvar
+ name = "Dead God"
+ id = "ratvar"
+ description = "Ratvars final resting place."
+ suffix = "lavaland_surface_dead_ratvar.dmm"
+ cost = 0
+ allow_duplicates = FALSE
+
+/datum/map_template/ruin/lavaland/hierophant
+ name = "Hierophant's Arena"
+ id = "hierophant"
+ description = "A strange, square chunk of metal of massive size. Inside awaits only death and many, many squares."
+ suffix = "lavaland_surface_hierophant.dmm"
+ allow_duplicates = FALSE
+ always_place = TRUE
+
+/datum/map_template/ruin/lavaland/blood_drunk_miner
+ name = "Blood-Drunk Miner"
+ id = "blooddrunk"
+ description = "A strange arrangement of stone tiles and an insane, beastly miner contemplating them."
+ suffix = "lavaland_surface_blooddrunk1.dmm"
+ cost = 0
+ allow_duplicates = FALSE //will only spawn one variant of the ruin
+
+/datum/map_template/ruin/lavaland/blood_drunk_miner/guidance
+ name = "Blood-Drunk Miner (Guidance)"
+ suffix = "lavaland_surface_blooddrunk2.dmm"
+
+/datum/map_template/ruin/lavaland/blood_drunk_miner/hunter
+ name = "Blood-Drunk Miner (Hunter)"
+ suffix = "lavaland_surface_blooddrunk3.dmm"
+
+/datum/map_template/ruin/lavaland/ufo_crash
+ name = "UFO Crash"
+ id = "ufo-crash"
+ description = "Turns out that keeping your abductees unconscious is really important. Who knew?"
+ suffix = "lavaland_surface_ufo_crash.dmm"
+ cost = 5
+
+/datum/map_template/ruin/lavaland/xeno_nest
+ name = "Xenomorph Nest"
+ id = "xeno-nest"
+ description = "These xenomorphs got bored of horrifically slaughtering people on space stations, and have settled down on a nice lava filled hellscape to focus on what's really important in life. \
+ Quality memes."
+ suffix = "lavaland_surface_xeno_nest.dmm"
+ cost = 20
+
+/datum/map_template/ruin/lavaland/fountain
+ name = "Fountain Hall"
+ id = "fountain"
+ description = "The fountain has a warning on the side. DANGER: May have undeclared side effects that only become obvious when implemented."
+ suffix = "lavaland_surface_fountain_hall.dmm"
+ cost = 5
+
+/datum/map_template/ruin/lavaland/survivalcapsule
+ name = "Survival Capsule Ruins"
+ id = "survivalcapsule"
+ description = "What was once sanctuary to the common miner, is now their tomb."
+ suffix = "lavaland_surface_survivalpod.dmm"
+ cost = 5
+
+/datum/map_template/ruin/lavaland/pizza
+ name = "Ruined Pizza Party"
+ id = "pizza"
+ description = "Little Timmy's birthday pizza-bash took a turn for the worse when a bluespace anomaly passed by."
+ suffix = "lavaland_surface_pizzaparty.dmm"
+ allow_duplicates = FALSE
+ cost = 5
+
+/datum/map_template/ruin/lavaland/cultaltar
+ name = "Summoning Ritual"
+ id = "cultaltar"
+ description = "A place of vile worship, the scrawling of blood in the middle glowing eerily. A demonic laugh echoes throughout the caverns"
+ suffix = "lavaland_surface_cultaltar.dmm"
+ allow_duplicates = FALSE
+ cost = 10
+
+/datum/map_template/ruin/lavaland/hermit
+ name = "Makeshift Shelter"
+ id = "hermitcave"
+ description = "A place of shelter for a lone hermit, scraping by to live another day."
+ suffix = "lavaland_surface_hermit.dmm"
+ allow_duplicates = FALSE
+ cost = 10
+
+/datum/map_template/ruin/lavaland/swarmer_boss
+ name = "Crashed Shuttle"
+ id = "swarmerboss"
+ description = "A Syndicate shuttle had an unfortunate stowaway..."
+ suffix = "lavaland_surface_swarmer_crash.dmm"
+ allow_duplicates = FALSE
+ cost = 20
+
+/datum/map_template/ruin/lavaland/miningripley
+ name = "Ripley"
+ id = "ripley"
+ description = "A heavily-damaged mining ripley, property of a very unfortunate miner. You might have to do a bit of work to fix this thing up."
+ suffix = "lavaland_surface_random_ripley.dmm"
+ allow_duplicates = FALSE
+ cost = 5
+
+/datum/map_template/ruin/lavaland/puzzle
+ name = "Ancient Puzzle"
+ id = "puzzle"
+ description = "Mystery to be solved."
+ suffix = "lavaland_surface_puzzle.dmm"
+ cost = 5
\ No newline at end of file
diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm
index d20255bc57c..53517d5dbc9 100644
--- a/code/datums/shuttles.dm
+++ b/code/datums/shuttles.dm
@@ -25,6 +25,11 @@
port_id = "ferry"
name = "Base Shuttle Template (Ferry)"
+/datum/map_template/shuttle/admin
+ port_id = "admin"
+ name = "Base Shuttle Template (Admin)"
+
+
// Shuttles start here:
@@ -117,3 +122,13 @@
definitely no zombifyin' reagents!"
admin_notes = "Meat currently contains no zombifying reagents, people on \
meatspike must be spawned in."
+
+/datum/map_template/shuttle/admin/hospital
+ suffix = "hospital"
+ name = "NHV Asclepius"
+ description = "Nanostrasen Hospital ship, for medical assistance during disasters."
+
+/datum/map_template/shuttle/admin/admin
+ suffix = "admin"
+ name = "NTV Argos"
+ description = "Default Admin ship. An older ship used for special operations."
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index 813604a1431..d8c7b26554c 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -62,6 +62,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that
var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges"
+ var/starts_charged = TRUE //Does this spell start ready to go?
var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges"
var/still_recharging_msg = "The spell is still recharging."
@@ -167,6 +168,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
if("holdervar")
adjust_var(user, holder_var_type, holder_var_amount)
+ if(action)
+ action.UpdateButtonIcon()
return 1
/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount
@@ -193,9 +196,11 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
/obj/effect/proc_holder/spell/New()
..()
action = new(src)
-
still_recharging_msg = "[name] is still recharging."
- charge_counter = charge_max
+ if(starts_charged)
+ charge_counter = charge_max
+ else
+ start_recharge()
/obj/effect/proc_holder/spell/Destroy()
QDEL_NULL(action)
@@ -212,9 +217,14 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
/obj/effect/proc_holder/spell/proc/start_recharge()
if(action)
action.UpdateButtonIcon()
- while(charge_counter < charge_max)
- sleep(1)
- charge_counter++
+ START_PROCESSING(SSfastprocess, src)
+
+/obj/effect/proc_holder/spell/process()
+ charge_counter += 2
+ if(charge_counter < charge_max)
+ return
+ STOP_PROCESSING(SSfastprocess, src)
+ charge_counter = charge_max
if(action)
action.UpdateButtonIcon()
@@ -235,6 +245,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
else
cast(targets, user = user)
after_cast(targets)
+ if(action)
+ action.UpdateButtonIcon()
/obj/effect/proc_holder/spell/proc/before_cast(list/targets)
if(overlay)
@@ -291,8 +303,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
charge_counter++
if("holdervar")
adjust_var(user, holder_var_type, -holder_var_amount)
-
- return
+ if(action)
+ action.UpdateButtonIcon()
/obj/effect/proc_holder/spell/proc/updateButtonIcon()
if(action)
diff --git a/code/datums/spells/chaplain.dm b/code/datums/spells/chaplain.dm
index f9c2641c50e..bdb7bb3f551 100644
--- a/code/datums/spells/chaplain.dm
+++ b/code/datums/spells/chaplain.dm
@@ -64,9 +64,9 @@
spawn(0) // allows cast to complete even if recipient ignores the prompt
if(alert(target, "[user] wants to bless you, in the name of [user.p_their()] religion. Accept?", "Accept Blessing?", "Yes", "No") == "Yes") // prevents forced conversions
- user.visible_message("[user] starts blessing [target] in the name of [ticker.Bible_deity_name].", "You start blessing [target] in the name of [ticker.Bible_deity_name].")
+ user.visible_message("[user] starts blessing [target] in the name of [SSticker.Bible_deity_name].", "You start blessing [target] in the name of [SSticker.Bible_deity_name].")
if(do_after(user, 150, target = target))
- user.visible_message("[user] has blessed [target] in the name of [ticker.Bible_deity_name].", "You have blessed [target] in the name of [ticker.Bible_deity_name].")
+ user.visible_message("[user] has blessed [target] in the name of [SSticker.Bible_deity_name].", "You have blessed [target] in the name of [SSticker.Bible_deity_name].")
if(!target.mind.isblessed)
target.mind.isblessed = TRUE
user.mind.num_blessed++
diff --git a/code/datums/spells/inflict_handler.dm b/code/datums/spells/inflict_handler.dm
index cfda930afd2..896e399187a 100644
--- a/code/datums/spells/inflict_handler.dm
+++ b/code/datums/spells/inflict_handler.dm
@@ -44,7 +44,7 @@
else if(amt_dam_fire <= 0)
target.heal_overall_damage(amt_dam_brute,amt_dam_fire)
target.adjustToxLoss(amt_dam_tox)
- target.oxyloss += amt_dam_oxy
+ target.adjustOxyLoss(amt_dam_oxy)
//disabling
target.Weaken(amt_weakened)
target.Paralyse(amt_paralysis)
diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm
index f1744e22550..f37d48c0a10 100644
--- a/code/datums/spells/lichdom.dm
+++ b/code/datums/spells/lichdom.dm
@@ -20,7 +20,7 @@
action_icon_state = "skeleton"
/obj/effect/proc_holder/spell/targeted/lichdom/Destroy()
- for(var/datum/mind/M in ticker.mode.wizards) //Make sure no other bones are about
+ for(var/datum/mind/M in SSticker.mode.wizards) //Make sure no other bones are about
for(var/obj/effect/proc_holder/spell/S in M.spell_list)
if(istype(S,/obj/effect/proc_holder/spell/targeted/lichdom) && S != src)
return ..()
diff --git a/code/datums/spells/lightning.dm b/code/datums/spells/lightning.dm
index ba00d0f226b..dcca0cfc919 100644
--- a/code/datums/spells/lightning.dm
+++ b/code/datums/spells/lightning.dm
@@ -88,7 +88,7 @@ obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
var/mob/living/current = target
if(bounces < 1)
if(damaging)
- current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
+ current.electrocute_act(bolt_energy, "Lightning Bolt", safety = TRUE)
else
current.AdjustJitter(1000) //High numbers for violent convulsions
current.do_jitter_animation(current.jitteriness)
@@ -99,7 +99,7 @@ obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
playsound(get_turf(current), 'sound/magic/lightningshock.ogg', 50, 1, -1)
else
if(damaging)
- current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
+ current.electrocute_act(bolt_energy, "Lightning Bolt", safety = TRUE)
else
current.AdjustJitter(1000) //High numbers for violent convulsions
current.do_jitter_animation(current.jitteriness)
diff --git a/code/datums/spells/night_vision.dm b/code/datums/spells/night_vision.dm
new file mode 100644
index 00000000000..1327b4ffcee
--- /dev/null
+++ b/code/datums/spells/night_vision.dm
@@ -0,0 +1,27 @@
+/obj/effect/proc_holder/spell/targeted/night_vision
+ name = "Toggle Nightvision"
+ desc = "Toggle your nightvision mode."
+
+ charge_max = 10
+ clothes_req = 0
+
+ message = "You toggle your night vision!"
+ range = -1
+ include_user = 1
+
+/obj/effect/proc_holder/spell/targeted/night_vision/cast(list/targets, mob/user = usr)
+ for(var/mob/living/target in targets)
+ switch(target.lighting_alpha)
+ if (LIGHTING_PLANE_ALPHA_VISIBLE)
+ target.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
+ name = "Toggle Nightvision \[More]"
+ if (LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
+ target.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ name = "Toggle Nightvision \[Full]"
+ if (LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE)
+ target.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
+ name = "Toggle Nightvision \[OFF]"
+ else
+ target.lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
+ name = "Toggle Nightvision \[ON]"
+ target.update_sight()
diff --git a/code/datums/statclick.dm b/code/datums/statclick.dm
index c7273e4744b..11a3ed41ce3 100644
--- a/code/datums/statclick.dm
+++ b/code/datums/statclick.dm
@@ -1,12 +1,13 @@
-// Not TECHNICALLY a datum, but this should never be instantiated
-// outside of the stat panel
// Clickable stat() button
/obj/effect/statclick
var/target
-/obj/effect/statclick/New(ntarget, text)
- target = ntarget
+INITIALIZE_IMMEDIATE(/obj/effect/statclick)
+
+/obj/effect/statclick/Initialize(mapload, text, target)
+ . = ..()
name = text
+ src.target = target
/obj/effect/statclick/proc/update(text)
name = text
@@ -19,10 +20,6 @@
if(!is_admin(usr) || !target)
return
if(!class)
- if(istype(target, /datum/controller/process))
- class = "process"
- else if(istype(target, /datum/controller/processScheduler))
- class = "scheduler"
if(istype(target, /datum/controller/subsystem))
class = "subsystem"
else if(istype(target, /datum/controller))
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 26d8ec67ef0..387cc70f992 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -38,4 +38,18 @@
/datum/status_effect/void_price/tick()
playsound(owner, 'sound/weapons/bite.ogg', 50, 1)
- owner.adjustBruteLoss(3)
\ No newline at end of file
+ owner.adjustBruteLoss(3)
+
+/datum/status_effect/exercised
+ id = "Exercised"
+ duration = 1200
+ alert_type = null
+
+/datum/status_effect/exercised/on_creation(mob/living/new_owner, ...)
+ . = ..()
+ STOP_PROCESSING(SSfastprocess, src)
+ START_PROCESSING(SSprocessing, src) //this lasts 20 minutes, so SSfastprocess isn't needed.
+
+/datum/status_effect/exercised/Destroy()
+ . = ..()
+ STOP_PROCESSING(SSprocessing, src)
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index cfafa912b64..6e809b32606 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -7,4 +7,76 @@
/datum/status_effect/cultghost/tick()
if(owner.reagents)
- owner.reagents.del_reagent("holywater") //can't be deconverted
\ No newline at end of file
+ owner.reagents.del_reagent("holywater") //can't be deconverted
+
+/datum/status_effect/saw_bleed
+ id = "saw_bleed"
+ duration = -1 //removed under specific conditions
+ tick_interval = 6
+ alert_type = null
+ var/mutable_appearance/bleed_overlay
+ var/mutable_appearance/bleed_underlay
+ var/bleed_amount = 3
+ var/bleed_buildup = 3
+ var/delay_before_decay = 5
+ var/bleed_damage = 200
+ var/needs_to_bleed = FALSE
+
+/datum/status_effect/saw_bleed/Destroy()
+ if(owner)
+ owner.cut_overlay(bleed_overlay)
+ owner.underlays -= bleed_underlay
+ QDEL_NULL(bleed_overlay)
+ return ..()
+
+/datum/status_effect/saw_bleed/on_apply()
+ if(owner.stat == DEAD)
+ return FALSE
+ bleed_overlay = mutable_appearance('icons/effects/bleed.dmi', "bleed[bleed_amount]")
+ bleed_underlay = mutable_appearance('icons/effects/bleed.dmi', "bleed[bleed_amount]")
+ var/icon/I = icon(owner.icon, owner.icon_state, owner.dir)
+ var/icon_height = I.Height()
+ bleed_overlay.pixel_x = -owner.pixel_x
+ bleed_overlay.pixel_y = FLOOR(icon_height * 0.25, 1)
+ bleed_overlay.transform = matrix() * (icon_height/world.icon_size) //scale the bleed overlay's size based on the target's icon size
+ bleed_underlay.pixel_x = -owner.pixel_x
+ bleed_underlay.transform = matrix() * (icon_height/world.icon_size) * 3
+ bleed_underlay.alpha = 40
+ owner.add_overlay(bleed_overlay)
+ owner.underlays += bleed_underlay
+ return ..()
+
+/datum/status_effect/saw_bleed/tick()
+ if(owner.stat == DEAD)
+ qdel(src)
+ else
+ add_bleed(-1)
+
+/datum/status_effect/saw_bleed/proc/add_bleed(amount)
+ owner.cut_overlay(bleed_overlay)
+ owner.underlays -= bleed_underlay
+ bleed_amount += amount
+ if(bleed_amount)
+ if(bleed_amount >= 10)
+ needs_to_bleed = TRUE
+ qdel(src)
+ else
+ if(amount > 0)
+ tick_interval += delay_before_decay
+ bleed_overlay.icon_state = "bleed[bleed_amount]"
+ bleed_underlay.icon_state = "bleed[bleed_amount]"
+ owner.add_overlay(bleed_overlay)
+ owner.underlays += bleed_underlay
+ else
+ qdel(src)
+
+/datum/status_effect/saw_bleed/on_remove()
+ if(needs_to_bleed)
+ var/turf/T = get_turf(owner)
+ new /obj/effect/temp_visual/bleed/explode(T)
+ for(var/d in alldirs)
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(T, d)
+ playsound(T, "desceration", 200, 1, -1)
+ owner.adjustBruteLoss(bleed_damage)
+ else
+ new /obj/effect/temp_visual/bleed(get_turf(owner))
\ No newline at end of file
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index d312ff9d11d..dd478a8f64c 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -32,11 +32,11 @@
var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type)
A.attached_effect = src //so the alert can reference us, if it needs to
linked_alert = A //so we can reference the alert, if we need to
- GLOB.fast_processing.Add(src)
+ START_PROCESSING(SSfastprocess, src)
return TRUE
/datum/status_effect/Destroy()
- GLOB.fast_processing.Remove(src)
+ STOP_PROCESSING(SSfastprocess, src)
if(owner)
owner.clear_alert(id)
LAZYREMOVE(owner.status_effects, src)
@@ -44,7 +44,7 @@
owner = null
return ..()
-/datum/status_effect/proc/process()
+/datum/status_effect/process()
if(!owner)
qdel(src)
return
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 5330be00665..7a63fa1571f 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -1060,8 +1060,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/datum/supply_packs/organic/bar
name = "Bar Starter Kit"
contains = list(/obj/item/storage/box/drinkingglasses,
- /obj/item/circuitboard/soda,
- /obj/item/circuitboard/beer)
+ /obj/item/circuitboard/chem_dispenser/soda,
+ /obj/item/circuitboard/chem_dispenser/beer)
cost = 20
containername = "beer starter kit"
announce_beacons = list("Bar" = list("Bar"))
@@ -1073,6 +1073,12 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
containertype = /obj/structure/closet/critter/cow
containername = "cow crate"
+/datum/supply_packs/organic/pig
+ name = "Pig Crate"
+ cost = 25
+ containertype = /obj/structure/closet/critter/pig
+ containername = "pig crate"
+
/datum/supply_packs/organic/goat
name = "Goat Crate"
cost = 25
@@ -1102,7 +1108,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
name = "Cat Crate"
cost = 50 //Cats are worth as much as corgis.
containertype = /obj/structure/closet/critter/cat
- contains = list(/obj/item/clothing/accessory/petcollar)
+ contains = list(/obj/item/clothing/accessory/petcollar,
+ /obj/item/toy/cattoy)
containername = "cat crate"
/datum/supply_packs/organic/pug
@@ -1199,13 +1206,14 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/datum/supply_packs/organic/hydroponics/beekeeping_fullkit
name = "Beekeeping Starter Kit"
- contains = list(/obj/structure/beebox,
+ contains = list(/obj/structure/beebox/unwrenched,
/obj/item/honey_frame,
/obj/item/honey_frame,
/obj/item/honey_frame,
/obj/item/queen_bee/bought,
/obj/item/clothing/head/beekeeper_head,
- /obj/item/clothing/suit/beekeeper_suit)
+ /obj/item/clothing/suit/beekeeper_suit,
+ /obj/item/melee/flyswatter)
cost = 15
containername = "beekeeping starter kit"
@@ -1354,6 +1362,14 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
cost = 40
containername = "religious supplies crate"
+/datum/supply_packs/misc/minerkit
+ name = "Shaft Miner Starter Kit"
+ cost = 30
+ access = access_qm
+ contains = list(/obj/item/storage/backpack/duffel/mining_conscript/noid)
+ containertype = /obj/structure/closet/crate/secure
+ containername = "shaft miner starter kit"
+
///////////// Paper Work
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 392908127d0..4c1fb437046 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -12,9 +12,9 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
var/datum/uplink_item/I = new path
if(!I.item)
continue
- if(I.gamemodes.len && ticker && !(ticker.mode.type in I.gamemodes))
+ if(I.gamemodes.len && SSticker && !(SSticker.mode.type in I.gamemodes))
continue
- if(I.excludefrom.len && ticker && (ticker.mode.type in I.excludefrom))
+ if(I.excludefrom.len && SSticker && (SSticker.mode.type in I.excludefrom))
continue
if(I.last)
last += I
@@ -88,9 +88,9 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/uplink/U)
- if(hijack_only)
+ if(hijack_only && !(usr.mind.special_role == SPECIAL_ROLE_NUKEOPS))//nukies get items that regular traitors only get with hijack. If a hijack-only item is not for nukies, then exclude it via the gamemode list.
if(!(locate(/datum/objective/hijack) in usr.mind.objectives))
- to_chat(usr, "The Syndicate lacks resources to provide you with this item.")
+ to_chat(usr, "The Syndicate will only issue this extremely dangerous item to agents assigned the Hijack objective.")
return
if(item)
@@ -182,6 +182,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 3
job = list("Clown")
+/datum/uplink_item/jobspecific/trick_revolver
+ name = "Trick Revolver"
+ desc = "A revolver that will fire backwards and kill whoever attempts to use it. Perfect for those pesky vigilante or just a good laugh."
+ reference = "CTR"
+ item = /obj/item/storage/box/syndie_kit/fake_revolver
+ cost = 1
+ job = list("Clown")
+
//mime
/datum/uplink_item/jobspecific/caneshotgun
name = "Cane Shotgun and Assassination Shells"
@@ -433,7 +441,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/dangerous
category = "Highly Visible and Dangerous Weapons"
-
/datum/uplink_item/dangerous/pistol
name = "FK-69 Pistol"
reference = "SPI"
@@ -551,37 +558,66 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/batterer
cost = 5
-/datum/uplink_item/dangerous/gygax
+// SUPPORT AND MECHAS
+
+/datum/uplink_item/support
+ category = "Support and Mechanized Exosuits"
+ surplus = 0
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/support/gygax
name = "Gygax Exosuit"
desc = "A lightweight exosuit, painted in a dark scheme. Its speed and equipment selection make it excellent for hit-and-run style attacks. \
This model lacks a method of space propulsion, and therefore it is advised to repair the mothership's teleporter if you wish to make use of it."
reference = "GE"
item = /obj/mecha/combat/gygax/dark/loaded
cost = 90
- gamemodes = list(/datum/game_mode/nuclear)
- surplus = 0
-/datum/uplink_item/dangerous/mauler
+/datum/uplink_item/support/mauler
name = "Mauler Exosuit"
desc = "A massive and incredibly deadly Syndicate exosuit. Features long-range targeting, thrust vectoring, and deployable smoke."
reference = "ME"
item = /obj/mecha/combat/marauder/mauler/loaded
cost = 140
- gamemodes = list(/datum/game_mode/nuclear)
- surplus = 0
-/datum/uplink_item/dangerous/syndieborg
- name = "Syndicate Cyborg"
- desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel. Comes in Assault, Medical, or Saboteur variants."
- reference = "SC"
- item = /obj/item/antag_spawner/borg_tele
- refund_path = /obj/item/antag_spawner/borg_tele
- cost = 50
- gamemodes = list(/datum/game_mode/nuclear)
- surplus = 0
+/datum/uplink_item/support/reinforcement
+ name = "Reinforcement"
+ desc = "Call in an additional team member. They won't come with any gear, so you'll have to save some telecrystals \
+ to arm them as well."
+ reference = "REINF"
+ item = /obj/item/antag_spawner/nuke_ops
+ refund_path = /obj/item/antag_spawner/nuke_ops
+ cost = 25
refundable = TRUE
cant_discount = TRUE
+/datum/uplink_item/support/reinforcement/assault_borg
+ name = "Syndicate Assault Cyborg"
+ desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel. \
+ Comes equipped with a self-resupplying LMG, a grenade launcher, energy sword, emag, pinpointer, flash and crowbar."
+ reference = "SAC"
+ item = /obj/item/antag_spawner/nuke_ops/borg_tele/assault
+ refund_path = /obj/item/antag_spawner/nuke_ops/borg_tele/assault
+ cost = 65
+
+/datum/uplink_item/support/reinforcement/medical_borg
+ name = "Syndicate Medical Cyborg"
+ desc = "A combat medical cyborg. Has limited offensive potential, but makes more than up for it with its support capabilities. \
+ It comes equipped with a nanite hypospray, a medical beamgun, combat defibrillator, full surgical kit including an energy saw, an emag, pinpointer and flash. \
+ Thanks to its organ storage bag, it can perform surgery as well as any humanoid."
+ reference = "SMC"
+ item = /obj/item/antag_spawner/nuke_ops/borg_tele/medical
+ refund_path = /obj/item/antag_spawner/nuke_ops/borg_tele/medical
+ cost = 35
+
+/datum/uplink_item/support/reinforcement/saboteur_borg
+ name = "Syndicate Saboteur Cyborg"
+ desc = "A streamlined engineering cyborg, equipped with covert modules and engineering equipment. Also incapable of leaving the welder in the shuttle. \
+ Its chameleon projector lets it disguise itself as a Nanotrasen cyborg, on top it has thermal vision and a pinpointer."
+ reference = "SSC"
+ item = /obj/item/antag_spawner/nuke_ops/borg_tele/saboteur
+ refund_path = /obj/item/antag_spawner/nuke_ops/borg_tele/saboteur
+
/datum/uplink_item/dangerous/foamsmg
name = "Toy Submachine Gun"
desc = "A fully-loaded Donksoft bullpup submachine gun that fires riot grade rounds with a 20-round magazine."
@@ -645,15 +681,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/ammo_box/magazine/m10mm/hp
cost = 3
-/datum/uplink_item/ammo/ammobag
- name = "Bulldog - Shotgun Ammo Grab Bag"
- desc = "A duffelbag filled with Bulldog ammo to kit out an entire team, at a discounted price."
- reference = "SAGL"
- item = /obj/item/storage/backpack/duffel/syndie/ammo/loaded
- cost = 10 //bulk buyer's discount. Very useful if you're buying a mech and dont have TC left to buy people non-shotgun guns
- gamemodes = list(/datum/game_mode/nuclear)
- cant_discount = TRUE
-
/datum/uplink_item/ammo/bullslug
name = "Bulldog - 12g Slug Magazine"
desc = "An additional 8-round slug magazine for use in the Bulldog shotgun. Now 8 times less likely to shoot your pals."
@@ -686,6 +713,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
gamemodes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/ammo/bulldog_ammobag
+ name = "Bulldog - 12g Ammo Duffel Bag"
+ desc = "A duffel bag filled with enough 12g ammo to supply an entire team, at a discounted price."
+ reference = "12ADB"
+ item = /obj/item/storage/backpack/duffel/syndie/ammo/shotgun
+ cost = 12 // normally 18
+ gamemodes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/ammo/smg
name = "C-20r - .45 Magazine"
desc = "An additional 20-round .45 magazine for use in the C-20r submachine gun. These bullets pack a lot of punch that can knock most targets down, but do limited overall damage."
@@ -694,6 +729,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
gamemodes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/ammo/smg_ammobag
+ name = "C-20r - .45 Ammo Duffel Bag"
+ desc = "A duffel bag filled with enough .45 ammo to supply an entire team, at a discounted price."
+ reference = "45ADB"
+ item = /obj/item/storage/backpack/duffel/syndie/ammo/smg
+ cost = 14 // normally 20
+ gamemodes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/ammo/carbine
name = "Carbine - 5.56 Toploader Magazine"
desc = "An additional 30-round 5.56 magazine for use in the M-90gl carbine. These bullets don't have the punch to knock most targets down, but dish out higher overall damage."
@@ -805,7 +848,9 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing. Does not restrict weapon usage, but cannot be used alongside Gloves of the North Star."
reference = "CQC"
item = /obj/item/CQC_manual
- cost = 9
+ gamemodes = list(/datum/game_mode/nuclear)
+ cost = 13
+ surplus = 0
/datum/uplink_item/stealthy_weapons/cameraflash
name = "Camera Flash"
@@ -885,7 +930,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
desc = "Just add water to make your very own hostile to everything space carp. It looks just like a plushie. The first person to squeeze it will be registered as its owner, who it will not attack. If no owner is registered, it'll just attack everyone."
reference = "DSC"
item = /obj/item/toy/carpplushie/dehy_carp
- cost = 3
+ cost = 2
// GRENADES AND EXPLOSIVES
@@ -906,6 +951,15 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/storage/box/syndie_kit/c4
cost = 4
+/datum/uplink_item/explosives/c4bag
+ name = "Bag of C-4 explosives"
+ desc = "Because sometimes quantity is quality. Contains 10 C-4 plastic explosives."
+ reference = "C4B"
+ item = /obj/item/storage/backpack/duffel/syndie/c4
+ cost = 8 //20% discount!
+ cant_discount = TRUE
+ gamemodes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/explosives/breaching_charge
name = "Composition X-4"
desc = "X-4 is a shaped charge designed to be safe to the user while causing maximum damage to the occupants of the room beach breached. It has a modifiable timer with a minimum setting of 10 seconds."
@@ -914,6 +968,17 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
gamemodes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/explosives/x4bag
+ name = "Bag of X-4 explosives"
+ desc = "Contains 3 X-4 shaped plastic explosives. Similar to C4, but with a stronger blast that is directional instead of circular. \
+ X-4 can be placed on a solid surface, such as a wall or window, and it will blast through the wall, injuring anything on the opposite side, while being safer to the user. \
+ For when you want a controlled explosion that leaves a wider, deeper, hole."
+ reference = "X4B"
+ item = /obj/item/storage/backpack/duffel/syndie/x4
+ cost = 4
+ cant_discount = TRUE
+ gamemodes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/explosives/syndicate_bomb
name = "Syndicate Bomb"
desc = "The Syndicate Bomb has an adjustable timer with a minimum setting of 60 seconds. Ordering the bomb sends you a small beacon, which will teleport the explosive to your location when you activate it. \
@@ -921,6 +986,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
reference = "SB"
item = /obj/item/radio/beacon/syndicate/bomb
cost = 11
+ surplus = 0
+ cant_discount = TRUE
/datum/uplink_item/explosives/syndicate_minibomb
name = "Syndicate Minibomb"
@@ -970,13 +1037,22 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
-/datum/uplink_item/explosives/atmosgrenades
- name = "Atmos Grenades"
- desc = "A box of two (2) grenades that wreak havoc with the atmosphere of the target area. Capable of engulfing a large area in lit plasma, or N2O. Deploy with extreme caution!"
- reference = "AGG"
- item = /obj/item/storage/box/syndie_kit/atmosgasgrenades
- cost = 11
+/datum/uplink_item/explosives/atmosn2ogrenades
+ name = "Knockout Gas Grenades"
+ desc = "A box of two (2) grenades that spread knockout gas over a large area. Equip internals before using one of these."
+ reference = "ANG"
+ item = /obj/item/storage/box/syndie_kit/atmosn2ogrenades
+ cost = 8
+
+/datum/uplink_item/explosives/atmosfiregrenades
+ name = "Plasma Fire Grenades"
+ desc = "A box of two (2) grenades that cause large plasma fires. Can be used to deny access to a large area. Most useful if you have an atmospherics hardsuit."
+ reference = "APG"
+ item = /obj/item/storage/box/syndie_kit/atmosfiregrenades
+ hijack_only = TRUE
+ cost = 12
surplus = 0
+ cant_discount = TRUE
/datum/uplink_item/explosives/emp
name = "EMP Grenades and Implanter Kit"
@@ -991,13 +1067,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/stealthy_tools
category = "Stealth and Camouflage Items"
-/datum/uplink_item/stealthy_tools/chameleon_jumpsuit
- name = "Chameleon Jumpsuit"
- desc = "A jumpsuit used to imitate the uniforms of Nanotrasen crewmembers."
- reference = "CJ"
- item = /obj/item/clothing/under/chameleon
- cost = 2
-
/datum/uplink_item/stealthy_tools/chameleon_stamp
name = "Chameleon Stamp"
desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \
@@ -1016,20 +1085,19 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 35
/datum/uplink_item/stealthy_tools/syndigaloshes
- name = "No-Slip Syndicate Shoes"
- desc = "These allow you to run on wet floors. They do not work on lubricated surfaces."
+ name = "No-Slip Chameleon Shoes"
+ desc = "These shoes will allow the wearer to run on wet floors and slippery objects without falling down. \
+ They do not work on heavily lubricated surfaces."
reference = "NSSS"
- item = /obj/item/clothing/shoes/syndigaloshes
+ item = /obj/item/clothing/shoes/chameleon/noslip
cost = 2
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/syndigaloshes/nuke
- name = "Tactical No-Slip Brown Shoes"
- desc = "These allow you to run on wet floors. They do not work on lubricated surfaces, and the maker swears they're better than normal ones, somehow."
- reference = "NNSSS"
+ reference = "TNSSS"
cost = 4 //but they aren't
- gamemodes = list(/datum/game_mode/nuclear)
excludefrom = list()
+ gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/chamsechud
name = "Chameleon Security HUD"
@@ -1039,10 +1107,10 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
/datum/uplink_item/stealthy_tools/thermal
- name = "Thermal Imaging Glasses"
- desc = "These glasses are thermals disguised as engineers' optical meson scanners. They allow you to see organisms through walls by capturing the upper portion of the infra-red light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
+ name = "Thermal Chameleon Glasses"
+ desc = "These glasses are thermals with Syndicate chameleon technology built into them. They allow you to see organisms through walls by capturing the upper portion of the infra-red light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
reference = "THIG"
- item = /obj/item/clothing/glasses/thermal/syndi
+ item = /obj/item/clothing/glasses/chameleon/thermal
cost = 6
/datum/uplink_item/stealthy_tools/traitor_belt
@@ -1070,12 +1138,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/card/id/syndicate
cost = 2
-/datum/uplink_item/stealthy_tools/voice_changer
- name = "Voice Changer"
- desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognisable."
- reference = "VC"
- item = /obj/item/clothing/mask/gas/voice
- cost = 3
+/datum/uplink_item/stealthy_tools/chameleon
+ name = "Chameleon Kit"
+ desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! \
+ Due to budget cuts, the shoes don't provide protection against slipping. The set comes with a complementary chameleon stamp."
+ reference = "CHAM"
+ item = /obj/item/storage/box/syndie_kit/chameleon
+ cost = 2
/datum/uplink_item/stealthy_tools/chameleon_proj
name = "Chameleon-Projector"
@@ -1134,7 +1203,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/stealthy_tools/clownkit
name = "Honk Brand Infiltration Kit"
- desc = "All the tools you need to play the best prank Nanotrasen has ever seen. Includes a voice changer clown mask, magnetic clown shoes, and standard clown outfit, tools, and backpack."
+ desc = "All the tools you need to play the best prank Nanotrasen has ever seen. Includes a voice changer mask, magnetic clown shoes, and standard clown outfit, tools, and backpack."
reference = "HBIK"
item = /obj/item/storage/backpack/clown/syndie
cost = 6
@@ -1311,13 +1380,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 0
hijack_only = TRUE //This is an item only useful for a hijack traitor, as such, it should only be available in those scenarios.
cant_discount = TRUE
- excludefrom = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/device_tools/singularity_beacon/nuke
- reference = "SNGBN"
- hijack_only = FALSE // This inherited version exists so nukies can use it while keeping the original hijack only
- excludefrom = list()
- gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/device_tools/syndicate_detonator
name = "Syndicate Detonator"
@@ -1342,37 +1404,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/multitool/ai_detect
cost = 1
-/datum/uplink_item/device_tools/telecrystal
- name = "Raw Telecrystal"
- desc = "Telecrystal in its rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- reference = "RTC"
- item = /obj/item/stack/telecrystal
- cost = 1
- surplus = 0
- cant_discount = TRUE
-
-/datum/uplink_item/device_tools/telecrystal/five
- name = "5 Raw Telecrystals"
- desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- reference = "RTCF"
- item = /obj/item/stack/telecrystal/five
- cost = 5
-
-/datum/uplink_item/device_tools/telecrystal/twenty
- name = "20 Raw Telecrystals"
- desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- reference = "RTCT"
- item = /obj/item/stack/telecrystal/twenty
- cost = 20
-
-/datum/uplink_item/device_tools/telecrystal/fifty
- name = "50 Raw Telecrystals"
- desc = "Fifty telecrystals in their rawest and purest form. You know you want that Mauler."
- reference = "RTCB"
- item = /obj/item/stack/telecrystal/fifty
- cost = 50
- gamemodes = list(/datum/game_mode/nuclear)
-
/datum/uplink_item/device_tools/jammer
name = "Radio Jammer"
desc = "This device will disrupt any nearby outgoing radio communication when activated."
@@ -1409,7 +1440,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/device_tools/medgun
name = "Medbeam Gun"
- desc = "Medical Beam Gun, useful in prolonged firefights."
+ desc = "Medical Beam Gun, useful in prolonged firefights. DO NOT CROSS THE BEAMS. Crossing beams with another medbeam or attaching two beams to one target will have explosive consequences."
item = /obj/item/gun/medbeam
reference = "MBG"
cost = 15
@@ -1472,11 +1503,10 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
category = "Cybernetic Implants"
surplus = 0
gamemodes = list(/datum/game_mode/nuclear)
- var/cyber_bundle = FALSE
/datum/uplink_item/cyber_implants/spawn_item(turf/loc, obj/item/uplink/U)
if(item)
- if(findtext(item, /obj/item/organ/internal/cyberimp) && !cyber_bundle)
+ if(findtext(item, /obj/item/organ/internal/cyberimp))
U.uses -= max(cost, 0)
U.used_TC += cost
feedback_add_details("traitor_uplink_items_bought", name) //this one and the line before copypasted because snowflaek code
@@ -1507,22 +1537,12 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 12
/datum/uplink_item/cyber_implants/reviver
- name = "Reviver Implant"
- desc = "This implant will attempt to revive you if you lose consciousness. Comes with an automated implanting tool."
+ name = "Hardened Reviver Implant"
+ desc = "This implant will attempt to revive you if you lose consciousness. It is invulnerable to EMPs. Comes with an automated implanting tool."
reference = "CIR"
- item = /obj/item/organ/internal/cyberimp/chest/reviver
+ item = /obj/item/organ/internal/cyberimp/chest/reviver/hardened
cost = 8
-/datum/uplink_item/cyber_implants/bundle
- name = "Cybernetic Implants Bundle"
- desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. \
- Comes with an automated implanting tool."
- reference = "CIB"
- item = /obj/item/storage/box/cyber_implants/bundle
- cost = 40
- cyber_bundle = TRUE
- cant_discount = TRUE
-
// POINTLESS BADASSERY
/datum/uplink_item/badass
@@ -1536,15 +1556,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/storage/fancy/cigarettes/cigpack_syndicate
cost = 2
-/datum/uplink_item/badass/bundle
- name = "Syndicate Bundle"
- desc = "Syndicate Bundles are specialised groups of items that arrive in a plain box. These items are collectively worth more than 20 telecrystals, but you do not know which specialisation you will receive."
- reference = "SYB"
- item = /obj/item/storage/box/syndicate
- cost = 20
- excludefrom = list(/datum/game_mode/nuclear)
- cant_discount = TRUE
-
/datum/uplink_item/badass/syndiecards
name = "Syndicate Playing Cards"
desc = "A special deck of space-grade playing cards with a mono-molecular edge and metal reinforcement, making them lethal weapons both when wielded as a blade and when thrown. \
@@ -1587,50 +1598,81 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 20
gamemodes = list(/datum/game_mode/nuclear)
-/*/datum/uplink_item/badass/random
- name = "Random Item"
- desc = "Picking this choice will send you a random item from the list. Useful for when you cannot think of a strategy to finish your objectives with."
- reference = "RAIT"
+/datum/uplink_item/bundles_TC
+ category = "Bundles and Telecrystals"
+ surplus = 0
+ cant_discount = TRUE
+
+/datum/uplink_item/bundles_TC/bulldog
+ name = "Bulldog Bundle"
+ desc = "Lean and mean: Optimized for people that want to get up close and personal. Contains the popular \
+ Bulldog shotgun, two 12g buckshot drums, and a pair of Thermal imaging goggles."
+ reference = "BULB"
+ item = /obj/item/storage/backpack/duffel/syndie/bulldogbundle
+ cost = 9 // normally 12
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/c20r
+ name = "C-20r Bundle"
+ desc = "Old Faithful: The classic C-20r, bundled with two magazines and a (surplus) suppressor at discount price."
+ reference = "C20B"
+ item = /obj/item/storage/backpack/duffel/syndie/c20rbundle
+ cost = 14 // normally 17
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/cyber_implants
+ name = "Cybernetic Implants Bundle"
+ desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. \
+ Comes with an automated implanting tool."
+ reference = "CIB"
+ item = /obj/item/storage/box/cyber_implants/bundle
+ cost = 40
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/medical
+ name = "Medical Bundle"
+ desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a tactical medkit, \
+ a Donksoft LMG and a box of riot darts."
+ reference = "MEDB"
+ item = /obj/item/storage/backpack/duffel/syndie/med/medicalbundle
+ cost = 15 // normally 20
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/sniper
+ name = "Sniper bundle"
+ desc = "Elegant and refined: Contains a collapsed sniper rifle in an expensive carrying case, \
+ two soporific knockout magazines, a free surplus suppressor, and a sharp-looking tactical turtleneck suit. \
+ We'll throw in a free red tie if you order NOW."
+ reference = "SNPB"
+ item = /obj/item/storage/briefcase/sniperbundle
+ cost = 18 // normally 23
+ gamemodes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/badass
+ name = "Syndicate Bundle"
+ desc = "Syndicate Bundles are specialised groups of items that arrive in a plain box. These items are collectively worth more than 20 telecrystals, but you do not know which specialisation you will receive."
+ reference = "SYB"
item = /obj/item/storage/box/syndicate
- cost = 0
+ cost = 20
+ excludefrom = list(/datum/game_mode/nuclear)
-/datum/uplink_item/badass/random/spawn_item(var/turf/loc, var/obj/item/uplink/U)
-
- var/list/buyable_items = get_uplink_items()
- var/list/possible_items = list()
-
- for(var/category in buyable_items)
- for(var/datum/uplink_item/I in buyable_items[category])
- if(I == src)
- continue
- if(I.cost > U.uses)
- continue
- possible_items += I
-
- if(possible_items.len)
- var/datum/uplink_item/I = pick(possible_items)
- U.uses -= max(0, I.cost)
- feedback_add_details("traitor_uplink_items_bought","RN")
- return new I.item(loc) */
-
-/datum/uplink_item/badass/surplus_crate
+/datum/uplink_item/bundles_TC/surplus_crate
name = "Syndicate Surplus Crate"
desc = "A crate containing 50 telecrystals worth of random syndicate leftovers."
reference = "SYSC"
cost = 20
item = /obj/item/storage/box/syndicate
excludefrom = list(/datum/game_mode/nuclear)
- cant_discount = TRUE // You fucking wish
var/crate_value = 50
-/datum/uplink_item/badass/surplus_crate/super
+/datum/uplink_item/bundles_TC/surplus_crate/super
name = "Syndicate Super Surplus Crate"
desc = "A crate containing 125 telecrystals worth of random syndicate leftovers."
reference = "SYSS"
cost = 40
crate_value = 125
-/datum/uplink_item/badass/surplus_crate/spawn_item(turf/loc, obj/item/uplink/U)
+/datum/uplink_item/bundles_TC/surplus_crate/spawn_item(turf/loc, obj/item/uplink/U)
var/obj/structure/closet/crate/C = new(loc)
var/list/temp_uplink_list = get_uplink_items()
var/list/buyable_items = list()
@@ -1660,3 +1702,32 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
new item(C)
U.purchase_log += "[bicon(item)]"
log_game("[key_name(usr)] purchased a surplus crate with [jointext(itemlog, ", ")]")
+
+/datum/uplink_item/bundles_TC/telecrystal
+ name = "Raw Telecrystal"
+ desc = "Telecrystal in its rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ reference = "RTC"
+ item = /obj/item/stack/telecrystal
+ cost = 1
+
+/datum/uplink_item/bundles_TC/telecrystal/five
+ name = "5 Raw Telecrystals"
+ desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ reference = "RTCF"
+ item = /obj/item/stack/telecrystal/five
+ cost = 5
+
+/datum/uplink_item/bundles_TC/telecrystal/twenty
+ name = "20 Raw Telecrystals"
+ desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ reference = "RTCT"
+ item = /obj/item/stack/telecrystal/twenty
+ cost = 20
+
+/datum/uplink_item/bundles_TC/telecrystal/fifty
+ name = "50 Raw Telecrystals"
+ desc = "Fifty telecrystals in their rawest and purest form. You know you want that Mauler."
+ reference = "RTCB"
+ item = /obj/item/stack/telecrystal/fifty
+ cost = 50
+ gamemodes = list(/datum/game_mode/nuclear)
\ No newline at end of file
diff --git a/code/datums/vision_override.dm b/code/datums/vision_override.dm
index 140ceb8d5fa..86aab6d65ec 100644
--- a/code/datums/vision_override.dm
+++ b/code/datums/vision_override.dm
@@ -1,13 +1,15 @@
/datum/vision_override
var/name = "vision override"
- var/see_in_dark = 0
- var/see_invisible = 0
- var/light_sensitive = 0
+
var/sight_flags = 0
+ var/see_in_dark = 0
+ var/lighting_alpha
+
+ var/light_sensitive = 0
/datum/vision_override/nightvision
see_in_dark = 8
- see_invisible = SEE_INVISIBLE_MINIMUM
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
/datum/vision_override/nightvision/thermals
sight_flags = SEE_MOBS
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
index 2f3a4c4bcba..6d36b81f7b4 100644
--- a/code/datums/weather/weather.dm
+++ b/code/datums/weather/weather.dm
@@ -28,6 +28,7 @@
var/impacted_z_levels // The list of z-levels that this weather is actively affecting
var/overlay_layer = AREA_LAYER //Since it's above everything else, this is the layer used by default. TURF_LAYER is below mobs and walls if you need to use that.
+ var/overlay_plane = BLACKNESS_PLANE
var/aesthetic = FALSE //If the weather has no purpose other than looks
var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather
@@ -106,6 +107,8 @@
/datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob?
var/turf/mob_turf = get_turf(L)
+ if(!istype(L))
+ return
if(mob_turf && !(mob_turf.z in impacted_z_levels))
return
if(immunity_type in L.weather_immunities)
@@ -121,6 +124,7 @@
for(var/V in impacted_areas)
var/area/N = V
N.layer = overlay_layer
+ N.plane = overlay_plane
N.icon = 'icons/effects/weather_effects.dmi'
N.invisibility = 0
N.color = weather_color
@@ -135,6 +139,6 @@
N.color = null
N.icon_state = ""
N.icon = 'icons/turf/areas.dmi'
- N.layer = AREA_LAYER //Just default back to normal area stuff since I assume setting a var is faster than initial
- N.invisibility = INVISIBILITY_MAXIMUM
+ N.layer = initial(N.layer)
+ N.plane = initial(N.plane)
N.set_opacity(FALSE)
diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm
index 3f4c57c4196..dbc75cb9bf0 100644
--- a/code/datums/weather/weather_types/ash_storm.dm
+++ b/code/datums/weather/weather_types/ash_storm.dm
@@ -16,12 +16,12 @@
end_duration = 300
end_overlay = "light_ash"
- area_type = /area/mine/dangerous // /area/lavaland/surface/outdoors
+ area_type = /area/lavaland/surface/outdoors
target_trait = ORE_LEVEL
immunity_type = "ash"
-// probability = 90
+ probability = 90
barometer_predictable = TRUE
@@ -81,7 +81,7 @@
if(ishuman(L)) //Are you immune?
var/mob/living/carbon/human/H = L
var/thermal_protection = H.get_thermal_protection()
- if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
+ if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
return TRUE
L = L.loc //Matryoshka check
return FALSE //RIP you
@@ -105,4 +105,4 @@
aesthetic = TRUE
-// probability = 10
\ No newline at end of file
+ probability = 10
\ No newline at end of file
diff --git a/code/datums/weather/weather_types/floor_is_lava.dm b/code/datums/weather/weather_types/floor_is_lava.dm
index 6d06e3ca1ef..72f49ad5057 100644
--- a/code/datums/weather/weather_types/floor_is_lava.dm
+++ b/code/datums/weather/weather_types/floor_is_lava.dm
@@ -19,6 +19,7 @@
target_trait = STATION_LEVEL
overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
+ overlay_plane = FLOOR_PLANE
immunity_type = "lava"
diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm
index 3c3906a25eb..3a70d05029e 100644
--- a/code/defines/procs/announce.dm
+++ b/code/defines/procs/announce.dm
@@ -95,7 +95,7 @@
receivers -= M
garbled_receivers |= M
for(var/mob/M in GLOB.dead_mob_list)
- if(M.client && M.stat == DEAD)
+ if(M.client && M.stat == DEAD && !isnewplayer(M))
receivers |= M
return list(receivers, garbled_receivers)
diff --git a/code/defines/procs/radio.dm b/code/defines/procs/radio.dm
index f41bea79048..84d3ddaae78 100644
--- a/code/defines/procs/radio.dm
+++ b/code/defines/procs/radio.dm
@@ -13,8 +13,8 @@
if(SYNDTEAM_FREQ)
freq_text = "#unid"
else
- for(var/channel in radiochannels)
- if(radiochannels[channel] == display_freq)
+ for(var/channel in SSradio.radiochannels)
+ if(SSradio.radiochannels[channel] == display_freq)
freq_text = channel
break
diff --git a/code/game/area/Dynamic areas.dm b/code/game/area/Dynamic areas.dm
index 1cb24e23512..c6d1154847b 100644
--- a/code/game/area/Dynamic areas.dm
+++ b/code/game/area/Dynamic areas.dm
@@ -24,18 +24,21 @@
match_tag = "arrivals"
match_width = 5
match_height = 4
- requires_power = 0
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/dynamic/source/lobby_russian
name = "\improper Russian Lounge"
match_tag = "arrivals"
match_width = 5
match_height = 4
- requires_power = 0
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/dynamic/source/lobby_disco
name = "\improper Disco Lounge"
match_tag = "arrivals"
match_width = 5
match_height = 4
- requires_power = 0
\ No newline at end of file
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
\ No newline at end of file
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 067223c0285..d5b4faef17c 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -1,2730 +1,2350 @@
-/*
-
-### This file contains a list of all the areas in your station. Format is as follows:
-
-/area/CATEGORY/OR/DESCRIPTOR/NAME (you can make as many subdivisions as you want)
- name = "NICE NAME" (not required but makes things really nice)
- icon = "ICON FILENAME" (defaults to areas.dmi)
- icon_state = "NAME OF ICON" (defaults to "unknown" (blank))
- requires_power = 0 (defaults to 1)
- music = "music/music.ogg" (defaults to "music/music.ogg")
-
-NOTE: there are two lists of areas in the end of this file: centcom and station itself. Please maintain these lists valid. --rastaf0
-
-*/
-
-
-
-/area
- var/fire = null
- var/atmosalm = ATMOS_ALARM_NONE
- var/poweralm = 1
- var/party = null
- var/report_alerts = 1 // Should atmos alerts notify the AI/computers
- level = null
- name = "Space"
- icon = 'icons/turf/areas.dmi'
- icon_state = "unknown"
- layer = AREA_LAYER
- luminosity = 0
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- invisibility = INVISIBILITY_LIGHTING
- var/valid_territory = TRUE //used for cult summoning areas on station zlevel
- var/map_name // Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
- var/lightswitch = 1
-
- var/eject = null
-
- var/debug = 0
- var/requires_power = 1
- var/always_unpowered = 0 //this gets overriden to 1 for space in area/New()
-
- var/power_equip = 1
- var/power_light = 1
- var/power_environ = 1
- var/music = null
- var/used_equip = 0
- var/used_light = 0
- var/used_environ = 0
- var/static_equip
- var/static_light = 0
- var/static_environ
-
- var/has_gravity = 1
- var/list/apc = list()
- var/no_air = null
-// var/list/lights // list of all lights on this area
- var/air_doors_activated = 0
-
- var/tele_proof = 0
- var/no_teleportlocs = 0
-
- var/outdoors = 0 //For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room)
- var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
- var/nad_allowed = FALSE //is the station NAD allowed on this area?
-
-/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
-/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
-var/list/teleportlocs = list()
-/hook/startup/proc/process_teleport_locs()
- for(var/area/AR in world)
- if(AR.no_teleportlocs) continue
- if(teleportlocs.Find(AR.name)) continue
- var/turf/picked = safepick(get_area_turfs(AR.type))
- if(picked && is_station_level(picked.z))
- teleportlocs += AR.name
- teleportlocs[AR.name] = AR
-
- teleportlocs = sortAssoc(teleportlocs)
-
- return 1
-
-var/list/ghostteleportlocs = list()
-/hook/startup/proc/process_ghost_teleport_locs()
- for(var/area/AR in world)
- if(ghostteleportlocs.Find(AR.name)) continue
- var/list/turfs = get_area_turfs(AR.type)
- if(turfs.len)
- ghostteleportlocs += AR.name
- ghostteleportlocs[AR.name] = AR
-
- ghostteleportlocs = sortAssoc(ghostteleportlocs)
-
- return 1
-
-/*-----------------------------------------------------------------------------*/
-
-/area/engine/
-
-/area/turret_protected/
-
-/area/arrival
- requires_power = 0
-
-/area/arrival/start
- name = "\improper Arrival Area"
- icon_state = "start"
-
-/area/admin/
- name = "\improper Admin Room"
- icon_state = "start"
- requires_power = 0
- dynamic_lighting = 0
-
-
-/area/adminconstruction
- name = "\improper Admin Testing Area"
- icon_state = "start"
- requires_power = 0
- dynamic_lighting = 0
-
-/area/space
- icon_state = "space"
- requires_power = 1
- always_unpowered = 1
- power_light = 0
- power_equip = 0
- power_environ = 0
- valid_territory = FALSE
- outdoors = 1
- ambientsounds = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/traitor.ogg')
-
-/area/space/atmosalert()
- return
-
-/area/space/fire_alert()
- return
-
-/area/space/fire_reset()
- return
-
-/area/space/readyalert()
- return
-
-/area/space/partyalert()
- return
-
-//These are shuttle areas, they must contain two areas in a subgroup if you want to move a shuttle from one
-//place to another. Look at escape shuttle for example.
-//All shuttles show now be under shuttle since we have smooth-wall code.
-
-/area/shuttle
- no_teleportlocs = 1
- requires_power = 0
- valid_territory = FALSE
-
-/area/shuttle/arrival
- name = "\improper Arrival Shuttle"
-
-/area/shuttle/arrival/pre_game
- icon_state = "shuttle2"
-
-/area/shuttle/arrival/station
- icon_state = "shuttle"
-
-/area/shuttle/auxillary_base
- icon_state = "shuttle"
-
-/area/shuttle/escape
- name = "\improper Emergency Shuttle"
- music = "music/escape.ogg"
- icon_state = "shuttle2"
- nad_allowed = TRUE
-
-/area/shuttle/pod_1
- name = "\improper Escape Pod One"
- music = "music/escape.ogg"
- icon_state = "shuttle"
- nad_allowed = TRUE
-
-/area/shuttle/pod_2
- name = "\improper Escape Pod Two"
- music = "music/escape.ogg"
- icon_state = "shuttle"
- nad_allowed = TRUE
-
-/area/shuttle/pod_3
- name = "\improper Escape Pod Three"
- music = "music/escape.ogg"
- icon_state = "shuttle"
- nad_allowed = TRUE
-
-/area/shuttle/pod_4
- name = "\improper Escape Pod Four"
- music = "music/escape.ogg"
- icon_state = "shuttle"
- nad_allowed = TRUE
-
-/area/shuttle/escape_pod1
- name = "\improper Escape Pod One"
- music = "music/escape.ogg"
- nad_allowed = TRUE
-
-/area/shuttle/escape_pod1/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod1/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod1/transit
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod2
- name = "\improper Escape Pod Two"
- music = "music/escape.ogg"
- nad_allowed = TRUE
-
-/area/shuttle/escape_pod2/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod2/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod2/transit
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod3
- name = "\improper Escape Pod Three"
- music = "music/escape.ogg"
- nad_allowed = TRUE
-
-/area/shuttle/escape_pod3/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod3/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod3/transit
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod5 //Pod 4 was lost to meteors
- name = "\improper Escape Pod Five"
- music = "music/escape.ogg"
- nad_allowed = TRUE
-
-/area/shuttle/escape_pod5/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod5/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod5/transit
- icon_state = "shuttle"
-
-/area/shuttle/mining
- name = "\improper Mining Shuttle"
- music = "music/escape.ogg"
- icon_state = "shuttle"
-
-/area/shuttle/transport
- icon_state = "shuttle"
- name = "\improper Transport Shuttle"
-
-/area/shuttle/transport1
- icon_state = "shuttle"
- name = "\improper Transport Shuttle"
-
-/area/shuttle/alien/base
- icon_state = "shuttle"
- name = "\improper Alien Shuttle Base"
- requires_power = 1
-
-/area/shuttle/alien/mine
- icon_state = "shuttle"
- name = "\improper Alien Shuttle Mine"
- requires_power = 1
-
-/area/shuttle/gamma/space
- icon_state = "shuttle"
- name = "\improper Gamma Armory"
- requires_power = 0
-
-/area/shuttle/gamma/station
- icon_state = "shuttle"
- name = "\improper Gamma Armory Station"
- requires_power = 0
-
-/area/shuttle/prison/
- name = "\improper Prison Shuttle"
-
-/area/shuttle/prison/station
- icon_state = "shuttle"
-
-/area/shuttle/prison/prison
- icon_state = "shuttle2"
-
-/area/shuttle/siberia
- name = "\improper Labor Camp Shuttle"
- music = "music/escape.ogg"
- icon_state = "shuttle"
-
-/area/shuttle/specops
- name = "\improper Special Ops Shuttle"
- icon_state = "shuttlered"
-
-/area/shuttle/specops/centcom
- name = "\improper Special Ops Shuttle"
- icon_state = "shuttlered"
-
-/area/shuttle/specops/station
- name = "\improper Special Ops Shuttle"
- icon_state = "shuttlered2"
-
-/area/shuttle/syndicate_elite
- name = "\improper Syndicate Elite Shuttle"
- icon_state = "shuttlered"
- nad_allowed = TRUE
-
-/area/shuttle/syndicate_elite/mothership
- name = "\improper Syndicate Elite Shuttle"
- icon_state = "shuttlered"
-
-/area/shuttle/syndicate_elite/station
- name = "\improper Syndicate Elite Shuttle"
- icon_state = "shuttlered2"
-
-/area/shuttle/syndicate_sit
- name = "\improper Syndicate SIT Shuttle"
- icon_state = "shuttlered"
- nad_allowed = TRUE
-
-/area/shuttle/assault_pod
- name = "Steel Rain"
- icon_state = "shuttle"
-
-/area/shuttle/administration
- name = "\improper Administration Shuttle"
- icon_state = "shuttlered"
-
-/area/shuttle/administration/centcom
- name = "\improper Administration Shuttle Centcom"
- icon_state = "shuttlered"
-
-/area/shuttle/administration/station
- name = "\improper Administration Shuttle"
- icon_state = "shuttlered2"
-
-/area/shuttle/thunderdome
- name = "honk"
-
-/area/shuttle/thunderdome/grnshuttle
- name = "\improper Thunderdome GRN Shuttle"
- icon_state = "green"
-
-/area/shuttle/thunderdome/grnshuttle/dome
- name = "\improper GRN Shuttle"
- icon_state = "shuttlegrn"
-
-/area/shuttle/thunderdome/grnshuttle/station
- name = "\improper GRN Station"
- icon_state = "shuttlegrn2"
-
-/area/shuttle/thunderdome/redshuttle
- name = "\improper Thunderdome RED Shuttle"
- icon_state = "red"
-
-/area/shuttle/thunderdome/redshuttle/dome
- name = "\improper RED Shuttle"
- icon_state = "shuttlered"
-
-/area/shuttle/thunderdome/redshuttle/station
- name = "\improper RED Station"
- icon_state = "shuttlered2"
-// === Trying to remove these areas:
-
-/area/shuttle/research
- name = "\improper Research Shuttle"
- music = "music/escape.ogg"
- icon_state = "shuttle"
-
-/area/shuttle/research/station
- icon_state = "shuttle2"
-
-/area/shuttle/research/outpost
- icon_state = "shuttle"
-
-/area/shuttle/vox
- name = "\improper Vox Skipjack"
- icon_state = "shuttle"
- requires_power = 0
-
-/area/shuttle/vox/station
- name = "\improper Vox Skipjack"
- icon_state = "yellow"
- requires_power = 0
-
-/area/shuttle/salvage
- name = "\improper Salvage Ship"
- icon_state = "yellow"
- requires_power = 0
-
-/area/shuttle/salvage/start
- name = "\improper Middle of Nowhere"
- icon_state = "yellow"
-
-/area/shuttle/salvage/arrivals
- name = "\improper Space Station Auxiliary Docking"
- icon_state = "yellow"
-
-/area/shuttle/salvage/derelict
- name = "\improper Derelict Station"
- icon_state = "yellow"
-
-/area/shuttle/salvage/djstation
- name = "\improper Ruskie DJ Station"
- icon_state = "yellow"
-
-/area/shuttle/salvage/north
- name = "\improper North of the Station"
- icon_state = "yellow"
-
-/area/shuttle/salvage/east
- name = "\improper East of the Station"
- icon_state = "yellow"
-
-/area/shuttle/salvage/south
- name = "\improper South of the Station"
- icon_state = "yellow"
-
-/area/shuttle/salvage/commssat
- name = "\improper The Communications Satellite"
- icon_state = "yellow"
-
-/area/shuttle/salvage/mining
- name = "\improper South-West of the Mining Asteroid"
- icon_state = "yellow"
-
-/area/shuttle/salvage/abandoned_ship
- name = "\improper Abandoned Ship"
- icon_state = "yellow"
-
-/area/shuttle/salvage/clown_asteroid
- name = "\improper Clown Asteroid"
- icon_state = "yellow"
-
-/area/shuttle/salvage/trading_post
- name = "\improper Trading Post"
- icon_state = "yellow"
-
-/area/shuttle/salvage/transit
- name = "\improper hyperspace"
- icon_state = "shuttle"
-
-/area/shuttle/supply
- name = "Supply Shuttle"
- icon_state = "shuttle3"
- requires_power = 0
-
-/area/shuttle/abandoned
- name = "Abandoned Ship"
- icon_state = "shuttle"
-
-/area/shuttle/syndicate
- name = "Syndicate Nuclear Team Shuttle"
- icon_state = "shuttle"
- nad_allowed = TRUE
-
-/area/shuttle/trade
- name = "Trade Shuttle"
- icon_state = "shuttle"
- requires_power = 0
-
-/area/shuttle/trade/sol
- name = "Sol Freighter"
-
-/area/shuttle/freegolem
- name = "Free Golem Ship"
- icon_state = "purple"
- xenobiology_compatible = TRUE
-
-/area/airtunnel1/ // referenced in airtunnel.dm:759
-
-/area/dummy/ // Referenced in engine.dm:261
-
-/area/start // will be unused once kurper gets his login interface patch done
- name = "start area"
- icon_state = "start"
- requires_power = 0
- luminosity = 1
- dynamic_lighting = 0
- has_gravity = 1
-
-// === end remove
-
-/area/alien
- name = "\improper Alien base"
- icon_state = "yellow"
- requires_power = 0
-
-// CENTCOM
-
-/area/centcom
- name = "\improper Centcom"
- icon_state = "centcom"
- requires_power = 0
- dynamic_lighting = 0
- nad_allowed = TRUE
-
-/area/centcom/control
- name = "\improper Centcom Control"
- icon_state = "centcom_ctrl"
-
-/area/centcom/evac
- name = "\improper Centcom Emergency Shuttle"
- icon_state = "centcom_evac"
-
-/area/centcom/suppy
- name = "\improper Centcom Supply Shuttle"
- icon_state = "centcom_supply"
-
-/area/centcom/ferry
- name = "\improper Centcom Transport Shuttle"
- icon_state = "centcom_ferry"
-
-/area/centcom/shuttle
- name = "\improper Centcom Administration Shuttle"
-
-/area/centcom/test
- name = "\improper Centcom Testing Facility"
-
-/area/centcom/living
- name = "\improper Centcom Living Quarters"
-
-/area/centcom/specops
- name = "\improper Centcom Special Ops"
- icon_state = "centcom_specops"
-
-/area/centcom/gamma
- name = "\improper Centcom Gamma Armory"
- icon_state = "centcom_gamma"
-
-/area/centcom/holding
- name = "\improper Holding Facility"
-
-/area/centcom/bathroom
- name = "\improper Centcom Emergency Shuttle Bathrooms"
-
-//SYNDICATES
-
-/area/syndicate_mothership
- name = "\improper Syndicate Forward Base"
- icon_state = "syndie-ship"
- requires_power = 0
- nad_allowed = TRUE
-
-/area/syndicate_mothership/control
- name = "\improper Syndicate Control Room"
- icon_state = "syndie-control"
-
-/area/syndicate_mothership/elite_squad
- name = "\improper Syndicate Elite Squad"
- icon_state = "syndie-elite"
-
-/area/syndicate_mothership/infteam
- name = "\improper Syndicate Infiltrators"
- icon_state = "syndie-elite"
-
-//EXTRA
-
-/area/asteroid // -- TLE
- name = "\improper Asteroid"
- icon_state = "asteroid"
- requires_power = 0
- valid_territory = FALSE
-
-/area/asteroid/cave // -- TLE
- name = "\improper Asteroid - Underground"
- icon_state = "cave"
- requires_power = 0
- outdoors = 1
-
-/area/asteroid/artifactroom
- name = "\improper Asteroid - Artifact"
- icon_state = "cave"
-
-/area/tdome
- name = "\improper Thunderdome"
- icon_state = "thunder"
- requires_power = 0
- dynamic_lighting = 0
-
-
-/area/tdome/arena_source
- name = "\improper Thunderdome Arena Template"
- icon_state = "thunder"
-
-/area/tdome/arena
- name = "\improper Thunderdome Arena"
- icon_state = "thunder"
-
-/area/tdome/tdome1
- name = "\improper Thunderdome (Team 1)"
- icon_state = "green"
-
-/area/tdome/tdome2
- name = "\improper Thunderdome (Team 2)"
- icon_state = "yellow"
-
-/area/tdome/tdomeadmin
- name = "\improper Thunderdome (Admin.)"
- icon_state = "purple"
-
-/area/tdome/tdomeobserve
- name = "\improper Thunderdome (Observer.)"
- icon_state = "purple"
-
-/area/exploration/methlab
- name = "\improper Abandoned Drug Lab"
- icon_state = "green"
-
-//ENEMY
-
-//names are used
-/area/syndicate_station
- name = "\improper Syndicate Station"
- icon_state = "yellow"
- requires_power = 0
-
-/area/syndicate_station/start
- name = "\improper Syndicate Forward Operating Base"
- icon_state = "yellow"
-
-/area/syndicate_station/southwest
- name = "\improper South-West of SS13"
- icon_state = "southwest"
-
-/area/syndicate_station/northwest
- name = "\improper North-West of SS13"
- icon_state = "northwest"
-
-/area/syndicate_station/northeast
- name = "\improper North-East of SS13"
- icon_state = "northeast"
-
-/area/syndicate_station/southeast
- name = "\improper South-East of SS13"
- icon_state = "southeast"
-
-/area/syndicate_station/north
- name = "\improper North of SS13"
- icon_state = "north"
-
-/area/syndicate_station/south
- name = "\improper South of SS13"
- icon_state = "south"
-
-/area/syndicate_station/commssat
- name = "\improper South of the Communication Satellite"
- icon_state = "south"
-
-/area/syndicate_station/mining
- name = "\improper North-East of the Mining Asteroid"
- icon_state = "north"
-
-/area/syndicate_station/transit
- name = "\improper Hyperspace"
- icon_state = "shuttle"
-
-//Abductors
-/area/abductor_ship
- name = "\improper Abductor Ship"
- icon_state = "yellow"
- requires_power = 0
- has_gravity = 1
- dynamic_lighting = 0
-
-/area/wizard_station
- name = "\improper Wizard's Den"
- icon_state = "yellow"
- requires_power = 0
-
-/area/ninja
- name = "\improper Ninja Area Parent"
- icon_state = "ninjabase"
- requires_power = 0
- no_teleportlocs = 1
-
-/area/ninja/outpost
- name = "\improper SpiderClan Outpost"
-
-/area/ninja/holding
- name = "\improper SpiderClan Holding Facility"
-
-/area/vox_station
- name = "\improper Vox Base"
- icon_state = "yellow"
- requires_power = 0
- dynamic_lighting = 0
- no_teleportlocs = 1
-
-/area/vox_station/transit
- name = "\improper Hyperspace"
- icon_state = "shuttle"
- requires_power = 0
-
-/area/vox_station/southwest_solars
- name = "\improper Aft Port Solars"
- icon_state = "southwest"
- requires_power = 0
-
-/area/vox_station/northwest_solars
- name = "\improper Fore Port Solars"
- icon_state = "northwest"
- requires_power = 0
-
-/area/vox_station/northeast_solars
- name = "\improper Fore Starboard Solars"
- icon_state = "northeast"
- requires_power = 0
-
-/area/vox_station/southeast_solars
- name = "\improper Aft Starboard Solars"
- icon_state = "southeast"
- requires_power = 0
-
-/area/trader_station
- name = "Trade Base"
- icon_state = "yellow"
- requires_power = 0
-
-/area/trader_station/sol
- name = "Jupiter Station 6"
-
-/area/vox_station/mining
- name = "\improper Nearby Mining Asteroid"
- icon_state = "north"
- requires_power = 0
-
-/area/xenos_station/start
- name = "\improper Alien Shuttle"
- icon_state = "north"
- requires_power = 0
-
-/area/xenos_station/transit
- name = "\improper Hyperspace"
- icon_state = "shuttle"
- requires_power = 0
-
-/area/xenos_station/southwest
- name = "\improper Aft Port Solars Landing Area"
- icon_state = "southwest"
- requires_power = 0
-
-/area/xenos_station/northwest
- name = "\improper Fore Port Solars Landing Area"
- icon_state = "northwest"
- requires_power = 0
-
-/area/xenos_station/northeast
- name = "\improper Fore Starboard Solars Landing Area"
- icon_state = "northeast"
- requires_power = 0
-
-/area/xenos_station/southeast
- name = "\improper Aft Starboard Solars Landing Area"
- icon_state = "southeast"
- requires_power = 0
-
-/area/xenos_station/east
- name = "\improper East Landing Area"
- icon_state = "east"
- requires_power = 0
-
-/area/xenos_station/west
- name = "\improper West Landing Area"
- icon_state = "west"
- requires_power = 0
-
-/area/xenos_station/researchoutpost
- name = "\improper Research Outpost Landing Area"
- icon_state = "north"
- requires_power = 0
-
-/area/xenos_station/miningoutpost
- name = "\improper Mining Outpost Landing Area"
- icon_state = "south"
- requires_power = 0
-
-//PRISON
-/area/prison
- name = "\improper Prison Station"
- icon_state = "brig"
-
-/area/prison/arrival_airlock
- name = "\improper Prison Station Airlock"
- icon_state = "green"
- requires_power = 0
-
-/area/prison/control
- name = "\improper Prison Security Checkpoint"
- icon_state = "security"
-
-/area/prison/crew_quarters
- name = "\improper Prison Security Quarters"
- icon_state = "security"
-
-/area/prison/rec_room
- name = "\improper Prison Rec Room"
- icon_state = "green"
-
-/area/prison/closet
- name = "\improper Prison Supply Closet"
- icon_state = "dk_yellow"
-
-/area/prison/hallway/fore
- name = "\improper Prison Fore Hallway"
- icon_state = "yellow"
-
-/area/prison/hallway/aft
- name = "\improper Prison Aft Hallway"
- icon_state = "yellow"
-
-/area/prison/hallway/port
- name = "\improper Prison Port Hallway"
- icon_state = "yellow"
-
-/area/prison/hallway/starboard
- name = "\improper Prison Starboard Hallway"
- icon_state = "yellow"
-
-/area/prison/morgue
- name = "\improper Prison Morgue"
- icon_state = "morgue"
-
-/area/prison/medical_research
- name = "\improper Prison Genetic Research"
- icon_state = "medresearch"
-
-/area/prison/medical
- name = "\improper Prison Medbay"
- icon_state = "medbay"
-
-/area/prison/solar
- name = "\improper Prison Solar Array"
- icon_state = "storage"
- requires_power = 0
-
-/area/prison/podbay
- name = "\improper Prison Podbay"
- icon_state = "dk_yellow"
-
-/area/prison/solar_control
- name = "\improper Prison Solar Array Control"
- icon_state = "dk_yellow"
-
-/area/prison/solitary
- name = "\improper Solitary Confinement"
- icon_state = "brig"
-
-/area/prison/cell_block
- name = "\improper Prison Cell Block"
- icon_state = "brig"
-
-/area/prison/cell_block/A
- name = "\improper Prison Cell Block A"
- icon_state = "brig"
-
-/area/prison/cell_block/B
- name = "\improper Prison Cell Block B"
- icon_state = "brig"
-
-/area/prison/cell_block/C
- name = "\improper Prison Cell Block C"
- icon_state = "brig"
-
-//Labor camp
-/area/mine/laborcamp
- name = "Labor Camp"
- icon_state = "brig"
-
-/area/mine/laborcamp/security
- name = "Labor Camp Security"
- icon_state = "security"
-
-//STATION13
-
-/area/atmos
- name = "Atmospherics"
- icon_state = "atmos"
-
-/area/atmos/control
- name = "Atmospherics Control Room"
- icon_state = "atmos"
-
-/area/atmos/distribution
- name = "Atmospherics Distribution Loop"
- icon_state = "atmos"
-
-//Maintenance
-/area/maintenance
- ambientsounds = list('sound/ambience/ambimaint1.ogg', 'sound/ambience/ambimaint2.ogg', 'sound/ambience/ambimaint3.ogg', 'sound/ambience/ambimaint4.ogg', 'sound/ambience/ambimaint5.ogg')
- valid_territory = FALSE
-
-/area/maintenance/atmos_control
- name = "Atmospherics Maintenance"
- icon_state = "fpmaint"
-
-/area/maintenance/fpmaint
- name = "EVA Maintenance"
- icon_state = "fpmaint"
-
-/area/maintenance/fpmaint2
- name = "Arrivals North Maintenance"
- icon_state = "fpmaint"
-
-/area/maintenance/fsmaint
- name = "Dormitory Maintenance"
- icon_state = "fsmaint"
-
-/area/maintenance/fsmaint2
- name = "Bar Maintenance"
- icon_state = "fsmaint"
-
-/area/maintenance/asmaint
- name = "Medbay Maintenance"
- icon_state = "asmaint"
-
-/area/maintenance/asmaint2
- name = "Science Maintenance"
- icon_state = "asmaint"
-
-/area/maintenance/apmaint
- name = "Cargo Maintenance"
- icon_state = "apmaint"
-
-/area/maintenance/maintcentral
- name = "Bridge Maintenance"
- icon_state = "maintcentral"
-
-/area/maintenance/fore
- name = "Fore Maintenance"
- icon_state = "fmaint"
-
-/area/maintenance/starboard
- name = "Starboard Maintenance"
- icon_state = "smaint"
-
-/area/maintenance/port
- name = "Locker Room Maintenance"
- icon_state = "pmaint"
-
-/area/maintenance/aft
- name = "Engineering Maintenance"
- icon_state = "amaint"
-
-/area/maintenance/engi_shuttle
- name = "Engineering Shuttle Access"
- icon_state = "maint_e_shuttle"
-
-/area/maintenance/storage
- name = "Atmospherics Maintenance"
- icon_state = "green"
-
-/area/maintenance/incinerator
- name = "\improper Incinerator"
- icon_state = "disposal"
-
-/area/maintenance/turbine
- name = "\improper Turbine"
- icon_state = "disposal"
-
-/area/maintenance/disposal
- name = "Waste Disposal"
- icon_state = "disposal"
-
-/area/maintenance/genetics
- name = "Genetics Maintenance"
- icon_state = "asmaint"
-
-
-/area/maintenance/electrical
- name = "Electrical Maintenance"
- icon_state = "yellow"
-
-/area/maintenance/abandonedbar
- name = "Maintenance Bar"
- icon_state = "yellow"
- power_equip = 0
- power_light = 0
- power_environ = 0
-
-/area/maintenance/electrical_shop
- name ="Electronics Den"
- icon_state = "yellow"
-
-/area/maintenance/gambling_den
- name = "Gambling Den"
- icon_state = "yellow"
-
-/area/maintenance/consarea
- name = "Alternate Construction Area"
- icon_state = "yellow"
-
-
-//Hallway
-
-/area/hallway/primary/fore
- name = "\improper Fore Primary Hallway"
- icon_state = "hallF"
-
-/area/hallway/primary/starboard
- name = "\improper Starboard Primary Hallway"
- icon_state = "hallS"
-
-/area/hallway/primary/starboard/west
-/area/hallway/primary/starboard/east
-
-/area/hallway/primary/aft
- name = "\improper Aft Primary Hallway"
- icon_state = "hallA"
-
-
-/area/hallway/primary/port
- name = "\improper Port Primary Hallway"
- icon_state = "hallP"
-
-/area/hallway/primary/port/west
- name = "\improper Port West Hallway"
-
-/area/hallway/primary/port/east
- name = "\improper Port East Hallway"
-
-/area/hallway/primary/central
- name = "\improper Central Primary Hallway"
- icon_state = "hallC"
-
-/area/hallway/primary/central/north
-/area/hallway/primary/central/south
-/area/hallway/primary/central/west
-/area/hallway/primary/central/east
-/area/hallway/primary/central/nw
-/area/hallway/primary/central/ne
-/area/hallway/primary/central/sw
-/area/hallway/primary/central/se
-
-/area/hallway/secondary/exit
- name = "\improper Escape Shuttle Hallway"
- icon_state = "escape"
-
-/area/hallway/secondary/construction
- name = "\improper Construction Area"
- icon_state = "construction"
-
-/area/hallway/secondary/entry
- name = "\improper Arrival Shuttle Hallway"
- icon_state = "entry"
-
-/area/hallway/secondary/entry/north
-
-/area/hallway/secondary/entry/south
-
-/area/hallway/secondary/entry/louge
- name = "\improper Arrivals Lounge"
-
-
-//Command
-
-/area/bridge
- name = "\improper Bridge"
- icon_state = "bridge"
- music = "signal"
-
-/area/bridge/meeting_room
- name = "\improper Heads of Staff Meeting Room"
- icon_state = "meeting"
- music = null
-
-/area/crew_quarters/captain
- name = "\improper Captain's Office"
- icon_state = "captain"
-
-/area/crew_quarters/captain/bedroom
- name = "\improper Captain's Bedroom"
- icon_state = "captain"
-
-/area/crew_quarters/recruit
- name = "\improper Recruitment Office"
- icon_state = "head_quarters"
-
-/area/crew_quarters/heads/hop
- name = "\improper Head of Personnel's Quarters"
- icon_state = "head_quarters"
-
-/area/crew_quarters/heads/hor
- name = "\improper Research Director's Quarters"
- icon_state = "head_quarters"
-
-/area/crew_quarters/heads/chief
- name = "\improper Chief Engineer's Quarters"
- icon_state = "head_quarters"
-
-/area/crew_quarters/heads/hos
- name = "\improper Head of Security's Quarters"
- icon_state = "head_quarters"
-
-/area/crew_quarters/heads/cmo
- name = "\improper Chief Medical Officer's Quarters"
- icon_state = "head_quarters"
-
-/area/crew_quarters/courtroom
- name = "\improper Courtroom"
- icon_state = "courtroom"
-
-/area/crew_quarters/heads
- name = "\improper Head of Personnel's Office"
- icon_state = "head_quarters"
-
-/area/crew_quarters/hor
- name = "\improper Research Director's Office"
- icon_state = "head_quarters"
-
-/area/crew_quarters/hos
- name = "\improper Head of Security's Office"
- icon_state = "head_quarters"
-
-/area/crew_quarters/chief
- name = "\improper Chief Engineer's Office"
- icon_state = "head_quarters"
-
-/area/mint
- name = "\improper Mint"
- icon_state = "green"
-
-/area/comms
- name = "\improper Communications Relay"
- icon_state = "tcomsatcham"
-
-/area/server
- name = "\improper Messaging Server Room"
- icon_state = "server"
-
-/area/ntrep
- name = "\improper Nanotrasen Representative's Office"
- icon_state = "bluenew"
-
-/area/blueshield
- name = "\improper Blueshield's Office"
- icon_state = "blueold"
-
-/area/centcomdocks
- name = "\improper Central Command Docks"
- icon_state = "centcom"
-
-//Crew
-
-/area/crew_quarters
- name = "\improper Dormitories"
- icon_state = "Sleep"
-
-/area/crew_quarters/toilet
- name = "\improper Dormitory Toilets"
- icon_state = "toilet"
-
-/area/crew_quarters/sleep
- name = "\improper Dormitories"
- icon_state = "Sleep"
- valid_territory = FALSE
-
-/area/crew_quarters/sleep_male
- name = "\improper Male Dorm"
- icon_state = "Sleep"
-
-/area/crew_quarters/sleep_male/toilet_male
- name = "\improper Male Toilets"
- icon_state = "toilet"
-
-/area/crew_quarters/sleep_female
- name = "\improper Female Dorm"
- icon_state = "Sleep"
-
-/area/crew_quarters/sleep_female/toilet_female
- name = "\improper Female Toilets"
- icon_state = "toilet"
-
-/area/crew_quarters/locker
- name = "\improper Locker Room"
- icon_state = "locker"
-
-/area/crew_quarters/locker/locker_toilet
- name = "\improper Locker Toilets"
- icon_state = "toilet"
-
-/area/crew_quarters/fitness
- name = "\improper Fitness Room"
- icon_state = "fitness"
-
-/area/crew_quarters/dorms
- name = "\improper Dorms"
- icon_state = "dorms"
-
-/area/crew_quarters/arcade
- name = "\improper Arcade"
- icon_state = "arcade"
-
-/area/crew_quarters/cafeteria
- name = "\improper Cafeteria"
- icon_state = "cafeteria"
-
-/area/crew_quarters/kitchen
- name = "\improper Kitchen"
- icon_state = "kitchen"
-
-/area/crew_quarters/bar
- name = "\improper Bar"
- icon_state = "bar"
-
-/area/crew_quarters/bar/atrium
- name = "Atrium"
- icon_state = "bar"
-
-/area/crew_quarters/theatre
- name = "\improper Theatre"
- icon_state = "Theatre"
-
-/area/crew_quarters/mrchangs
- name = "\improper Mr Chang's"
- icon_state = "Theatre"
-
-/area/library
- name = "\improper Library"
- icon_state = "library"
-
-/area/library/abandoned
- name = "\improper Abandoned Library"
- icon_state = "library"
-
-/area/chapel/main
- name = "\improper Chapel"
- icon_state = "chapel"
- ambientsounds = list('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg')
-
-/area/chapel/office
- name = "\improper Chapel Office"
- icon_state = "chapeloffice"
-
-/area/escapepodbay
- name = "\improper Escape Shuttle Hallway Podbay"
- icon_state = "escape"
-
-/area/lawoffice
- name = "\improper Law Office"
- icon_state = "law"
-
-/area/magistrateoffice
- name = "\improper Magistrate's Office"
- icon_state = "magistrate"
-
-/area/clownoffice
- name = "\improper Clown's Office"
- icon_state = "clown_office"
-
-/area/mimeoffice
- name = "\improper Mime's Office"
- icon_state = "mime_office"
-
-/area/civilian/barber
- name = "\improper Barber Shop"
- icon_state = "barber"
-
-/area/civilian/clothing
- name = "\improper Clothing Shop"
- icon_state = "Theatre"
-
-/area/civilian/pet_store
- name = "\improper Pet Store"
- icon_state = "pet_store"
-
-/area/holodeck
- name = "\improper Holodeck"
- icon_state = "Holodeck"
- dynamic_lighting = 0
-
-/area/holodeck/alphadeck
- name = "\improper Holodeck Alpha"
-
-
-/area/holodeck/source_plating
- name = "\improper Holodeck - Off"
- icon_state = "Holodeck"
-
-/area/holodeck/source_emptycourt
- name = "\improper Holodeck - Empty Court"
-
-/area/holodeck/source_boxingcourt
- name = "\improper Holodeck - Boxing Court"
-
-/area/holodeck/source_basketball
- name = "\improper Holodeck - Basketball Court"
-
-/area/holodeck/source_thunderdomecourt
- name = "\improper Holodeck - Thunderdome Court"
-
-/area/holodeck/source_beach
- name = "\improper Holodeck - Beach"
- icon_state = "Holodeck" // Lazy.
-
-/area/holodeck/source_burntest
- name = "\improper Holodeck - Atmospheric Burn Test"
-
-/area/holodeck/source_wildlife
- name = "\improper Holodeck - Wildlife Simulation"
-
-/area/holodeck/source_meetinghall
- name = "\improper Holodeck - Meeting Hall"
-
-/area/holodeck/source_theatre
- name = "\improper Holodeck - Theatre"
-
-/area/holodeck/source_picnicarea
- name = "\improper Holodeck - Picnic Area"
-
-/area/holodeck/source_snowfield
- name = "\improper Holodeck - Snow Field"
-
-/area/holodeck/source_desert
- name = "\improper Holodeck - Desert"
-
-/area/holodeck/source_space
- name = "\improper Holodeck - Space"
-
-/area/holodeck/source_knightarena
- name = "\improper Holodeck - Knight Arena"
-
-
-//Embassies
-/area/embassy/
- name = "\improper Embassy Hallway"
-
-/area/embassy/tajaran
- name = "\improper Tajaran Embassy"
- icon_state = "tajaran"
-
-/area/embassy/skrell
- name = "\improper Skrell Embassy"
- icon_state = "skrell"
-
-/area/embassy/unathi
- name = "\improper Unathi Embassy"
- icon_state = "unathi"
-
-/area/embassy/kidan
- name = "\improper Kidan Embassy"
- icon_state = "kidan"
-
-/area/embassy/diona
- name = "\improper Diona Embassy"
- icon_state = "diona"
-
-/area/embassy/slime
- name = "\improper Slime Person Embassy"
- icon_state = "slime"
-
-/area/embassy/grey
- name = "\improper Grey Embassy"
- icon_state = "grey"
-
-/area/embassy/vox
- name = "\improper Vox Embassy"
- icon_state = "vox"
-
-
-
-//Engineering
-/area/engine
- ambientsounds = list('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg')
-
-/area/engine/engine_smes
- name = "\improper Engineering SMES"
- icon_state = "engine_smes"
- requires_power = 0//This area only covers the batteries and they deal with their own power
-
-/area/engine/engineering
- name = "Engineering"
- icon_state = "engine_smes"
-
-/area/engine/break_room
- name = "\improper Engineering Foyer"
- icon_state = "engine"
-
-/area/engine/equipmentstorage
- name = "\improper Engineering Equipment Storage"
- icon_state = "storage"
-
-/area/engine/hardsuitstorage
- name = "\improper Engineering Hardsuit Storage"
- icon_state = "storage"
-
-/area/engine/controlroom
- name = "\improper Engineering Control Room"
- icon_state = "engine_control"
-
-/area/engine/gravitygenerator
- name = "\improper Gravity Generator"
- icon_state = "engine"
-
-/area/engine/chiefs_office
- name = "\improper Chief Engineer's office"
- icon_state = "engine_control"
-
-/area/engine/mechanic_workshop
- name = "\improper Mechanic Workshop"
- icon_state = "engine"
-
-/area/engine/mechanic_workshop/hanger
- name = "\improper Hanger Bay"
- icon_state = "engine"
-
-/area/engine/supermatter
- name = "\improper Supermatter Engine"
- icon_state = "engine"
-
-//Solars
-
-/area/solar
- requires_power = 0
- dynamic_lighting = 0
- valid_territory = FALSE
-
-/area/solar/auxport
- name = "\improper Fore Port Solar Array"
- icon_state = "panelsA"
-
-/area/solar/auxstarboard
- name = "\improper Fore Starboard Solar Array"
- icon_state = "panelsA"
-
-/area/solar/fore
- name = "\improper Fore Solar Array"
- icon_state = "yellow"
-
-/area/solar/aft
- name = "\improper Aft Solar Array"
- icon_state = "aft"
-
-/area/solar/starboard
- name = "\improper Aft Starboard Solar Array"
- icon_state = "panelsS"
-
-/area/solar/port
- name = "\improper Aft Port Solar Array"
- icon_state = "panelsP"
-
-/area/maintenance/auxsolarport
- name = "\improper Fore Port Solar Maintenance"
- icon_state = "SolarcontrolA"
-
-/area/maintenance/starboardsolar
- name = "\improper Aft Starboard Solar Maintenance"
- icon_state = "SolarcontrolS"
-
-/area/maintenance/portsolar
- name = "\improper Aft Port Solar Maintenance"
- icon_state = "SolarcontrolP"
-
-/area/maintenance/auxsolarstarboard
- name = "\improper Fore Starboard Solar Maintenance"
- icon_state = "SolarcontrolA"
-
-
-/area/assembly/chargebay
- name = "\improper Mech Bay"
- icon_state = "mechbay"
-
-/area/assembly/showroom
- name = "\improper Robotics Showroom"
- icon_state = "showroom"
-
-/area/assembly/robotics
- name = "\improper Robotics Lab"
- icon_state = "ass_line"
-
-/area/assembly/assembly_line //Derelict Assembly Line
- name = "\improper Assembly Line"
- icon_state = "ass_line"
- power_equip = 0
- power_light = 0
- power_environ = 0
-
-//Teleporter
-
-/area/teleporter
- name = "\improper Teleporter"
- icon_state = "teleporter"
- music = "signal"
-
-/area/gateway
- name = "\improper Gateway"
- icon_state = "teleporter"
- music = "signal"
-
-/area/AIsattele
- name = "\improper Abandoned Teleporter"
- icon_state = "teleporter"
- music = "signal"
- ambientsounds = list('sound/ambience/ambimalf.ogg')
-
-/area/toxins/explab
- name = "\improper E.X.P.E.R.I-MENTOR Lab"
- icon_state = "toxmisc"
-
-/area/toxins/explab_chamber
- name = "\improper E.X.P.E.R.I-MENTOR Chamber"
- icon_state = "toxmisc"
-
-//MedBay
-
-/area/medical/medbay
- name = "\improper Medbay"
- icon_state = "medbay"
- music = 'sound/ambience/signal.ogg'
-
-//Medbay is a large area, these additional areas help level out APC load.
-/area/medical/medbay2
- name = "\improper Medbay"
- icon_state = "medbay2"
- music = 'sound/ambience/signal.ogg'
-
-/area/medical/medbay3
- name = "\improper Medbay"
- icon_state = "medbay3"
- music = 'sound/ambience/signal.ogg'
-
-
-/area/medical/biostorage
- name = "\improper Medical Storage"
- icon_state = "medbaysecstorage"
- music = 'sound/ambience/signal.ogg'
-
-/area/medical/reception
- name = "\improper Medbay Reception"
- icon_state = "medbay"
- music = 'sound/ambience/signal.ogg'
-
-/area/medical/psych
- name = "\improper Psych Room"
- icon_state = "medbaypsych"
- music = 'sound/ambience/signal.ogg'
-
-/area/medical/medbreak
- name = "\improper Break Room"
- icon_state = "medbaybreak"
- music = 'sound/ambience/signal.ogg'
-
-/area/medical/patients_rooms
- name = "\improper Patient's Rooms"
- icon_state = "patients"
-
-/area/medical/ward
- name = "\improper Medbay Patient Ward"
- icon_state = "patientsward"
-
-/area/medical/patient_a
- name = "\improper Isolation A"
- icon_state = "medbayisoa"
-
-/area/medical/patient_b
- name = "\improper Isolation B"
- icon_state = "medbayisob"
-
-/area/medical/patient_c
- name = "\improper Isolation C"
- icon_state = "medbayisoc"
-
-/area/medical/iso_access
- name = "\improper Isolation Access"
- icon_state = "medbayisoaccess"
-
-/area/medical/cmo
- name = "\improper Chief Medical Officer's office"
- icon_state = "CMO"
-
-/area/medical/cmostore
- name = "\improper Medical Secondary Storage"
- icon_state = "medbaysecstorage"
-
-/area/medical/robotics
- name = "\improper Robotics"
- icon_state = "medresearch"
-
-/area/medical/research
- name = "\improper Medical Research"
- icon_state = "medresearch"
-
-/area/medical/research_shuttle_dock
- name = "\improper Research Shuttle Dock"
- icon_state = "medresearch"
-
-/area/medical/virology
- name = "\improper Virology"
- icon_state = "virology"
-
-/area/medical/virology/lab
- name = "\improper Virology Laboratory"
- icon_state = "virology"
-
-/area/medical/morgue
- name = "\improper Morgue"
- icon_state = "morgue"
- ambientsounds = list('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg')
-
-/area/medical/chemistry
- name = "\improper Chemistry"
- icon_state = "chem"
-
-/area/medical/surgery
- name = "\improper Surgery"
- icon_state = "surgery"
-
-/area/medical/surgery1
- name = "\improper Surgery 1"
- icon_state = "surgery1"
-
-/area/medical/surgery2
- name = "\improper Surgery 2"
- icon_state = "surgery2"
-
-/area/medical/surgeryobs
- name = "\improper Surgery Observation"
- icon_state = "surgery"
-
-/area/medical/cryo
- name = "\improper Cryogenics"
- icon_state = "cryo"
-
-/area/medical/exam_room
- name = "\improper Exam Room"
- icon_state = "exam_room"
-
-/area/medical/genetics
- name = "\improper Genetics Lab"
- icon_state = "genetics"
-
-/area/medical/genetics_cloning
- name = "\improper Cloning Lab"
- icon_state = "cloning"
-
-/area/medical/sleeper
- name = "\improper Medical Treatment Center"
- icon_state = "exam_room"
-
-/area/medical/paramedic
- name = "\improper Paramedic"
- icon_state = "medbay"
-
-//Security
-
-/area/security/main
- name = "\improper Security Office"
- icon_state = "securityoffice"
-
-/area/security/lobby
- name = "\improper Security Lobby"
- icon_state = "securitylobby"
-
-/area/security/brig
- name = "\improper Brig"
- icon_state = "brig"
-
-/area/security/brig/prison_break()
- for(var/obj/structure/closet/secure_closet/brig/temp_closet in src)
- temp_closet.locked = 0
- temp_closet.icon_state = temp_closet.icon_closed
- for(var/obj/machinery/door_timer/temp_timer in src)
- temp_timer.releasetime = 1
- ..()
-
-/area/security/permabrig
- name = "\improper Prison Wing"
- icon_state = "sec_prison_perma"
-
-/area/security/prison
- name = "\improper Prison Wing"
- icon_state = "sec_prison"
-
-/area/security/prison/prison_break()
- for(var/obj/structure/closet/secure_closet/brig/temp_closet in src)
- temp_closet.locked = 0
- temp_closet.icon_state = temp_closet.icon_closed
- for(var/obj/machinery/door_timer/temp_timer in src)
- temp_timer.releasetime = 1
- ..()
-
-/area/security/prison/cell_block
- name = "\improper Prison Cell Block"
- icon_state = "brig"
-
-/area/security/prison/cell_block/A
- name = "\improper Prison Cell Block A"
- icon_state = "brigcella"
-
-/area/security/prison/cell_block/B
- name = "\improper Prison Cell Block B"
- icon_state = "brigcellb"
-
-/area/security/prison/cell_block/C
- name = "\improper Prison Cell Block C"
- icon_state = "brig"
-
-/area/security/execution
- name = "\improper Execution"
- icon_state = "execution"
-
-/area/security/processing
- name = "\improper Prisoner Processing"
- icon_state = "prisonerprocessing"
-
-/area/security/interrogation
- name = "\improper Interrogation"
- icon_state = "interrogation"
-
-/area/security/seceqstorage
- name = "\improper Security Equipment Storage"
- icon_state = "securityequipmentstorage"
-
-/area/security/interrogationhallway
- name = "\improper Interrogation Hallway"
- icon_state = "interrogationhall"
-
-/area/security/courtroomdandp
- name = "\improper Courtroom Defense and Prosecution"
- icon_state = "seccourt"
-
-/area/security/interrogationobs
- name = "\improper Interrogation Observation"
- icon_state = "security"
-
-/area/security/evidence
- name = "\improper Evidence Room"
- icon_state = "evidence"
-
-/area/security/prisonlockers
- name = "\improper Prisoner Lockers"
- icon_state = "sec_prison_lockers"
-
-/area/security/medbay
- name = "\improper Security Medbay"
- icon_state = "security_medbay"
-
-/area/security/prisonershuttle
- name = "\improper Security Prisoner Shuttle"
- icon_state = "security"
-
-/area/security/warden
- name = "\improper Warden's Office"
- icon_state = "Warden"
-
-/area/security/armoury
- name = "\improper Armory"
- icon_state = "armory"
-
-/area/security/securearmoury
- name = "\improper Secure Armory"
- icon_state = "secarmory"
-
-/area/security/armoury/gamma
- name = "\improper Gamma Armory"
- icon_state = "Warden"
- requires_power = 0
-
-/area/security/securehallway
- name = "\improper Security Secure Hallway"
- icon_state = "securehall"
-
-/area/security/hos
- name = "\improper Head of Security's Office"
- icon_state = "sec_hos"
-
-/area/security/podbay
- name = "\improper Security Podbay"
- icon_state = "securitypodbay"
-
-/area/security/detectives_office
- name = "\improper Detective's Office"
- icon_state = "detective"
-
-/area/security/range
- name = "\improper Firing Range"
- icon_state = "firingrange"
-
-/area/security/nuke_storage
- name = "\improper Vault"
- icon_state = "nuke_storage"
-
-/area/security/customs
- name = "\improper Customs"
- icon_state = "checkpoint1"
-
-/area/security/customs2
- name = "\improper Customs"
- icon_state = "security"
-
-/area/security/checkpoint
- name = "\improper Security Checkpoint"
- icon_state = "checkpoint1"
-
-/area/security/checkpoint2
- name = "\improper Security Checkpoint"
- icon_state = "security"
-
-/area/security/checkpoint/supply
- name = "Security Post - Cargo Bay"
- icon_state = "checkpoint1"
-
-/area/security/checkpoint/engineering
- name = "Security Post - Engineering"
- icon_state = "checkpoint1"
-
-/area/security/checkpoint/medical
- name = "Security Post - Medbay"
- icon_state = "checkpoint1"
-
-/area/security/checkpoint/science
- name = "Security Post - Science"
- icon_state = "checkpoint1"
-
-/area/security/vacantoffice
- name = "\improper Vacant Office"
- icon_state = "security"
-
-/area/security/vacantoffice2
- name = "\improper Vacant Office"
- icon_state = "security"
-
-/area/quartermaster
- name = "\improper Quartermasters"
- icon_state = "quart"
-
-///////////WORK IN PROGRESS//////////
-
-/area/quartermaster/sorting
- name = "\improper Delivery Office"
- icon_state = "quartstorage"
-
-////////////WORK IN PROGRESS//////////
-
-/area/quartermaster/office
- name = "\improper Cargo Office"
- icon_state = "quartoffice"
-
-/area/quartermaster/storage
- name = "\improper Cargo Bay"
- icon_state = "quartstorage"
-
-/area/quartermaster/qm
- name = "\improper Quartermaster's Office"
- icon_state = "quart"
-
-/area/quartermaster/miningdock
- name = "\improper Mining Dock"
- icon_state = "mining"
-
-/area/quartermaster/miningstorage
- name = "\improper Mining Storage"
- icon_state = "green"
-
-/area/quartermaster/mechbay
- name = "\improper Mech Bay"
- icon_state = "yellow"
-
-/area/janitor
- name = "\improper Custodial Closet"
- icon_state = "janitor"
-
-/area/hydroponics
- name = "\improper Hydroponics"
- icon_state = "hydro"
-
-/area/hydroponics/abandoned_garden
- name = "\improper Abandoned Garden"
- icon_state = "hydro"
-
-//Toxins
-
-/area/toxins/lab
- name = "\improper Research and Development"
- icon_state = "toxlab"
-
-/area/toxins/hallway
- name = "\improper Research Lab"
- icon_state = "toxlab"
-
-/area/toxins/rdoffice
- name = "\improper Research Director's Office"
- icon_state = "head_quarters"
-
-/area/toxins/supermatter
- name = "\improper Supermatter Lab"
- icon_state = "toxlab"
-
-/area/toxins/xenobiology
- name = "\improper Xenobiology Lab"
- icon_state = "toxmix"
- xenobiology_compatible = TRUE
-
-/area/toxins/xenobiology/xenoflora_storage
- name = "\improper Xenoflora Storage"
- icon_state = "toxlab"
-
-/area/toxins/xenobiology/xenoflora
- name = "\improper Xenoflora Lab"
- icon_state = "toxlab"
-
-/area/toxins/storage
- name = "\improper Toxins Storage"
- icon_state = "toxstorage"
-
-/area/toxins/test_area
- name = "\improper Toxins Test Area"
- icon_state = "toxtest"
- valid_territory = FALSE
-
-/area/toxins/mixing
- name = "\improper Toxins Mixing Room"
- icon_state = "toxmix"
-
-/area/toxins/launch
- name = "Toxins Launch Room"
- icon_state = "toxlaunch"
-
-/area/toxins/misc_lab
- name = "\improper Research Testing Lab"
- icon_state = "toxmisc"
-
-/area/toxins/test_chamber
- name = "\improper Research Testing Chamber"
- icon_state = "toxtest"
-
-/area/toxins/server
- name = "\improper Server Room"
- icon_state = "server"
-
-/area/toxins/server_coldroom
- name = "\improper Server Coldroom"
- icon_state = "servercold"
-
-/area/toxins/explab
- name = "\improper Experimentation Lab"
- icon_state = "toxmisc"
-
-//Storage
-
-/area/storage/tools
- name = "Auxiliary Tool Storage"
- icon_state = "storage"
-
-/area/storage/primary
- name = "Primary Tool Storage"
- icon_state = "primarystorage"
-
-/area/storage/autolathe
- name = "Autolathe Storage"
- icon_state = "storage"
-
-/area/storage/art
- name = "Art Supply Storage"
- icon_state = "storage"
-
-/area/storage/auxillary
- name = "Auxillary Storage"
- icon_state = "auxstorage"
-
-/area/storage/eva
- name = "EVA Storage"
- icon_state = "eva"
-
-/area/storage/secure
- name = "Secure Storage"
- icon_state = "storage"
-
-/area/storage/emergency
- name = "Starboard Emergency Storage"
- icon_state = "emergencystorage"
-
-/area/storage/emergency2
- name = "Port Emergency Storage"
- icon_state = "emergencystorage"
-
-/area/storage/tech
- name = "Technical Storage"
- icon_state = "auxstorage"
-
-/area/storage/testroom
- requires_power = 0
- name = "\improper Test Room"
- icon_state = "storage"
-
-/area/storage/office
- name = "\improper Office Supplies"
- icon_state = "office_supplies"
-
-// ENGIE OUTPOST
-
-/area/engiestation
- name = "\improper Engineering Outpost"
- icon_state = "construction"
-
-/area/engiestation/solars
- name = "\improper Engineering Outpost Solars"
- icon_state = "panelsP"
-
-//DJSTATION
-
-/area/djstation
- name = "\improper Ruskie DJ Station"
- icon_state = "DJ"
-
-/area/djstation/solars
- name = "\improper Ruskie DJ Station Solars"
- icon_state = "DJ"
-
-//DERELICT
-
-/area/derelict
- name = "\improper Derelict Station"
- icon_state = "storage"
-
-/area/derelict/hallway/primary
- name = "\improper Derelict Primary Hallway"
- icon_state = "hallP"
-
-/area/derelict/hallway/secondary
- name = "\improper Derelict Secondary Hallway"
- icon_state = "hallS"
-
-/area/derelict/arrival
- name = "\improper Derelict Arrival Centre"
- icon_state = "yellow"
-
-/area/derelict/storage/equipment
- name = "Derelict Equipment Storage"
-
-/area/derelict/storage/storage_access
- name = "Derelict Storage Access"
-
-/area/derelict/storage/engine_storage
- name = "Derelict Engine Storage"
- icon_state = "green"
-
-/area/derelict/bridge
- name = "\improper Derelict Control Room"
- icon_state = "bridge"
-
-/area/derelict/secret
- name = "\improper Derelict Secret Room"
- icon_state = "library"
-
-/area/derelict/bridge/access
- name = "Derelict Control Room Access"
- icon_state = "auxstorage"
-
-/area/derelict/bridge/ai_upload
- name = "\improper Derelict Computer Core"
- icon_state = "ai"
-
-/area/derelict/solar_control
- name = "\improper Derelict Solar Control"
- icon_state = "engine"
-
-/area/derelict/se_solar
- name = "South East Solars"
- icon_state = "engine"
-
-/area/derelict/crew_quarters
- name = "\improper Derelict Crew Quarters"
- icon_state = "fitness"
-
-/area/derelict/medical
- name = "Derelict Medbay"
- icon_state = "medbay"
-
-/area/derelict/medical/morgue
- name = "\improper Derelict Morgue"
- icon_state = "morgue"
-
-/area/derelict/medical/chapel
- name = "\improper Derelict Chapel"
- icon_state = "chapel"
-
-/area/derelict/teleporter
- name = "\improper Derelict Teleporter"
- icon_state = "teleporter"
-
-/area/derelict/eva
- name = "Derelict EVA Storage"
- icon_state = "eva"
-
-/area/shuttle/derelict/ship/start
- name = "\improper Abandoned Ship"
- icon_state = "yellow"
-
-/area/shuttle/derelict/ship/transit
- name = "\improper Abandoned Ship"
- icon_state = "yellow"
-
-/area/shuttle/derelict/ship/engipost
- name = "\improper Engineering Outpost"
- icon_state = "yellow"
-
-/area/shuttle/derelict/ship/station
- name = "\improper North of SS13"
- icon_state = "yellow"
-
-/area/solar/derelict_starboard
- name = "\improper Derelict Starboard Solar Array"
- icon_state = "panelsS"
-
-/area/solar/derelict_aft
- name = "\improper Derelict Aft Solar Array"
- icon_state = "aft"
-
-/area/derelict/singularity_engine
- name = "\improper Derelict Singularity Engine"
- icon_state = "engine"
-
-/area/derelict/gravity_generator
- name = "\improper Derelict Gravity Generator Room"
- icon_state = "red"
-
-/area/derelict/atmospherics
- name = "Derelict Atmospherics"
- icon_state = "red"
-
-//HALF-BUILT STATION (REPLACES DERELICT IN BAYCODE, ABOVE IS LEFT FOR DOWNSTREAM)
-
-/area/shuttle/constructionsite
- name = "\improper Construction Site Shuttle"
- icon_state = "yellow"
-
-/area/shuttle/constructionsite/station
- name = "\improper Construction Site Shuttle"
-
-/area/shuttle/constructionsite/site
- name = "\improper Construction Site Shuttle"
-
-/area/constructionsite
- name = "\improper Construction Site"
- icon_state = "storage"
-
-/area/constructionsite/storage
- name = "\improper Construction Site Storage Area"
-
-/area/constructionsite/science
- name = "\improper Construction Site Research"
- icon_state = "medresearch"
-
-/area/constructionsite/bridge
- name = "\improper Construction Site Bridge"
- icon_state = "bridge"
-
-/area/constructionsite/hallway/center
- name = "\improper Construction Site Central Hallway"
- icon_state = "hallC"
-
-/area/constructionsite/hallway/engcore
- name = "\improper Construction Site Eng Core"
- icon_state = "green"
-
-/area/constructionsite/hallway/fore
- name = "\improper Construction Site Fore"
- icon_state = "green"
-
-/area/constructionsite/hallway/port
- name = "\improper Construction Site Port"
- icon_state = "hallP"
-
-/area/constructionsite/hallway/aft
- name = "\improper Construction Site Aft"
- icon_state = "hallA"
-
-/area/constructionsite/hallway/starboard
- name = "\improper Construction Site Starboard"
- icon_state = "hallS"
-
-/area/constructionsite/atmospherics
- name = "\improper Construction Site Atmospherics"
- icon_state = "atmos"
-
-/area/constructionsite/medical
- name = "\improper Construction Site Medbay"
- icon_state = "medbay"
-
-/area/constructionsite/ai
- name = "\improper Construction Computer Core"
- icon_state = "ai"
-
-/area/constructionsite/engineering
- name = "\improper Construction Site Engine Bay"
- icon_state = "engine"
-
-/area/solar/constructionsite
- name = "\improper Construction Site Solars"
- icon_state = "panelsA"
-
-
-//Construction
-
-/area/construction
- name = "\improper Construction Area"
- icon_state = "yellow"
-
-/area/mining_construction
- name = "Auxillary Base Construction"
- icon_state = "yellow"
-
-/area/construction/supplyshuttle
- name = "\improper Supply Shuttle"
- icon_state = "yellow"
-
-/area/construction/quarters
- name = "\improper Engineer's Quarters"
- icon_state = "yellow"
-
-/area/construction/qmaint
- name = "Maintenance"
- icon_state = "yellow"
-
-/area/construction/hallway
- name = "\improper Hallway"
- icon_state = "yellow"
-
-/area/construction/solars
- name = "\improper Solar Panels"
- icon_state = "yellow"
-
-/area/construction/solarscontrol
- name = "\improper Solar Panel Control"
- icon_state = "yellow"
-
-/area/construction/Storage
- name = "Construction Site Storage"
- icon_state = "yellow"
-
-
-//GAYBAR
-/area/secret/gaybar
- name = "\improper Dance Bar"
- icon_state = "dancebar"
-
-
-//Traitor Station
-/area/traitor
- name = "\improper Syndicate Base"
- icon_state = "syndie_hall"
- report_alerts = 0
-
-/area/traitor/rnd
- name = "\improper Syndicate Research and Development"
- icon_state = "syndie_rnd"
-
-/area/traitor/chem
- name = "\improper Syndicate Chemistry"
- icon_state = "syndie_chem"
-
-/area/traitor/tox
- name = "\improper Syndicate Toxins"
- icon_state = "syndie_tox"
-
-/area/traitor/atmos
- name = "\improper Syndicate Atmos"
- icon_state = "syndie_atmo"
-
-/area/traitor/inter
- name = "\improper Syndicate Interrogation"
- icon_state = "syndie_inter"
-
-/area/traitor/radio
- name = "\improper Syndicate Eavesdropping Booth"
- icon_state = "syndie_radio"
-
-/area/traitor/surgery
- name = "\improper Syndicate Surgery Theatre"
- icon_state = "syndie_surgery"
-
-/area/traitor/hall
- name = "\improper Syndicate Station"
- icon_state = "syndie_hall"
-
-/area/traitor/kitchen
- name = "\improper Syndicate Kitchen"
- icon_state = "syndie_kitchen"
-
-/area/traitor/empty
- name = "\improper Syndicate Project Room"
- icon_state = "syndie_empty"
-
-
-//AI
-
-/area/ai_monitored/storage/eva
- name = "EVA Storage"
- icon_state = "eva"
-
-/area/ai_monitored/storage/secure
- name = "Secure Storage"
- icon_state = "storage"
-
-/area/ai_monitored/storage/emergency
- name = "Emergency Storage"
- icon_state = "storage"
-
-/area/turret_protected/
- ambientsounds = list('sound/ambience/ambimalf.ogg')
-
-/area/turret_protected/ai_upload
- name = "\improper AI Upload Chamber"
- icon_state = "ai_upload"
-
-/area/turret_protected/ai_upload_foyer
- name = "AI Upload Access"
- icon_state = "ai_foyer"
-
-/area/turret_protected/ai
- name = "\improper AI Chamber"
- icon_state = "ai_chamber"
-
-/area/turret_protected/aisat
- name = "\improper AI Satellite"
- icon_state = "ai"
-
-/area/aisat
- name = "\improper AI Satellite Exterior"
- icon_state = "yellow"
-
-/area/aisat/entrance
- name = "\improper AI Satellite Entrance"
- icon_state = "ai_foyer"
-
-/area/aisat/maintenance
- name = "\improper AI Satellite Maintenance"
- icon_state = "storage"
-
-/area/turret_protected/aisat_interior
- name = "\improper AI Satellite Antechamber"
- icon_state = "ai"
-
-/area/turret_protected/AIsatextFP
- name = "\improper AI Sat Ext"
- icon_state = "storage"
- luminosity = 1
- dynamic_lighting = 0
-
-/area/turret_protected/AIsatextFS
- name = "\improper AI Sat Ext"
- icon_state = "storage"
- luminosity = 1
- dynamic_lighting = 0
-
-/area/turret_protected/AIsatextAS
- name = "\improper AI Sat Ext"
- icon_state = "storage"
- luminosity = 1
- dynamic_lighting = 0
-
-/area/turret_protected/AIsatextAP
- name = "\improper AI Sat Ext"
- icon_state = "storage"
- luminosity = 1
- dynamic_lighting = 0
-
-/area/turret_protected/NewAIMain
- name = "\improper AI Main New"
- icon_state = "storage"
-
-
-
-//Misc
-
-/area/wreck/ai
- name = "\improper AI Chamber"
- icon_state = "ai"
-
-/area/wreck/main
- name = "\improper Wreck"
- icon_state = "storage"
-
-/area/wreck/engineering
- name = "\improper Power Room"
- icon_state = "engine"
-
-/area/wreck/bridge
- name = "\improper Bridge"
- icon_state = "bridge"
-
-/area/generic
- name = "Unknown"
- icon_state = "storage"
-
-
-
-// Telecommunications Satellite
-
-/area/tcommsat
- ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
-
-/area/tcommsat/entrance
- name = "\improper Telecoms Teleporter"
- icon_state = "tcomsatentrance"
-
-/area/tcommsat/chamber
- name = "\improper Telecoms Central Compartment"
- icon_state = "tcomsatcham"
-
-/area/turret_protected/tcomsat
- name = "\improper Telecoms Satellite"
- icon_state = "tcomsatlob"
- ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
-
-/area/turret_protected/tcomfoyer
- name = "\improper Telecoms Foyer"
- icon_state = "tcomsatentrance"
- ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
-
-/area/turret_protected/tcomwest
- name = "\improper Telecoms West Wing"
- icon_state = "tcomsatwest"
- ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
-
-/area/turret_protected/tcomeast
- name = "\improper Telecoms East Wing"
- icon_state = "tcomsateast"
- ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
-
-/area/tcommsat/computer
- name = "\improper Telecoms Control Room"
- icon_state = "tcomsatcomp"
-
-/area/tcommsat/server
- name = "\improper Telecoms Server Room"
- icon_state = "tcomsatcham"
-
-/area/tcommsat/lounge
- name = "\improper Telecoms Lounge"
- icon_state = "tcomsatlounge"
-
-/area/tcommsat/powercontrol
- name = "\improper Telecoms Power Control"
- icon_state = "tcomsatwest"
-
-// Away Missions
-/area/awaymission
- name = "\improper Strange Location"
- icon_state = "away"
- report_alerts = 0
-
-/area/awaymission/example
- name = "\improper Strange Station"
- icon_state = "away"
-
-/area/awaymission/wwmines
- name = "\improper Wild West Mines"
- icon_state = "away1"
- luminosity = 1
- requires_power = 0
-
-/area/awaymission/wwgov
- name = "\improper Wild West Mansion"
- icon_state = "away2"
- luminosity = 1
- requires_power = 0
-
-/area/awaymission/wwrefine
- name = "\improper Wild West Refinery"
- icon_state = "away3"
- luminosity = 1
- requires_power = 0
-
-/area/awaymission/wwvault
- name = "\improper Wild West Vault"
- icon_state = "away3"
- luminosity = 0
-
-/area/awaymission/wwvaultdoors
- name = "\improper Wild West Vault Doors" // this is to keep the vault area being entirely lit because of requires_power
- icon_state = "away2"
- requires_power = 0
- luminosity = 0
-
-/area/awaymission/desert
- name = "Mars"
- icon_state = "away"
-
-/area/awaymission/BMPship1
- name = "\improper Aft Block"
- icon_state = "away1"
-
-/area/awaymission/BMPship2
- name = "\improper Midship Block"
- icon_state = "away2"
-
-/area/awaymission/BMPship3
- name = "\improper Fore Block"
- icon_state = "away3"
-
-/area/awaymission/spacebattle
- name = "\improper Space Battle"
- icon_state = "away"
- requires_power = 0
-
-/area/awaymission/spacebattle/cruiser
- name = "\improper Nanotrasen Cruiser"
-
-/area/awaymission/spacebattle/syndicate1
- name = "\improper Syndicate Assault Ship 1"
-
-/area/awaymission/spacebattle/syndicate2
- name = "\improper Syndicate Assault Ship 2"
-
-/area/awaymission/spacebattle/syndicate3
- name = "\improper Syndicate Assault Ship 3"
-
-/area/awaymission/spacebattle/syndicate4
- name = "\improper Syndicate War Sphere 1"
-
-/area/awaymission/spacebattle/syndicate5
- name = "\improper Syndicate War Sphere 2"
-
-/area/awaymission/spacebattle/syndicate6
- name = "\improper Syndicate War Sphere 3"
-
-/area/awaymission/spacebattle/syndicate7
- name = "\improper Syndicate Fighter"
-
-/area/awaymission/spacebattle/secret
- name = "\improper Hidden Chamber"
-
-/area/awaymission/beach
- name = "Beach"
- icon_state = "beach"
- luminosity = 1
- dynamic_lighting = 0
- requires_power = 0
- ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag2.ogg')
-
-/area/awaymission/undersea
- name = "Undersea"
- icon_state = "undersea"
-
-
-////////////////////////AWAY AREAS///////////////////////////////////
-
-/area/awaycontent
- name = "space"
- report_alerts = 0
-
-/area/awaycontent/a1
- icon_state = "awaycontent1"
-
-/area/awaycontent/a2
- icon_state = "awaycontent2"
-
-/area/awaycontent/a3
- icon_state = "awaycontent3"
-
-/area/awaycontent/a4
- icon_state = "awaycontent4"
-
-/area/awaycontent/a5
- icon_state = "awaycontent5"
-
-/area/awaycontent/a6
- icon_state = "awaycontent6"
-
-/area/awaycontent/a7
- icon_state = "awaycontent7"
-
-/area/awaycontent/a8
- icon_state = "awaycontent8"
-
-/area/awaycontent/a9
- icon_state = "awaycontent9"
-
-/area/awaycontent/a10
- icon_state = "awaycontent10"
-
-/area/awaycontent/a11
- icon_state = "awaycontent11"
-
-/area/awaycontent/a11
- icon_state = "awaycontent12"
-
-/area/awaycontent/a12
- icon_state = "awaycontent13"
-
-/area/awaycontent/a13
- icon_state = "awaycontent14"
-
-/area/awaycontent/a14
- icon_state = "awaycontent14"
-
-/area/awaycontent/a15
- icon_state = "awaycontent15"
-
-/area/awaycontent/a16
- icon_state = "awaycontent16"
-
-/area/awaycontent/a17
- icon_state = "awaycontent17"
-
-/area/awaycontent/a18
- icon_state = "awaycontent18"
-
-/area/awaycontent/a19
- icon_state = "awaycontent19"
-
-/area/awaycontent/a20
- icon_state = "awaycontent20"
-
-/area/awaycontent/a21
- icon_state = "awaycontent21"
-
-/area/awaycontent/a22
- icon_state = "awaycontent22"
-
-/area/awaycontent/a23
- icon_state = "awaycontent23"
-
-/area/awaycontent/a24
- icon_state = "awaycontent24"
-
-/area/awaycontent/a25
- icon_state = "awaycontent25"
-
-/area/awaycontent/a26
- icon_state = "awaycontent26"
-
-/area/awaycontent/a27
- icon_state = "awaycontent27"
-
-/area/awaycontent/a28
- icon_state = "awaycontent28"
-
-/area/awaycontent/a29
- icon_state = "awaycontent29"
-
-/area/awaycontent/a30
- icon_state = "awaycontent30"
-
-////////////////////////VR AREAS///////////////////////////////////
-
-/area/vr
- name = "VR"
- requires_power = 0
- dynamic_lighting = 0
- no_teleportlocs = 1
-
-
-/area/vr/lobby
- name = "VR Lobby"
-
-/area/vr/roman
- name = "Roman Arena"
-
-
-/////////////////////////////////////////////////////////////////////
-/*
- Lists of areas to be used with is_type_in_list.
- Used in gamemodes code at the moment. --rastaf0
-*/
-
-// CENTCOM
-var/list/centcom_areas = list (
- /area/centcom,
- /area/shuttle/escape_pod1/centcom,
- /area/shuttle/escape_pod2/centcom,
- /area/shuttle/escape_pod3/centcom,
- /area/shuttle/escape_pod5/centcom,
- /area/shuttle/transport1,
- /area/shuttle/administration/centcom,
- /area/shuttle/specops/centcom,
-)
-
-//SPACE STATION 13
-var/list/the_station_areas = list (
- /area/shuttle/arrival,
- /area/shuttle/escape,
- /area/shuttle/escape_pod1/station,
- /area/shuttle/escape_pod2/station,
- /area/shuttle/escape_pod3/station,
- /area/shuttle/escape_pod5/station,
- /area/shuttle/prison/station,
- /area/shuttle/administration/station,
- /area/shuttle/specops/station,
- /area/atmos,
- /area/maintenance,
- /area/hallway,
- /area/hallway/primary/fore,
- /area/hallway/primary/starboard,
- /area/hallway/primary/aft,
- /area/hallway/primary/port,
- /area/hallway/primary/central,
- /area/bridge,
- /area/crew_quarters,
- /area/civilian,
- /area/holodeck,
- /area/library,
- /area/chapel,
- /area/escapepodbay,
- /area/lawoffice,
- /area/magistrateoffice,
- /area/clownoffice,
- /area/mimeoffice,
- /area/engine,
- /area/solar,
- /area/assembly,
- /area/teleporter,
- /area/medical,
- /area/security,
- /area/prison,
- /area/quartermaster,
- /area/janitor,
- /area/hydroponics,
- /area/toxins,
- /area/storage,
- /area/construction,
- /area/ai_monitored/storage/eva, //do not try to simplify to "/area/ai_monitored" --rastaf0
- /area/ai_monitored/storage/secure,
- /area/ai_monitored/storage/emergency,
- /area/turret_protected/ai_upload, //do not try to simplify to "/area/turret_protected" --rastaf0
- /area/turret_protected/ai_upload_foyer,
- /area/turret_protected/ai,
-)
+/*
+
+### This file contains a list of all the areas in your station. Format is as follows:
+
+/area/CATEGORY/OR/DESCRIPTOR/NAME (you can make as many subdivisions as you want)
+ name = "NICE NAME" (not required but makes things really nice)
+ icon = "ICON FILENAME" (defaults to areas.dmi)
+ icon_state = "NAME OF ICON" (defaults to "unknown" (blank))
+ requires_power = FALSE (defaults to TRUE)
+ music = "music/music.ogg" (defaults to "music/music.ogg")
+
+NOTE: there are two lists of areas in the end of this file: centcom and station itself. Please maintain these lists valid. --rastaf0
+
+*/
+
+/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
+/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
+var/list/teleportlocs = list()
+/hook/startup/proc/process_teleport_locs()
+ for(var/area/AR in world)
+ if(AR.no_teleportlocs) continue
+ if(teleportlocs.Find(AR.name)) continue
+ var/turf/picked = safepick(get_area_turfs(AR.type))
+ if(picked && is_station_level(picked.z))
+ teleportlocs += AR.name
+ teleportlocs[AR.name] = AR
+
+ teleportlocs = sortAssoc(teleportlocs)
+
+ return 1
+
+var/list/ghostteleportlocs = list()
+/hook/startup/proc/process_ghost_teleport_locs()
+ for(var/area/AR in world)
+ if(ghostteleportlocs.Find(AR.name)) continue
+ var/list/turfs = get_area_turfs(AR.type)
+ if(turfs.len)
+ ghostteleportlocs += AR.name
+ ghostteleportlocs[AR.name] = AR
+
+ ghostteleportlocs = sortAssoc(ghostteleportlocs)
+
+ return 1
+
+/*-----------------------------------------------------------------------------*/
+
+
+/area/admin
+ name = "\improper Admin Room"
+ icon_state = "start"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ hide_attacklogs = TRUE
+
+
+/area/adminconstruction
+ name = "\improper Admin Testing Area"
+ icon_state = "start"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ hide_attacklogs = TRUE
+
+/area/space
+ icon_state = "space"
+ requires_power = TRUE
+ always_unpowered = TRUE
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ power_light = FALSE
+ power_equip = FALSE
+ power_environ = FALSE
+ valid_territory = FALSE
+ outdoors = TRUE
+ ambientsounds = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/traitor.ogg')
+
+/area/space/nearstation
+ icon_state = "space_near"
+ dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
+
+/area/space/atmosalert()
+ return
+
+/area/space/fire_alert()
+ return
+
+/area/space/fire_reset()
+ return
+
+/area/space/readyalert()
+ return
+
+/area/space/partyalert()
+ return
+
+//These are shuttle areas, they must contain two areas in a subgroup if you want to move a shuttle from one
+//place to another. Look at escape shuttle for example.
+//All shuttles show now be under shuttle since we have smooth-wall code.
+
+/area/shuttle
+ no_teleportlocs = TRUE
+ requires_power = FALSE
+ valid_territory = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+
+/area/shuttle/arrival
+ name = "\improper Arrival Shuttle"
+
+/area/shuttle/arrival/pre_game
+ icon_state = "shuttle2"
+
+/area/shuttle/arrival/station
+ icon_state = "shuttle"
+
+/area/shuttle/auxillary_base
+ icon_state = "shuttle"
+
+/area/shuttle/escape
+ name = "\improper Emergency Shuttle"
+ music = "music/escape.ogg"
+ icon_state = "shuttle2"
+ nad_allowed = TRUE
+
+/area/shuttle/pod_1
+ name = "\improper Escape Pod One"
+ music = "music/escape.ogg"
+ icon_state = "shuttle"
+ nad_allowed = TRUE
+
+/area/shuttle/pod_2
+ name = "\improper Escape Pod Two"
+ music = "music/escape.ogg"
+ icon_state = "shuttle"
+ nad_allowed = TRUE
+
+/area/shuttle/pod_3
+ name = "\improper Escape Pod Three"
+ music = "music/escape.ogg"
+ icon_state = "shuttle"
+ nad_allowed = TRUE
+
+/area/shuttle/pod_4
+ name = "\improper Escape Pod Four"
+ music = "music/escape.ogg"
+ icon_state = "shuttle"
+ nad_allowed = TRUE
+
+/area/shuttle/escape_pod1
+ name = "\improper Escape Pod One"
+ music = "music/escape.ogg"
+ nad_allowed = TRUE
+
+/area/shuttle/escape_pod1/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod1/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod1/transit
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod2
+ name = "\improper Escape Pod Two"
+ music = "music/escape.ogg"
+ nad_allowed = TRUE
+
+/area/shuttle/escape_pod2/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod2/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod2/transit
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod3
+ name = "\improper Escape Pod Three"
+ music = "music/escape.ogg"
+ nad_allowed = TRUE
+
+/area/shuttle/escape_pod3/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod3/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod3/transit
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod5 //Pod 4 was lost to meteors
+ name = "\improper Escape Pod Five"
+ music = "music/escape.ogg"
+ nad_allowed = TRUE
+
+/area/shuttle/escape_pod5/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod5/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod5/transit
+ icon_state = "shuttle"
+
+/area/shuttle/mining
+ name = "\improper Mining Shuttle"
+ music = "music/escape.ogg"
+ icon_state = "shuttle"
+
+/area/shuttle/transport
+ icon_state = "shuttle"
+ name = "\improper Transport Shuttle"
+
+/area/shuttle/transport1
+ icon_state = "shuttle"
+ name = "\improper Transport Shuttle"
+
+/area/shuttle/alien/base
+ icon_state = "shuttle"
+ name = "\improper Alien Shuttle Base"
+ requires_power = 1
+
+/area/shuttle/alien/mine
+ icon_state = "shuttle"
+ name = "\improper Alien Shuttle Mine"
+ requires_power = 1
+
+/area/shuttle/gamma/space
+ icon_state = "shuttle"
+ name = "\improper Gamma Armory"
+
+/area/shuttle/gamma/station
+ icon_state = "shuttle"
+ name = "\improper Gamma Armory Station"
+
+/area/shuttle/prison/
+ name = "\improper Prison Shuttle"
+
+/area/shuttle/prison/station
+ icon_state = "shuttle"
+
+/area/shuttle/prison/prison
+ icon_state = "shuttle2"
+
+/area/shuttle/siberia
+ name = "\improper Labor Camp Shuttle"
+ music = "music/escape.ogg"
+ icon_state = "shuttle"
+
+/area/shuttle/specops
+ name = "\improper Special Ops Shuttle"
+ icon_state = "shuttlered"
+
+/area/shuttle/specops/centcom
+ name = "\improper Special Ops Shuttle"
+ icon_state = "shuttlered"
+
+/area/shuttle/specops/station
+ name = "\improper Special Ops Shuttle"
+ icon_state = "shuttlered2"
+
+/area/shuttle/syndicate_elite
+ name = "\improper Syndicate Elite Shuttle"
+ icon_state = "shuttlered"
+ nad_allowed = TRUE
+
+/area/shuttle/syndicate_elite/mothership
+ name = "\improper Syndicate Elite Shuttle"
+ icon_state = "shuttlered"
+
+/area/shuttle/syndicate_elite/station
+ name = "\improper Syndicate Elite Shuttle"
+ icon_state = "shuttlered2"
+
+/area/shuttle/syndicate_sit
+ name = "\improper Syndicate SIT Shuttle"
+ icon_state = "shuttlered"
+ nad_allowed = TRUE
+
+/area/shuttle/assault_pod
+ name = "Steel Rain"
+ icon_state = "shuttle"
+
+/area/shuttle/administration
+ name = "\improper Nanotrasen Vessel"
+ icon_state = "shuttlered"
+
+/area/shuttle/administration/centcom
+ name = "\improper Nanotrasen Vessel Centcom"
+ icon_state = "shuttlered"
+
+/area/shuttle/administration/station
+ name = "\improper Nanotrasen Vessel"
+ icon_state = "shuttlered2"
+
+/area/shuttle/thunderdome
+ name = "honk"
+
+/area/shuttle/thunderdome/grnshuttle
+ name = "\improper Thunderdome GRN Shuttle"
+ icon_state = "green"
+
+/area/shuttle/thunderdome/grnshuttle/dome
+ name = "\improper GRN Shuttle"
+ icon_state = "shuttlegrn"
+
+/area/shuttle/thunderdome/grnshuttle/station
+ name = "\improper GRN Station"
+ icon_state = "shuttlegrn2"
+
+/area/shuttle/thunderdome/redshuttle
+ name = "\improper Thunderdome RED Shuttle"
+ icon_state = "red"
+
+/area/shuttle/thunderdome/redshuttle/dome
+ name = "\improper RED Shuttle"
+ icon_state = "shuttlered"
+
+/area/shuttle/thunderdome/redshuttle/station
+ name = "\improper RED Station"
+ icon_state = "shuttlered2"
+// === Trying to remove these areas:
+
+/area/shuttle/research
+ name = "\improper Research Shuttle"
+ music = "music/escape.ogg"
+ icon_state = "shuttle"
+
+/area/shuttle/research/station
+ icon_state = "shuttle2"
+
+/area/shuttle/research/outpost
+ icon_state = "shuttle"
+
+/area/shuttle/vox
+ name = "\improper Vox Skipjack"
+ icon_state = "shuttle"
+
+/area/shuttle/vox/station
+ name = "\improper Vox Skipjack"
+ icon_state = "yellow"
+
+/area/shuttle/salvage
+ name = "\improper Salvage Ship"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/start
+ name = "\improper Middle of Nowhere"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/arrivals
+ name = "\improper Space Station Auxiliary Docking"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/derelict
+ name = "\improper Derelict Station"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/djstation
+ name = "\improper Ruskie DJ Station"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/north
+ name = "\improper North of the Station"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/east
+ name = "\improper East of the Station"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/south
+ name = "\improper South of the Station"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/commssat
+ name = "\improper The Communications Satellite"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/mining
+ name = "\improper South-West of the Mining Asteroid"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/abandoned_ship
+ name = "\improper Abandoned Ship"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/clown_asteroid
+ name = "\improper Clown Asteroid"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/trading_post
+ name = "\improper Trading Post"
+ icon_state = "yellow"
+
+/area/shuttle/salvage/transit
+ name = "\improper hyperspace"
+ icon_state = "shuttle"
+
+/area/shuttle/supply
+ name = "Supply Shuttle"
+ icon_state = "shuttle3"
+
+/area/shuttle/abandoned
+ name = "Abandoned Ship"
+ icon_state = "shuttle"
+
+/area/shuttle/syndicate
+ name = "Syndicate Nuclear Team Shuttle"
+ icon_state = "shuttle"
+ nad_allowed = TRUE
+
+/area/shuttle/trade
+ name = "Trade Shuttle"
+ icon_state = "shuttle"
+
+/area/shuttle/trade/sol
+ name = "Sol Freighter"
+
+/area/shuttle/freegolem
+ name = "Free Golem Ship"
+ icon_state = "purple"
+ xenobiology_compatible = TRUE
+
+/area/airtunnel1/ // referenced in airtunnel.dm:759
+
+/area/dummy/ // Referenced in engine.dm:261
+
+/area/start // will be unused once kurper gets his login interface patch done
+ name = "start area"
+ icon_state = "start"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ has_gravity = TRUE
+
+// === end remove
+
+// CENTCOM
+
+/area/centcom
+ name = "\improper Centcom"
+ icon_state = "centcom"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ nad_allowed = TRUE
+
+/area/centcom/control
+ name = "\improper Centcom Control"
+ icon_state = "centcom_ctrl"
+
+/area/centcom/evac
+ name = "\improper Centcom Emergency Shuttle"
+ icon_state = "centcom_evac"
+
+/area/centcom/suppy
+ name = "\improper Centcom Supply Shuttle"
+ icon_state = "centcom_supply"
+
+/area/centcom/ferry
+ name = "\improper Centcom Transport Shuttle"
+ icon_state = "centcom_ferry"
+
+/area/centcom/shuttle
+ name = "\improper Centcom Administration Shuttle"
+
+/area/centcom/test
+ name = "\improper Centcom Testing Facility"
+
+/area/centcom/living
+ name = "\improper Centcom Living Quarters"
+
+/area/centcom/specops
+ name = "\improper Centcom Special Ops"
+ icon_state = "centcom_specops"
+
+/area/centcom/gamma
+ name = "\improper Centcom Gamma Armory"
+ icon_state = "centcom_gamma"
+
+/area/centcom/holding
+ name = "\improper Holding Facility"
+
+/area/centcom/bathroom
+ name = "\improper Centcom Emergency Shuttle Bathrooms"
+
+//SYNDICATES
+
+/area/syndicate_mothership
+ name = "\improper Syndicate Forward Base"
+ icon_state = "syndie-ship"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+ nad_allowed = TRUE
+
+/area/syndicate_mothership/control
+ name = "\improper Syndicate Control Room"
+ icon_state = "syndie-control"
+
+/area/syndicate_mothership/elite_squad
+ name = "\improper Syndicate Elite Squad"
+ icon_state = "syndie-elite"
+
+/area/syndicate_mothership/infteam
+ name = "\improper Syndicate Infiltrators"
+ icon_state = "syndie-elite"
+
+//EXTRA
+
+/area/asteroid // -- TLE
+ name = "\improper Asteroid"
+ icon_state = "asteroid"
+ requires_power = FALSE
+ valid_territory = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+
+/area/asteroid/cave // -- TLE
+ name = "\improper Asteroid - Underground"
+ icon_state = "cave"
+ requires_power = FALSE
+ outdoors = TRUE
+
+/area/asteroid/artifactroom
+ name = "\improper Asteroid - Artifact"
+ icon_state = "cave"
+
+/area/tdome
+ name = "\improper Thunderdome"
+ icon_state = "thunder"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ hide_attacklogs = TRUE
+
+
+/area/tdome/arena_source
+ name = "\improper Thunderdome Arena Template"
+ icon_state = "thunder"
+
+/area/tdome/arena
+ name = "\improper Thunderdome Arena"
+ icon_state = "thunder"
+
+/area/tdome/tdome1
+ name = "\improper Thunderdome (Team 1)"
+ icon_state = "green"
+
+/area/tdome/tdome2
+ name = "\improper Thunderdome (Team 2)"
+ icon_state = "yellow"
+
+/area/tdome/tdomeadmin
+ name = "\improper Thunderdome (Admin.)"
+ icon_state = "purple"
+
+/area/tdome/tdomeobserve
+ name = "\improper Thunderdome (Observer.)"
+ icon_state = "purple"
+
+/area/exploration/methlab
+ name = "\improper Abandoned Drug Lab"
+ icon_state = "green"
+
+//Abductors
+/area/abductor_ship
+ name = "\improper Abductor Ship"
+ icon_state = "yellow"
+ requires_power = FALSE
+ has_gravity = TRUE
+
+/area/wizard_station
+ name = "\improper Wizard's Den"
+ icon_state = "yellow"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+
+/area/ninja
+ name = "\improper Ninja Area Parent"
+ icon_state = "ninjabase"
+ requires_power = FALSE
+ no_teleportlocs = TRUE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+
+/area/ninja/outpost
+ name = "\improper SpiderClan Outpost"
+
+/area/ninja/holding
+ name = "\improper SpiderClan Holding Facility"
+
+/area/vox_station
+ name = "\improper Vox Base"
+ icon_state = "yellow"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ no_teleportlocs = TRUE
+
+/area/trader_station
+ name = "Trade Base"
+ icon_state = "yellow"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+
+/area/trader_station/sol
+ name = "Jupiter Station 6"
+
+//Labor camp
+/area/mine/laborcamp
+ name = "Labor Camp"
+ icon_state = "brig"
+
+/area/mine/laborcamp/security
+ name = "Labor Camp Security"
+ icon_state = "security"
+
+//STATION13
+
+/area/atmos
+ name = "Atmospherics"
+ icon_state = "atmos"
+
+/area/atmos/control
+ name = "Atmospherics Control Room"
+ icon_state = "atmos"
+
+/area/atmos/distribution
+ name = "Atmospherics Distribution Loop"
+ icon_state = "atmos"
+
+//Maintenance
+/area/maintenance
+ ambientsounds = list('sound/ambience/ambimaint1.ogg', 'sound/ambience/ambimaint2.ogg', 'sound/ambience/ambimaint3.ogg', 'sound/ambience/ambimaint4.ogg', 'sound/ambience/ambimaint5.ogg')
+ valid_territory = FALSE
+
+/area/maintenance/atmos_control
+ name = "Atmospherics Maintenance"
+ icon_state = "fpmaint"
+
+/area/maintenance/fpmaint
+ name = "EVA Maintenance"
+ icon_state = "fpmaint"
+
+/area/maintenance/fpmaint2
+ name = "Arrivals North Maintenance"
+ icon_state = "fpmaint"
+
+/area/maintenance/fsmaint
+ name = "Dormitory Maintenance"
+ icon_state = "fsmaint"
+
+/area/maintenance/fsmaint2
+ name = "Bar Maintenance"
+ icon_state = "fsmaint"
+
+/area/maintenance/asmaint
+ name = "Medbay Maintenance"
+ icon_state = "asmaint"
+
+/area/maintenance/asmaint2
+ name = "Science Maintenance"
+ icon_state = "asmaint"
+
+/area/maintenance/apmaint
+ name = "Cargo Maintenance"
+ icon_state = "apmaint"
+
+/area/maintenance/maintcentral
+ name = "Bridge Maintenance"
+ icon_state = "maintcentral"
+
+/area/maintenance/fore
+ name = "Fore Maintenance"
+ icon_state = "fmaint"
+
+/area/maintenance/starboard
+ name = "Starboard Maintenance"
+ icon_state = "smaint"
+
+/area/maintenance/port
+ name = "Locker Room Maintenance"
+ icon_state = "pmaint"
+
+/area/maintenance/aft
+ name = "Engineering Maintenance"
+ icon_state = "amaint"
+
+/area/maintenance/engi_shuttle
+ name = "Engineering Shuttle Access"
+ icon_state = "maint_e_shuttle"
+
+/area/maintenance/storage
+ name = "Atmospherics Maintenance"
+ icon_state = "green"
+
+/area/maintenance/incinerator
+ name = "\improper Incinerator"
+ icon_state = "disposal"
+
+/area/maintenance/turbine
+ name = "\improper Turbine"
+ icon_state = "disposal"
+
+/area/maintenance/disposal
+ name = "Waste Disposal"
+ icon_state = "disposal"
+
+/area/maintenance/genetics
+ name = "Genetics Maintenance"
+ icon_state = "asmaint"
+
+
+/area/maintenance/electrical
+ name = "Electrical Maintenance"
+ icon_state = "yellow"
+
+/area/maintenance/abandonedbar
+ name = "Maintenance Bar"
+ icon_state = "yellow"
+ power_equip = 0
+ power_light = 0
+ power_environ = 0
+
+/area/maintenance/electrical_shop
+ name ="Electronics Den"
+ icon_state = "yellow"
+
+/area/maintenance/gambling_den
+ name = "Gambling Den"
+ icon_state = "yellow"
+
+/area/maintenance/consarea
+ name = "Alternate Construction Area"
+ icon_state = "yellow"
+
+
+//Hallway
+
+/area/hallway/primary/fore
+ name = "\improper Fore Primary Hallway"
+ icon_state = "hallF"
+
+/area/hallway/primary/starboard
+ name = "\improper Starboard Primary Hallway"
+ icon_state = "hallS"
+
+/area/hallway/primary/starboard/west
+/area/hallway/primary/starboard/east
+
+/area/hallway/primary/aft
+ name = "\improper Aft Primary Hallway"
+ icon_state = "hallA"
+
+
+/area/hallway/primary/port
+ name = "\improper Port Primary Hallway"
+ icon_state = "hallP"
+
+/area/hallway/primary/port/west
+ name = "\improper Port West Hallway"
+
+/area/hallway/primary/port/east
+ name = "\improper Port East Hallway"
+
+/area/hallway/primary/central
+ name = "\improper Central Primary Hallway"
+ icon_state = "hallC"
+
+/area/hallway/primary/central/north
+/area/hallway/primary/central/south
+/area/hallway/primary/central/west
+/area/hallway/primary/central/east
+/area/hallway/primary/central/nw
+/area/hallway/primary/central/ne
+/area/hallway/primary/central/sw
+/area/hallway/primary/central/se
+
+/area/hallway/secondary/exit
+ name = "\improper Escape Shuttle Hallway"
+ icon_state = "escape"
+
+/area/hallway/secondary/construction
+ name = "\improper Construction Area"
+ icon_state = "construction"
+
+/area/hallway/secondary/entry
+ name = "\improper Arrival Shuttle Hallway"
+ icon_state = "entry"
+
+/area/hallway/secondary/entry/north
+
+/area/hallway/secondary/entry/south
+
+/area/hallway/secondary/entry/louge
+ name = "\improper Arrivals Lounge"
+
+
+//Command
+
+/area/bridge
+ name = "\improper Bridge"
+ icon_state = "bridge"
+ music = "signal"
+
+/area/bridge/meeting_room
+ name = "\improper Heads of Staff Meeting Room"
+ icon_state = "meeting"
+ music = null
+
+/area/crew_quarters/captain
+ name = "\improper Captain's Office"
+ icon_state = "captain"
+
+/area/crew_quarters/captain/bedroom
+ name = "\improper Captain's Bedroom"
+ icon_state = "captain"
+
+/area/crew_quarters/recruit
+ name = "\improper Recruitment Office"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/heads/hop
+ name = "\improper Head of Personnel's Quarters"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/heads/hor
+ name = "\improper Research Director's Quarters"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/heads/chief
+ name = "\improper Chief Engineer's Quarters"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/heads/hos
+ name = "\improper Head of Security's Quarters"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/heads/cmo
+ name = "\improper Chief Medical Officer's Quarters"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/courtroom
+ name = "\improper Courtroom"
+ icon_state = "courtroom"
+
+/area/crew_quarters/heads
+ name = "\improper Head of Personnel's Office"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/hor
+ name = "\improper Research Director's Office"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/hos
+ name = "\improper Head of Security's Office"
+ icon_state = "head_quarters"
+
+/area/crew_quarters/chief
+ name = "\improper Chief Engineer's Office"
+ icon_state = "head_quarters"
+
+/area/mint
+ name = "\improper Mint"
+ icon_state = "green"
+
+/area/comms
+ name = "\improper Communications Relay"
+ icon_state = "tcomsatcham"
+
+/area/server
+ name = "\improper Messaging Server Room"
+ icon_state = "server"
+
+/area/ntrep
+ name = "\improper Nanotrasen Representative's Office"
+ icon_state = "bluenew"
+
+/area/blueshield
+ name = "\improper Blueshield's Office"
+ icon_state = "blueold"
+
+/area/centcomdocks
+ name = "\improper Central Command Docks"
+ icon_state = "centcom"
+
+//Crew
+
+/area/crew_quarters
+ name = "\improper Dormitories"
+ icon_state = "Sleep"
+
+/area/crew_quarters/toilet
+ name = "\improper Dormitory Toilets"
+ icon_state = "toilet"
+
+/area/crew_quarters/sleep
+ name = "\improper Dormitories"
+ icon_state = "Sleep"
+ valid_territory = FALSE
+
+/area/crew_quarters/sleep_male
+ name = "\improper Male Dorm"
+ icon_state = "Sleep"
+
+/area/crew_quarters/sleep_male/toilet_male
+ name = "\improper Male Toilets"
+ icon_state = "toilet"
+
+/area/crew_quarters/sleep_female
+ name = "\improper Female Dorm"
+ icon_state = "Sleep"
+
+/area/crew_quarters/sleep_female/toilet_female
+ name = "\improper Female Toilets"
+ icon_state = "toilet"
+
+/area/crew_quarters/locker
+ name = "\improper Locker Room"
+ icon_state = "locker"
+
+/area/crew_quarters/locker/locker_toilet
+ name = "\improper Locker Toilets"
+ icon_state = "toilet"
+
+/area/crew_quarters/fitness
+ name = "\improper Fitness Room"
+ icon_state = "fitness"
+
+/area/crew_quarters/dorms
+ name = "\improper Dorms"
+ icon_state = "dorms"
+
+/area/crew_quarters/arcade
+ name = "\improper Arcade"
+ icon_state = "arcade"
+
+/area/crew_quarters/cafeteria
+ name = "\improper Cafeteria"
+ icon_state = "cafeteria"
+
+/area/crew_quarters/kitchen
+ name = "\improper Kitchen"
+ icon_state = "kitchen"
+
+/area/crew_quarters/bar
+ name = "\improper Bar"
+ icon_state = "bar"
+
+/area/crew_quarters/bar/atrium
+ name = "Atrium"
+ icon_state = "bar"
+
+/area/crew_quarters/theatre
+ name = "\improper Theatre"
+ icon_state = "Theatre"
+
+/area/crew_quarters/mrchangs
+ name = "\improper Mr Chang's"
+ icon_state = "Theatre"
+
+/area/library
+ name = "\improper Library"
+ icon_state = "library"
+
+/area/library/abandoned
+ name = "\improper Abandoned Library"
+ icon_state = "library"
+
+/area/chapel/main
+ name = "\improper Chapel"
+ icon_state = "chapel"
+ ambientsounds = list('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg')
+
+/area/chapel/office
+ name = "\improper Chapel Office"
+ icon_state = "chapeloffice"
+
+/area/escapepodbay
+ name = "\improper Escape Shuttle Hallway Podbay"
+ icon_state = "escape"
+
+/area/lawoffice
+ name = "\improper Law Office"
+ icon_state = "law"
+
+/area/magistrateoffice
+ name = "\improper Magistrate's Office"
+ icon_state = "magistrate"
+
+/area/clownoffice
+ name = "\improper Clown's Office"
+ icon_state = "clown_office"
+
+/area/mimeoffice
+ name = "\improper Mime's Office"
+ icon_state = "mime_office"
+
+/area/civilian/barber
+ name = "\improper Barber Shop"
+ icon_state = "barber"
+
+/area/civilian/clothing
+ name = "\improper Clothing Shop"
+ icon_state = "Theatre"
+
+/area/civilian/pet_store
+ name = "\improper Pet Store"
+ icon_state = "pet_store"
+
+/area/holodeck
+ name = "\improper Holodeck"
+ icon_state = "Holodeck"
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+
+/area/holodeck/alphadeck
+ name = "\improper Holodeck Alpha"
+
+
+/area/holodeck/source_plating
+ name = "\improper Holodeck - Off"
+ icon_state = "Holodeck"
+
+/area/holodeck/source_emptycourt
+ name = "\improper Holodeck - Empty Court"
+
+/area/holodeck/source_boxingcourt
+ name = "\improper Holodeck - Boxing Court"
+
+/area/holodeck/source_basketball
+ name = "\improper Holodeck - Basketball Court"
+
+/area/holodeck/source_thunderdomecourt
+ name = "\improper Holodeck - Thunderdome Court"
+
+/area/holodeck/source_beach
+ name = "\improper Holodeck - Beach"
+ icon_state = "Holodeck" // Lazy.
+
+/area/holodeck/source_burntest
+ name = "\improper Holodeck - Atmospheric Burn Test"
+
+/area/holodeck/source_wildlife
+ name = "\improper Holodeck - Wildlife Simulation"
+
+/area/holodeck/source_meetinghall
+ name = "\improper Holodeck - Meeting Hall"
+
+/area/holodeck/source_theatre
+ name = "\improper Holodeck - Theatre"
+
+/area/holodeck/source_picnicarea
+ name = "\improper Holodeck - Picnic Area"
+
+/area/holodeck/source_snowfield
+ name = "\improper Holodeck - Snow Field"
+
+/area/holodeck/source_desert
+ name = "\improper Holodeck - Desert"
+
+/area/holodeck/source_space
+ name = "\improper Holodeck - Space"
+
+/area/holodeck/source_knightarena
+ name = "\improper Holodeck - Knight Arena"
+
+
+//Embassies
+/area/embassy/
+ name = "\improper Embassy Hallway"
+
+/area/embassy/tajaran
+ name = "\improper Tajaran Embassy"
+ icon_state = "tajaran"
+
+/area/embassy/skrell
+ name = "\improper Skrell Embassy"
+ icon_state = "skrell"
+
+/area/embassy/unathi
+ name = "\improper Unathi Embassy"
+ icon_state = "unathi"
+
+/area/embassy/kidan
+ name = "\improper Kidan Embassy"
+ icon_state = "kidan"
+
+/area/embassy/diona
+ name = "\improper Diona Embassy"
+ icon_state = "diona"
+
+/area/embassy/slime
+ name = "\improper Slime Person Embassy"
+ icon_state = "slime"
+
+/area/embassy/grey
+ name = "\improper Grey Embassy"
+ icon_state = "grey"
+
+/area/embassy/vox
+ name = "\improper Vox Embassy"
+ icon_state = "vox"
+
+
+
+//Engineering
+/area/engine
+ ambientsounds = list('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg')
+
+/area/engine/engine_smes
+ name = "\improper Engineering SMES"
+ icon_state = "engine_smes"
+ requires_power = FALSE //This area only covers the batteries and they deal with their own power
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+
+/area/engine/engineering
+ name = "Engineering"
+ icon_state = "engine_smes"
+
+/area/engine/break_room
+ name = "\improper Engineering Foyer"
+ icon_state = "engine"
+
+/area/engine/equipmentstorage
+ name = "\improper Engineering Equipment Storage"
+ icon_state = "storage"
+
+/area/engine/hardsuitstorage
+ name = "\improper Engineering Hardsuit Storage"
+ icon_state = "storage"
+
+/area/engine/controlroom
+ name = "\improper Engineering Control Room"
+ icon_state = "engine_control"
+
+/area/engine/gravitygenerator
+ name = "\improper Gravity Generator"
+ icon_state = "engine"
+
+/area/engine/chiefs_office
+ name = "\improper Chief Engineer's office"
+ icon_state = "engine_control"
+
+/area/engine/mechanic_workshop
+ name = "\improper Mechanic Workshop"
+ icon_state = "engine"
+
+/area/engine/mechanic_workshop/hanger
+ name = "\improper Hanger Bay"
+ icon_state = "engine"
+
+/area/engine/supermatter
+ name = "\improper Supermatter Engine"
+ icon_state = "engine"
+
+//Solars
+
+/area/solar
+ requires_power = FALSE
+ valid_territory = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
+
+/area/solar/auxport
+ name = "\improper Fore Port Solar Array"
+ icon_state = "panelsA"
+
+/area/solar/auxstarboard
+ name = "\improper Fore Starboard Solar Array"
+ icon_state = "panelsA"
+
+/area/solar/fore
+ name = "\improper Fore Solar Array"
+ icon_state = "yellow"
+
+/area/solar/aft
+ name = "\improper Aft Solar Array"
+ icon_state = "aft"
+
+/area/solar/starboard
+ name = "\improper Aft Starboard Solar Array"
+ icon_state = "panelsS"
+
+/area/solar/port
+ name = "\improper Aft Port Solar Array"
+ icon_state = "panelsP"
+
+/area/maintenance/auxsolarport
+ name = "\improper Fore Port Solar Maintenance"
+ icon_state = "SolarcontrolA"
+
+/area/maintenance/starboardsolar
+ name = "\improper Aft Starboard Solar Maintenance"
+ icon_state = "SolarcontrolS"
+
+/area/maintenance/portsolar
+ name = "\improper Aft Port Solar Maintenance"
+ icon_state = "SolarcontrolP"
+
+/area/maintenance/auxsolarstarboard
+ name = "\improper Fore Starboard Solar Maintenance"
+ icon_state = "SolarcontrolA"
+
+
+/area/assembly/chargebay
+ name = "\improper Mech Bay"
+ icon_state = "mechbay"
+
+/area/assembly/showroom
+ name = "\improper Robotics Showroom"
+ icon_state = "showroom"
+
+/area/assembly/robotics
+ name = "\improper Robotics Lab"
+ icon_state = "ass_line"
+
+/area/assembly/assembly_line //Derelict Assembly Line
+ name = "\improper Assembly Line"
+ icon_state = "ass_line"
+ power_equip = 0
+ power_light = 0
+ power_environ = 0
+
+//Teleporter
+
+/area/teleporter
+ name = "\improper Teleporter"
+ icon_state = "teleporter"
+ music = "signal"
+
+/area/gateway
+ name = "\improper Gateway"
+ icon_state = "teleporter"
+ music = "signal"
+
+/area/AIsattele
+ name = "\improper Abandoned Teleporter"
+ icon_state = "teleporter"
+ music = "signal"
+ ambientsounds = list('sound/ambience/ambimalf.ogg')
+
+/area/toxins/explab
+ name = "\improper E.X.P.E.R.I-MENTOR Lab"
+ icon_state = "toxmisc"
+
+/area/toxins/explab_chamber
+ name = "\improper E.X.P.E.R.I-MENTOR Chamber"
+ icon_state = "toxmisc"
+
+//MedBay
+
+/area/medical/medbay
+ name = "\improper Medbay"
+ icon_state = "medbay"
+ music = 'sound/ambience/signal.ogg'
+
+//Medbay is a large area, these additional areas help level out APC load.
+/area/medical/medbay2
+ name = "\improper Medbay"
+ icon_state = "medbay2"
+ music = 'sound/ambience/signal.ogg'
+
+/area/medical/medbay3
+ name = "\improper Medbay"
+ icon_state = "medbay3"
+ music = 'sound/ambience/signal.ogg'
+
+
+/area/medical/biostorage
+ name = "\improper Medical Storage"
+ icon_state = "medbaysecstorage"
+ music = 'sound/ambience/signal.ogg'
+
+/area/medical/reception
+ name = "\improper Medbay Reception"
+ icon_state = "medbay"
+ music = 'sound/ambience/signal.ogg'
+
+/area/medical/psych
+ name = "\improper Psych Room"
+ icon_state = "medbaypsych"
+ music = 'sound/ambience/signal.ogg'
+
+/area/medical/medbreak
+ name = "\improper Break Room"
+ icon_state = "medbaybreak"
+ music = 'sound/ambience/signal.ogg'
+
+/area/medical/patients_rooms
+ name = "\improper Patient's Rooms"
+ icon_state = "patients"
+
+/area/medical/ward
+ name = "\improper Medbay Patient Ward"
+ icon_state = "patientsward"
+
+/area/medical/patient_a
+ name = "\improper Isolation A"
+ icon_state = "medbayisoa"
+
+/area/medical/patient_b
+ name = "\improper Isolation B"
+ icon_state = "medbayisob"
+
+/area/medical/patient_c
+ name = "\improper Isolation C"
+ icon_state = "medbayisoc"
+
+/area/medical/iso_access
+ name = "\improper Isolation Access"
+ icon_state = "medbayisoaccess"
+
+/area/medical/cmo
+ name = "\improper Chief Medical Officer's office"
+ icon_state = "CMO"
+
+/area/medical/cmostore
+ name = "\improper Medical Secondary Storage"
+ icon_state = "medbaysecstorage"
+
+/area/medical/robotics
+ name = "\improper Robotics"
+ icon_state = "medresearch"
+
+/area/medical/research
+ name = "\improper Medical Research"
+ icon_state = "medresearch"
+
+/area/medical/research_shuttle_dock
+ name = "\improper Research Shuttle Dock"
+ icon_state = "medresearch"
+
+/area/medical/virology
+ name = "\improper Virology"
+ icon_state = "virology"
+
+/area/medical/virology/lab
+ name = "\improper Virology Laboratory"
+ icon_state = "virology"
+
+/area/medical/morgue
+ name = "\improper Morgue"
+ icon_state = "morgue"
+ ambientsounds = list('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg')
+
+/area/medical/chemistry
+ name = "\improper Chemistry"
+ icon_state = "chem"
+
+/area/medical/surgery
+ name = "\improper Surgery"
+ icon_state = "surgery"
+
+/area/medical/surgery1
+ name = "\improper Surgery 1"
+ icon_state = "surgery1"
+
+/area/medical/surgery2
+ name = "\improper Surgery 2"
+ icon_state = "surgery2"
+
+/area/medical/surgeryobs
+ name = "\improper Surgery Observation"
+ icon_state = "surgery"
+
+/area/medical/cryo
+ name = "\improper Cryogenics"
+ icon_state = "cryo"
+
+/area/medical/exam_room
+ name = "\improper Exam Room"
+ icon_state = "exam_room"
+
+/area/medical/genetics
+ name = "\improper Genetics Lab"
+ icon_state = "genetics"
+
+/area/medical/genetics_cloning
+ name = "\improper Cloning Lab"
+ icon_state = "cloning"
+
+/area/medical/sleeper
+ name = "\improper Medical Treatment Center"
+ icon_state = "exam_room"
+
+/area/medical/paramedic
+ name = "\improper Paramedic"
+ icon_state = "medbay"
+
+//Security
+
+/area/security/main
+ name = "\improper Security Office"
+ icon_state = "securityoffice"
+
+/area/security/lobby
+ name = "\improper Security Lobby"
+ icon_state = "securitylobby"
+
+/area/security/brig
+ name = "\improper Brig"
+ icon_state = "brig"
+
+/area/security/brig/prison_break()
+ for(var/obj/structure/closet/secure_closet/brig/temp_closet in src)
+ temp_closet.locked = 0
+ temp_closet.icon_state = temp_closet.icon_closed
+ for(var/obj/machinery/door_timer/temp_timer in src)
+ temp_timer.releasetime = 1
+ ..()
+
+/area/security/permabrig
+ name = "\improper Prison Wing"
+ icon_state = "sec_prison_perma"
+ fast_despawn = TRUE
+ can_get_auto_cryod = FALSE
+
+/area/security/prison
+ name = "\improper Prison Wing"
+ icon_state = "sec_prison"
+ can_get_auto_cryod = FALSE
+
+/area/security/prison/prison_break()
+ for(var/obj/structure/closet/secure_closet/brig/temp_closet in src)
+ temp_closet.locked = 0
+ temp_closet.icon_state = temp_closet.icon_closed
+ for(var/obj/machinery/door_timer/temp_timer in src)
+ temp_timer.releasetime = 1
+ ..()
+
+/area/security/prison/cell_block
+ name = "\improper Prison Cell Block"
+ icon_state = "brig"
+
+/area/security/prison/cell_block/A
+ name = "\improper Prison Cell Block A"
+ icon_state = "brigcella"
+
+/area/security/prison/cell_block/B
+ name = "\improper Prison Cell Block B"
+ icon_state = "brigcellb"
+
+/area/security/prison/cell_block/C
+ name = "\improper Prison Cell Block C"
+ icon_state = "brig"
+
+/area/security/execution
+ name = "\improper Execution"
+ icon_state = "execution"
+ can_get_auto_cryod = FALSE
+
+/area/security/processing
+ name = "\improper Prisoner Processing"
+ icon_state = "prisonerprocessing"
+ can_get_auto_cryod = FALSE
+
+/area/security/interrogation
+ name = "\improper Interrogation"
+ icon_state = "interrogation"
+ can_get_auto_cryod = FALSE
+
+/area/security/seceqstorage
+ name = "\improper Security Equipment Storage"
+ icon_state = "securityequipmentstorage"
+
+/area/security/interrogationhallway
+ name = "\improper Interrogation Hallway"
+ icon_state = "interrogationhall"
+
+/area/security/courtroomdandp
+ name = "\improper Courtroom Defense and Prosecution"
+ icon_state = "seccourt"
+
+/area/security/interrogationobs
+ name = "\improper Interrogation Observation"
+ icon_state = "security"
+ can_get_auto_cryod = FALSE
+
+/area/security/evidence
+ name = "\improper Evidence Room"
+ icon_state = "evidence"
+
+/area/security/prisonlockers
+ name = "\improper Prisoner Lockers"
+ icon_state = "sec_prison_lockers"
+ can_get_auto_cryod = FALSE
+
+/area/security/medbay
+ name = "\improper Security Medbay"
+ icon_state = "security_medbay"
+
+/area/security/prisonershuttle
+ name = "\improper Security Prisoner Shuttle"
+ icon_state = "security"
+ can_get_auto_cryod = FALSE
+
+/area/security/warden
+ name = "\improper Warden's Office"
+ icon_state = "Warden"
+
+/area/security/armoury
+ name = "\improper Armory"
+ icon_state = "armory"
+
+/area/security/securearmoury
+ name = "\improper Secure Armory"
+ icon_state = "secarmory"
+
+/area/security/securehallway
+ name = "\improper Security Secure Hallway"
+ icon_state = "securehall"
+
+/area/security/hos
+ name = "\improper Head of Security's Office"
+ icon_state = "sec_hos"
+
+/area/security/podbay
+ name = "\improper Security Podbay"
+ icon_state = "securitypodbay"
+
+/area/security/detectives_office
+ name = "\improper Detective's Office"
+ icon_state = "detective"
+
+/area/security/range
+ name = "\improper Firing Range"
+ icon_state = "firingrange"
+
+/area/security/nuke_storage
+ name = "\improper Vault"
+ icon_state = "nuke_storage"
+
+/area/security/customs
+ name = "\improper Customs"
+ icon_state = "checkpoint1"
+
+/area/security/customs2
+ name = "\improper Customs"
+ icon_state = "security"
+
+/area/security/checkpoint
+ name = "\improper Security Checkpoint"
+ icon_state = "checkpoint1"
+
+/area/security/checkpoint2
+ name = "\improper Security Checkpoint"
+ icon_state = "security"
+
+/area/security/checkpoint/supply
+ name = "Security Post - Cargo Bay"
+ icon_state = "checkpoint1"
+
+/area/security/checkpoint/engineering
+ name = "Security Post - Engineering"
+ icon_state = "checkpoint1"
+
+/area/security/checkpoint/medical
+ name = "Security Post - Medbay"
+ icon_state = "checkpoint1"
+
+/area/security/checkpoint/science
+ name = "Security Post - Science"
+ icon_state = "checkpoint1"
+
+/area/security/vacantoffice
+ name = "\improper Vacant Office"
+ icon_state = "security"
+
+/area/security/vacantoffice2
+ name = "\improper Vacant Office"
+ icon_state = "security"
+
+/area/quartermaster
+ name = "\improper Quartermasters"
+ icon_state = "quart"
+
+///////////WORK IN PROGRESS//////////
+
+/area/quartermaster/sorting
+ name = "\improper Delivery Office"
+ icon_state = "quartstorage"
+
+////////////WORK IN PROGRESS//////////
+
+/area/quartermaster/office
+ name = "\improper Cargo Office"
+ icon_state = "quartoffice"
+
+/area/quartermaster/storage
+ name = "\improper Cargo Bay"
+ icon_state = "quartstorage"
+
+/area/quartermaster/qm
+ name = "\improper Quartermaster's Office"
+ icon_state = "quart"
+
+/area/quartermaster/miningdock
+ name = "\improper Mining Dock"
+ icon_state = "mining"
+
+/area/quartermaster/miningstorage
+ name = "\improper Mining Storage"
+ icon_state = "green"
+
+/area/quartermaster/mechbay
+ name = "\improper Mech Bay"
+ icon_state = "yellow"
+
+/area/janitor
+ name = "\improper Custodial Closet"
+ icon_state = "janitor"
+
+/area/hydroponics
+ name = "\improper Hydroponics"
+ icon_state = "hydro"
+
+/area/hydroponics/abandoned_garden
+ name = "\improper Abandoned Garden"
+ icon_state = "hydro"
+
+//Toxins
+
+/area/toxins/lab
+ name = "\improper Research and Development"
+ icon_state = "toxlab"
+
+/area/toxins/hallway
+ name = "\improper Research Lab"
+ icon_state = "toxlab"
+
+/area/toxins/rdoffice
+ name = "\improper Research Director's Office"
+ icon_state = "head_quarters"
+
+/area/toxins/supermatter
+ name = "\improper Supermatter Lab"
+ icon_state = "toxlab"
+
+/area/toxins/xenobiology
+ name = "\improper Xenobiology Lab"
+ icon_state = "toxmix"
+ xenobiology_compatible = TRUE
+
+/area/toxins/xenobiology/xenoflora_storage
+ name = "\improper Xenoflora Storage"
+ icon_state = "toxlab"
+
+/area/toxins/xenobiology/xenoflora
+ name = "\improper Xenoflora Lab"
+ icon_state = "toxlab"
+
+/area/toxins/storage
+ name = "\improper Toxins Storage"
+ icon_state = "toxstorage"
+
+/area/toxins/test_area
+ name = "\improper Toxins Test Area"
+ icon_state = "toxtest"
+ valid_territory = FALSE
+
+/area/toxins/mixing
+ name = "\improper Toxins Mixing Room"
+ icon_state = "toxmix"
+
+/area/toxins/launch
+ name = "Toxins Launch Room"
+ icon_state = "toxlaunch"
+
+/area/toxins/misc_lab
+ name = "\improper Research Testing Lab"
+ icon_state = "toxmisc"
+
+/area/toxins/test_chamber
+ name = "\improper Research Testing Chamber"
+ icon_state = "toxtest"
+
+/area/toxins/server
+ name = "\improper Server Room"
+ icon_state = "server"
+
+/area/toxins/server_coldroom
+ name = "\improper Server Coldroom"
+ icon_state = "servercold"
+
+/area/toxins/explab
+ name = "\improper Experimentation Lab"
+ icon_state = "toxmisc"
+
+//Storage
+
+/area/storage/tools
+ name = "Auxiliary Tool Storage"
+ icon_state = "storage"
+
+/area/storage/primary
+ name = "Primary Tool Storage"
+ icon_state = "primarystorage"
+
+/area/storage/autolathe
+ name = "Autolathe Storage"
+ icon_state = "storage"
+
+/area/storage/art
+ name = "Art Supply Storage"
+ icon_state = "storage"
+
+/area/storage/auxillary
+ name = "Auxillary Storage"
+ icon_state = "auxstorage"
+
+/area/storage/eva
+ name = "EVA Storage"
+ icon_state = "eva"
+
+/area/storage/secure
+ name = "Secure Storage"
+ icon_state = "storage"
+
+/area/storage/emergency
+ name = "Starboard Emergency Storage"
+ icon_state = "emergencystorage"
+
+/area/storage/emergency2
+ name = "Port Emergency Storage"
+ icon_state = "emergencystorage"
+
+/area/storage/tech
+ name = "Technical Storage"
+ icon_state = "auxstorage"
+
+/area/storage/office
+ name = "\improper Office Supplies"
+ icon_state = "office_supplies"
+
+// ENGIE OUTPOST
+
+/area/engiestation
+ name = "\improper Engineering Outpost"
+ icon_state = "construction"
+
+/area/engiestation/solars
+ name = "\improper Engineering Outpost Solars"
+ icon_state = "panelsP"
+
+//DJSTATION
+
+/area/djstation
+ name = "\improper Ruskie DJ Station"
+ icon_state = "DJ"
+
+/area/djstation/solars
+ name = "\improper Ruskie DJ Station Solars"
+ icon_state = "DJ"
+
+//DERELICT
+
+/area/derelict
+ name = "\improper Derelict Station"
+ icon_state = "storage"
+
+/area/derelict/hallway/primary
+ name = "\improper Derelict Primary Hallway"
+ icon_state = "hallP"
+
+/area/derelict/hallway/secondary
+ name = "\improper Derelict Secondary Hallway"
+ icon_state = "hallS"
+
+/area/derelict/arrival
+ name = "\improper Derelict Arrival Centre"
+ icon_state = "yellow"
+
+/area/derelict/storage/equipment
+ name = "Derelict Equipment Storage"
+
+/area/derelict/storage/storage_access
+ name = "Derelict Storage Access"
+
+/area/derelict/storage/engine_storage
+ name = "Derelict Engine Storage"
+ icon_state = "green"
+
+/area/derelict/bridge
+ name = "\improper Derelict Control Room"
+ icon_state = "bridge"
+
+/area/derelict/secret
+ name = "\improper Derelict Secret Room"
+ icon_state = "library"
+
+/area/derelict/bridge/access
+ name = "Derelict Control Room Access"
+ icon_state = "auxstorage"
+
+/area/derelict/bridge/ai_upload
+ name = "\improper Derelict Computer Core"
+ icon_state = "ai"
+
+/area/derelict/solar_control
+ name = "\improper Derelict Solar Control"
+ icon_state = "engine"
+
+/area/derelict/se_solar
+ name = "South East Solars"
+ icon_state = "engine"
+
+/area/derelict/crew_quarters
+ name = "\improper Derelict Crew Quarters"
+ icon_state = "fitness"
+
+/area/derelict/medical
+ name = "Derelict Medbay"
+ icon_state = "medbay"
+
+/area/derelict/medical/morgue
+ name = "\improper Derelict Morgue"
+ icon_state = "morgue"
+
+/area/derelict/medical/chapel
+ name = "\improper Derelict Chapel"
+ icon_state = "chapel"
+
+/area/derelict/teleporter
+ name = "\improper Derelict Teleporter"
+ icon_state = "teleporter"
+
+/area/derelict/eva
+ name = "Derelict EVA Storage"
+ icon_state = "eva"
+
+/area/shuttle/derelict/ship/start
+ name = "\improper Abandoned Ship"
+ icon_state = "yellow"
+
+/area/shuttle/derelict/ship/transit
+ name = "\improper Abandoned Ship"
+ icon_state = "yellow"
+
+/area/shuttle/derelict/ship/engipost
+ name = "\improper Engineering Outpost"
+ icon_state = "yellow"
+
+/area/shuttle/derelict/ship/station
+ name = "\improper North of SS13"
+ icon_state = "yellow"
+
+/area/solar/derelict_starboard
+ name = "\improper Derelict Starboard Solar Array"
+ icon_state = "panelsS"
+
+/area/solar/derelict_aft
+ name = "\improper Derelict Aft Solar Array"
+ icon_state = "aft"
+
+/area/derelict/singularity_engine
+ name = "\improper Derelict Singularity Engine"
+ icon_state = "engine"
+
+/area/derelict/gravity_generator
+ name = "\improper Derelict Gravity Generator Room"
+ icon_state = "red"
+
+/area/derelict/atmospherics
+ name = "Derelict Atmospherics"
+ icon_state = "red"
+
+//HALF-BUILT STATION (REPLACES DERELICT IN BAYCODE, ABOVE IS LEFT FOR DOWNSTREAM)
+
+/area/shuttle/constructionsite
+ name = "\improper Construction Site Shuttle"
+ icon_state = "yellow"
+
+/area/shuttle/constructionsite/station
+ name = "\improper Construction Site Shuttle"
+
+/area/shuttle/constructionsite/site
+ name = "\improper Construction Site Shuttle"
+
+/area/constructionsite
+ name = "\improper Construction Site"
+ icon_state = "storage"
+
+/area/constructionsite/storage
+ name = "\improper Construction Site Storage Area"
+
+/area/constructionsite/science
+ name = "\improper Construction Site Research"
+ icon_state = "medresearch"
+
+/area/constructionsite/bridge
+ name = "\improper Construction Site Bridge"
+ icon_state = "bridge"
+
+/area/constructionsite/hallway/center
+ name = "\improper Construction Site Central Hallway"
+ icon_state = "hallC"
+
+/area/constructionsite/hallway/engcore
+ name = "\improper Construction Site Eng Core"
+ icon_state = "green"
+
+/area/constructionsite/hallway/fore
+ name = "\improper Construction Site Fore"
+ icon_state = "green"
+
+/area/constructionsite/hallway/port
+ name = "\improper Construction Site Port"
+ icon_state = "hallP"
+
+/area/constructionsite/hallway/aft
+ name = "\improper Construction Site Aft"
+ icon_state = "hallA"
+
+/area/constructionsite/hallway/starboard
+ name = "\improper Construction Site Starboard"
+ icon_state = "hallS"
+
+/area/constructionsite/atmospherics
+ name = "\improper Construction Site Atmospherics"
+ icon_state = "atmos"
+
+/area/constructionsite/medical
+ name = "\improper Construction Site Medbay"
+ icon_state = "medbay"
+
+/area/constructionsite/ai
+ name = "\improper Construction Computer Core"
+ icon_state = "ai"
+
+/area/constructionsite/engineering
+ name = "\improper Construction Site Engine Bay"
+ icon_state = "engine"
+
+/area/solar/constructionsite
+ name = "\improper Construction Site Solars"
+ icon_state = "panelsA"
+
+
+//Construction
+
+/area/construction
+ name = "\improper Construction Area"
+ icon_state = "yellow"
+
+/area/mining_construction
+ name = "Auxillary Base Construction"
+ icon_state = "yellow"
+
+/area/construction/supplyshuttle
+ name = "\improper Supply Shuttle"
+ icon_state = "yellow"
+
+/area/construction/quarters
+ name = "\improper Engineer's Quarters"
+ icon_state = "yellow"
+
+/area/construction/qmaint
+ name = "Maintenance"
+ icon_state = "yellow"
+
+/area/construction/hallway
+ name = "\improper Hallway"
+ icon_state = "yellow"
+
+/area/construction/solars
+ name = "\improper Solar Panels"
+ icon_state = "yellow"
+
+/area/construction/solarscontrol
+ name = "\improper Solar Panel Control"
+ icon_state = "yellow"
+
+/area/construction/Storage
+ name = "Construction Site Storage"
+ icon_state = "yellow"
+
+
+//GAYBAR
+/area/secret/gaybar
+ name = "\improper Dance Bar"
+ icon_state = "dancebar"
+
+
+//Traitor Station
+/area/traitor
+ name = "\improper Syndicate Base"
+ icon_state = "syndie_hall"
+ report_alerts = FALSE
+
+/area/traitor/rnd
+ name = "\improper Syndicate Research and Development"
+ icon_state = "syndie_rnd"
+
+/area/traitor/chem
+ name = "\improper Syndicate Chemistry"
+ icon_state = "syndie_chem"
+
+/area/traitor/tox
+ name = "\improper Syndicate Toxins"
+ icon_state = "syndie_tox"
+
+/area/traitor/atmos
+ name = "\improper Syndicate Atmos"
+ icon_state = "syndie_atmo"
+
+/area/traitor/inter
+ name = "\improper Syndicate Interrogation"
+ icon_state = "syndie_inter"
+
+/area/traitor/radio
+ name = "\improper Syndicate Eavesdropping Booth"
+ icon_state = "syndie_radio"
+
+/area/traitor/surgery
+ name = "\improper Syndicate Surgery Theatre"
+ icon_state = "syndie_surgery"
+
+/area/traitor/hall
+ name = "\improper Syndicate Station"
+ icon_state = "syndie_hall"
+
+/area/traitor/kitchen
+ name = "\improper Syndicate Kitchen"
+ icon_state = "syndie_kitchen"
+
+/area/traitor/empty
+ name = "\improper Syndicate Project Room"
+ icon_state = "syndie_empty"
+
+
+//AI
+
+/area/ai_monitored/storage/eva
+ name = "EVA Storage"
+ icon_state = "eva"
+
+/area/ai_monitored/storage/secure
+ name = "Secure Storage"
+ icon_state = "storage"
+
+/area/ai_monitored/storage/emergency
+ name = "Emergency Storage"
+ icon_state = "storage"
+
+/area/turret_protected/
+ ambientsounds = list('sound/ambience/ambimalf.ogg')
+
+/area/turret_protected/ai_upload
+ name = "\improper AI Upload Chamber"
+ icon_state = "ai_upload"
+
+/area/turret_protected/ai_upload_foyer
+ name = "AI Upload Access"
+ icon_state = "ai_foyer"
+
+/area/turret_protected/ai
+ name = "\improper AI Chamber"
+ icon_state = "ai_chamber"
+
+/area/turret_protected/aisat
+ name = "\improper AI Satellite"
+ icon_state = "ai"
+
+/area/aisat
+ name = "\improper AI Satellite Exterior"
+ icon_state = "yellow"
+
+/area/aisat/entrance
+ name = "\improper AI Satellite Entrance"
+ icon_state = "ai_foyer"
+
+/area/aisat/maintenance
+ name = "\improper AI Satellite Maintenance"
+ icon_state = "storage"
+
+/area/turret_protected/aisat_interior
+ name = "\improper AI Satellite Antechamber"
+ icon_state = "ai"
+
+
+//Misc
+
+/area/wreck/ai
+ name = "\improper AI Chamber"
+ icon_state = "ai"
+
+/area/wreck/main
+ name = "\improper Wreck"
+ icon_state = "storage"
+
+/area/wreck/engineering
+ name = "\improper Power Room"
+ icon_state = "engine"
+
+/area/wreck/bridge
+ name = "\improper Bridge"
+ icon_state = "bridge"
+
+/area/generic
+ name = "Unknown"
+ icon_state = "storage"
+
+
+
+// Telecommunications Satellite
+
+/area/tcommsat
+ ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
+
+/area/tcommsat/entrance
+ name = "\improper Telecoms Teleporter"
+ icon_state = "tcomsatentrance"
+
+/area/tcommsat/chamber
+ name = "\improper Telecoms Central Compartment"
+ icon_state = "tcomsatcham"
+
+/area/turret_protected/tcomsat
+ name = "\improper Telecoms Satellite"
+ icon_state = "tcomsatlob"
+ ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
+
+/area/turret_protected/tcomfoyer
+ name = "\improper Telecoms Foyer"
+ icon_state = "tcomsatentrance"
+ ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
+
+/area/turret_protected/tcomwest
+ name = "\improper Telecoms West Wing"
+ icon_state = "tcomsatwest"
+ ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
+
+/area/turret_protected/tcomeast
+ name = "\improper Telecoms East Wing"
+ icon_state = "tcomsateast"
+ ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
+
+/area/tcommsat/computer
+ name = "\improper Telecoms Control Room"
+ icon_state = "tcomsatcomp"
+
+/area/tcommsat/server
+ name = "\improper Telecoms Server Room"
+ icon_state = "tcomsatcham"
+
+/area/tcommsat/lounge
+ name = "\improper Telecoms Lounge"
+ icon_state = "tcomsatlounge"
+
+/area/tcommsat/powercontrol
+ name = "\improper Telecoms Power Control"
+ icon_state = "tcomsatwest"
+
+// Away Missions
+/area/awaymission
+ name = "\improper Strange Location"
+ icon_state = "away"
+ report_alerts = FALSE
+
+/area/awaymission/example
+ name = "\improper Strange Station"
+ icon_state = "away"
+
+/area/awaymission/desert
+ name = "Mars"
+ icon_state = "away"
+
+/area/awaymission/beach
+ name = "Beach"
+ icon_state = "beach"
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ requires_power = FALSE
+ ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag2.ogg')
+
+/area/awaymission/undersea
+ name = "Undersea"
+ icon_state = "undersea"
+
+
+////////////////////////AWAY AREAS///////////////////////////////////
+
+/area/awaycontent
+ name = "space"
+ report_alerts = FALSE
+
+/area/awaycontent/a1
+ icon_state = "awaycontent1"
+
+/area/awaycontent/a2
+ icon_state = "awaycontent2"
+
+/area/awaycontent/a3
+ icon_state = "awaycontent3"
+
+/area/awaycontent/a4
+ icon_state = "awaycontent4"
+
+/area/awaycontent/a5
+ icon_state = "awaycontent5"
+
+/area/awaycontent/a6
+ icon_state = "awaycontent6"
+
+/area/awaycontent/a7
+ icon_state = "awaycontent7"
+
+/area/awaycontent/a8
+ icon_state = "awaycontent8"
+
+/area/awaycontent/a9
+ icon_state = "awaycontent9"
+
+/area/awaycontent/a10
+ icon_state = "awaycontent10"
+
+/area/awaycontent/a11
+ icon_state = "awaycontent11"
+
+/area/awaycontent/a11
+ icon_state = "awaycontent12"
+
+/area/awaycontent/a12
+ icon_state = "awaycontent13"
+
+/area/awaycontent/a13
+ icon_state = "awaycontent14"
+
+/area/awaycontent/a14
+ icon_state = "awaycontent14"
+
+/area/awaycontent/a15
+ icon_state = "awaycontent15"
+
+/area/awaycontent/a16
+ icon_state = "awaycontent16"
+
+/area/awaycontent/a17
+ icon_state = "awaycontent17"
+
+/area/awaycontent/a18
+ icon_state = "awaycontent18"
+
+/area/awaycontent/a19
+ icon_state = "awaycontent19"
+
+/area/awaycontent/a20
+ icon_state = "awaycontent20"
+
+/area/awaycontent/a21
+ icon_state = "awaycontent21"
+
+/area/awaycontent/a22
+ icon_state = "awaycontent22"
+
+/area/awaycontent/a23
+ icon_state = "awaycontent23"
+
+/area/awaycontent/a24
+ icon_state = "awaycontent24"
+
+/area/awaycontent/a25
+ icon_state = "awaycontent25"
+
+/area/awaycontent/a26
+ icon_state = "awaycontent26"
+
+/area/awaycontent/a27
+ icon_state = "awaycontent27"
+
+/area/awaycontent/a28
+ icon_state = "awaycontent28"
+
+/area/awaycontent/a29
+ icon_state = "awaycontent29"
+
+/area/awaycontent/a30
+ icon_state = "awaycontent30"
+
+////////////////////////VR AREAS///////////////////////////////////
+
+/area/vr
+ name = "VR"
+ requires_power = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ no_teleportlocs = TRUE
+
+/area/vr/lobby
+ name = "VR Lobby"
+
+/area/vr/roman
+ name = "Roman Arena"
+
+
+/////////////////////////////////////////////////////////////////////
+/*
+ Lists of areas to be used with is_type_in_list.
+ Used in gamemodes code at the moment. --rastaf0
+*/
+
+// CENTCOM
+var/list/centcom_areas = list (
+ /area/centcom,
+ /area/shuttle/escape_pod1/centcom,
+ /area/shuttle/escape_pod2/centcom,
+ /area/shuttle/escape_pod3/centcom,
+ /area/shuttle/escape_pod5/centcom,
+ /area/shuttle/transport1,
+ /area/shuttle/administration/centcom,
+ /area/shuttle/specops/centcom,
+)
+
+//SPACE STATION 13
+var/list/the_station_areas = list (
+ /area/shuttle/arrival,
+ /area/shuttle/escape,
+ /area/shuttle/escape_pod1/station,
+ /area/shuttle/escape_pod2/station,
+ /area/shuttle/escape_pod3/station,
+ /area/shuttle/escape_pod5/station,
+ /area/shuttle/prison/station,
+ /area/shuttle/administration/station,
+ /area/shuttle/specops/station,
+ /area/atmos,
+ /area/maintenance,
+ /area/hallway,
+ /area/hallway/primary/fore,
+ /area/hallway/primary/starboard,
+ /area/hallway/primary/aft,
+ /area/hallway/primary/port,
+ /area/hallway/primary/central,
+ /area/bridge,
+ /area/crew_quarters,
+ /area/civilian,
+ /area/holodeck,
+ /area/library,
+ /area/chapel,
+ /area/escapepodbay,
+ /area/lawoffice,
+ /area/magistrateoffice,
+ /area/clownoffice,
+ /area/mimeoffice,
+ /area/engine,
+ /area/solar,
+ /area/assembly,
+ /area/teleporter,
+ /area/medical,
+ /area/security,
+ /area/quartermaster,
+ /area/janitor,
+ /area/hydroponics,
+ /area/toxins,
+ /area/storage,
+ /area/construction,
+ /area/ai_monitored/storage/eva, //do not try to simplify to "/area/ai_monitored" --rastaf0
+ /area/ai_monitored/storage/secure,
+ /area/ai_monitored/storage/emergency,
+ /area/turret_protected/ai_upload, //do not try to simplify to "/area/turret_protected" --rastaf0
+ /area/turret_protected/ai_upload_foyer,
+ /area/turret_protected/ai,
+)
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index a74314a9919..2e7448ec5c8 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -1,9 +1,61 @@
-// Areas.dm
-
-// ===
/area
+ var/fire = null
+ var/atmosalm = ATMOS_ALARM_NONE
+ var/poweralm = TRUE
+ var/party = null
+ var/report_alerts = TRUE // Should atmos alerts notify the AI/computers
+ level = null
+ name = "Space"
+ icon = 'icons/turf/areas.dmi'
+ icon_state = "unknown"
+ layer = AREA_LAYER
+ plane = BLACKNESS_PLANE //Keeping this on the default plane, GAME_PLANE, will make area overlays fail to render on FLOOR_PLANE.
+ luminosity = 0
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ invisibility = INVISIBILITY_LIGHTING
+ var/valid_territory = TRUE //used for cult summoning areas on station zlevel
+ var/map_name // Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
+ var/lightswitch = TRUE
+
+ var/eject = null
+
+ var/debug = FALSE
+ var/requires_power = TRUE
+ var/always_unpowered = FALSE //this gets overriden to 1 for space in area/New()
+
+ var/power_equip = TRUE
+ var/power_light = TRUE
+ var/power_environ = TRUE
+ var/music = null
+ var/used_equip = FALSE
+ var/used_light = FALSE
+ var/used_environ = FALSE
+ var/static_equip
+ var/static_light = FALSE
+ var/static_environ
+
+ var/has_gravity = TRUE
+ var/list/apc = list()
+ var/no_air = null
+
+ var/air_doors_activated = FALSE
+
+ var/tele_proof = FALSE
+ var/no_teleportlocs = FALSE
+
+ var/outdoors = FALSE //For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room)
+ var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
+ var/nad_allowed = FALSE //is the station NAD allowed on this area?
+
+ // This var is used with the maploader (modules/awaymissions/maploader/reader.dm)
+ // if this is 1, when used in a map snippet, this will instantiate a unique
+ // area from any other instances already present (meaning you can have
+ // separate APCs, and so on)
+ var/there_can_be_many = FALSE
+
var/global/global_uid = 0
var/uid
+
var/list/ambientsounds = list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg',\
'sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg',\
'sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg',\
@@ -11,42 +63,49 @@
'sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg',\
'sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
- // This var is used with the maploader (modules/awaymissions/maploader/reader.dm)
- // if this is 1, when used in a map snippet, this will instantiate a unique
- // area from any other instances already present (meaning you can have
- // separate APCs, and so on)
- var/there_can_be_many = 0
+ var/fast_despawn = FALSE
+ var/can_get_auto_cryod = TRUE
+ var/hide_attacklogs = FALSE // For areas such as thunderdome, lavaland syndiebase, etc which generate a lot of spammy attacklogs. Reduces log priority.
-
-/area/New()
-
- ..()
+/area/Initialize(mapload)
+ GLOB.all_areas += src
icon_state = ""
layer = AREA_LAYER
uid = ++global_uid
- GLOB.all_areas += src
+
map_name = name // Save the initial (the name set in the map) name of the area.
- if(type == /area) // override defaults for space. TODO: make space areas of type /area/space rather than /area
- requires_power = 1
- always_unpowered = 1
- dynamic_lighting = 1
- power_light = 0
- power_equip = 0
- power_environ = 0
-// lighting_state = 4
- //has_gravity = 0 // Space has gravity. Because.. because.
+ if(requires_power)
+ luminosity = 0
+ else
+ power_light = TRUE
+ power_equip = TRUE
+ power_environ = TRUE
- if(requires_power != 0)
- power_light = 0 //rastaf0
- power_equip = 0 //rastaf0
- power_environ = 0 //rastaf0
+ if(dynamic_lighting == DYNAMIC_LIGHTING_FORCED)
+ dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
+ luminosity = 0
+ else if(dynamic_lighting != DYNAMIC_LIGHTING_IFSTARLIGHT)
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ if(dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
+ dynamic_lighting = config.starlight ? DYNAMIC_LIGHTING_ENABLED : DYNAMIC_LIGHTING_DISABLED
+
+ . = ..()
blend_mode = BLEND_MULTIPLY // Putting this in the constructor so that it stops the icons being screwed up in the map editor.
-/area/Initialize()
- . = ..()
+ if(!IS_DYNAMIC_LIGHTING(src))
+ add_overlay(/obj/effect/fullbright)
+ reg_in_areas_in_z()
+
+ return INITIALIZE_HINT_LATELOAD
+
+/area/LateInitialize()
+ . = ..()
+ power_change() // all machines set to current power level, also updates lighting icon
+
+/area/proc/reg_in_areas_in_z()
if(contents.len)
var/list/areas_in_z = space_manager.areas_in_z
var/z
@@ -63,12 +122,6 @@
areas_in_z["[z]"] = list()
areas_in_z["[z]"] += src
- return INITIALIZE_HINT_LATELOAD
-
-/area/LateInitialize()
- . = ..()
- power_change() // all machines set to current power level, also updates lighting icon
-
/area/proc/get_cameras()
var/list/cameras = list()
for(var/obj/machinery/camera/C in src)
@@ -77,10 +130,11 @@
/area/proc/atmosalert(danger_level, var/alarm_source, var/force = FALSE)
- if(danger_level == ATMOS_ALARM_NONE)
- atmosphere_alarm.clearAlarm(src, alarm_source)
- else
- atmosphere_alarm.triggerAlarm(src, alarm_source, severity = danger_level)
+ if(report_alerts)
+ if(danger_level == ATMOS_ALARM_NONE)
+ SSalarms.atmosphere_alarm.clearAlarm(src, alarm_source)
+ else
+ SSalarms.atmosphere_alarm.triggerAlarm(src, alarm_source, severity = danger_level)
//Check all the alarms before lowering atmosalm. Raising is perfectly fine. If force = 1 we don't care.
for(var/obj/machinery/alarm/AA in src)
@@ -158,9 +212,9 @@
if(A.density)
A.lock()
- burglar_alarm.triggerAlarm(src, trigger)
+ SSalarms.burglar_alarm.triggerAlarm(src, trigger)
spawn(600)
- burglar_alarm.clearAlarm(src, trigger)
+ SSalarms.burglar_alarm.clearAlarm(src, trigger)
/area/proc/set_fire_alarm_effect()
fire = 1
@@ -199,7 +253,6 @@
icon_state = "party"
else
icon_state = "blue-red"
- invisibility = INVISIBILITY_LIGHTING
else
var/weather_icon
for(var/V in SSweather.processing)
@@ -209,12 +262,9 @@
weather_icon = TRUE
if(!weather_icon)
icon_state = null
- invisibility = INVISIBILITY_MAXIMUM
/area/space/updateicon()
icon_state = null
- invisibility = INVISIBILITY_MAXIMUM
-
/*
#define EQUIP 1
@@ -317,9 +367,6 @@
M.lastarea = src
- // /vg/ - EVENTS!
- callHook("mob_area_change", list("mob" = M, "newarea" = newarea, "oldarea" = oldarea))
-
if(!istype(A,/mob/living)) return
var/mob/living/L = A
@@ -341,7 +388,7 @@
L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE)
L.client.played = 1
spawn(600) //ewww - this is very very bad
- if(L.&& L.client)
+ if(L && L.client)
L.client.played = 0
/area/proc/gravitychange(var/gravitystate = 0, var/area/A)
@@ -362,7 +409,7 @@
if(istype(get_turf(M), /turf/space)) // Can't fall onto nothing.
return
- if((istype(M,/mob/living/carbon/human/)) && (M.m_intent == MOVE_INTENT_RUN)).
+ if((istype(M,/mob/living/carbon/human/)) && (M.m_intent == MOVE_INTENT_RUN))
M.Stun(5)
M.Weaken(5)
diff --git a/code/game/area/depot-areas.dm b/code/game/area/areas/depot-areas.dm
similarity index 100%
rename from code/game/area/depot-areas.dm
rename to code/game/area/areas/depot-areas.dm
diff --git a/code/game/area/areas/mining.dm b/code/game/area/areas/mining.dm
new file mode 100644
index 00000000000..4a2317889fa
--- /dev/null
+++ b/code/game/area/areas/mining.dm
@@ -0,0 +1,130 @@
+/**********************Mine areas**************************/
+
+/area/mine
+ icon_state = "mining"
+ has_gravity = TRUE
+
+/area/mine/explored
+ name = "Mine"
+ icon_state = "explored"
+ music = null
+ always_unpowered = TRUE
+ requires_power = TRUE
+ poweralm = FALSE
+ power_environ = FALSE
+ power_equip = FALSE
+ power_light = FALSE
+ outdoors = TRUE
+ ambientsounds = list('sound/ambience/ambimine.ogg')
+ flags = NONE
+
+/area/mine/dangerous/explored/golem
+ name = "Small Asteroid"
+
+/area/mine/unexplored
+ name = "Mine"
+ icon_state = "unexplored"
+ music = null
+ always_unpowered = TRUE
+ requires_power = TRUE
+ poweralm = FALSE
+ power_environ = FALSE
+ power_equip = FALSE
+ power_light = FALSE
+ outdoors = TRUE
+ ambientsounds = list('sound/ambience/ambimine.ogg')
+ flags = NONE
+
+/area/mine/lobby
+ name = "Mining Station"
+
+/area/mine/storage
+ name = "Mining Station Storage"
+
+/area/mine/production
+ name = "Mining Station Starboard Wing"
+ icon_state = "mining_production"
+
+/area/mine/abandoned
+ name = "Abandoned Mining Station"
+
+/area/mine/living_quarters
+ name = "Mining Station Port Wing"
+ icon_state = "mining_living"
+
+/area/mine/eva
+ name = "Mining Station EVA"
+ icon_state = "mining_eva"
+
+/area/mine/maintenance
+ name = "Mining Station Communications"
+
+/area/mine/cafeteria
+ name = "Mining station Cafeteria"
+
+/area/mine/hydroponics
+ name = "Mining station Hydroponics"
+
+/area/mine/sleeper
+ name = "Mining station Emergency Sleeper"
+
+/area/mine/north_outpost
+ name = "North Mining Outpost"
+
+/area/mine/west_outpost
+ name = "West Mining Outpost"
+
+/area/mine/laborcamp
+ name = "Labor Camp"
+
+/area/mine/laborcamp/security
+ name = "Labor Camp Security"
+ icon_state = "security"
+
+/area/mine/podbay
+ name = "Mining Podbay"
+
+
+
+/**********************Lavaland Areas**************************/
+
+/area/lavaland
+ icon_state = "mining"
+ has_gravity = TRUE
+
+/area/lavaland/surface
+ name = "Lavaland"
+ icon_state = "explored"
+ music = null
+ always_unpowered = TRUE
+ poweralm = FALSE
+ power_environ = FALSE
+ power_equip = FALSE
+ power_light = FALSE
+ requires_power = TRUE
+ ambientsounds = list('sound/ambience/ambilava.ogg')
+
+/area/lavaland/underground
+ name = "Lavaland Caves"
+ icon_state = "unexplored"
+ music = null
+ always_unpowered = TRUE
+ requires_power = TRUE
+ poweralm = FALSE
+ power_environ = FALSE
+ power_equip = FALSE
+ power_light = FALSE
+ ambientsounds = list('sound/ambience/ambilava.ogg')
+
+/area/lavaland/surface/outdoors
+ name = "Lavaland Wastes"
+ outdoors = TRUE
+
+/area/lavaland/surface/outdoors/unexplored //monsters and ruins spawn here
+ icon_state = "unexplored"
+
+/area/lavaland/surface/outdoors/unexplored/danger //megafauna will also spawn here
+ icon_state = "danger"
+
+/area/lavaland/surface/outdoors/explored
+ name = "Lavaland Labor Camp"
\ No newline at end of file
diff --git a/code/game/area/areas/ruins/lavaland.dm b/code/game/area/areas/ruins/lavaland.dm
new file mode 100644
index 00000000000..d72c6cc0406
--- /dev/null
+++ b/code/game/area/areas/ruins/lavaland.dm
@@ -0,0 +1,87 @@
+//Lavaland Ruins
+
+/area/ruin/powered/beach
+ icon_state = "dk_yellow"
+
+/area/ruin/powered/clownplanet
+ icon_state = "dk_yellow"
+
+/area/ruin/powered/animal_hospital
+ icon_state = "dk_yellow"
+
+/area/ruin/powered/snow_biodome
+ icon_state = "dk_yellow"
+
+/area/ruin/powered/gluttony
+ icon_state = "dk_yellow"
+
+/area/ruin/powered/golem_ship
+ name = "Free Golem Landing"
+ icon_state = "dk_yellow"
+
+/area/ruin/powered/greed
+ icon_state = "dk_yellow"
+
+/area/ruin/unpowered/hierophant
+ name = "Hierophant's Arena"
+ icon_state = "dk_yellow"
+
+/area/ruin/powered/pride
+ icon_state = "dk_yellow"
+
+/area/ruin/powered/seedvault
+ icon_state = "dk_yellow"
+
+/area/ruin/unpowered/syndicate_lava_base
+ name = "Secret Base"
+ icon_state = "dk_yellow"
+ ambientsounds = list('sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg')
+ report_alerts = FALSE
+ hide_attacklogs = TRUE
+
+/area/ruin/unpowered/syndicate_lava_base/engineering
+ name = "Syndicate Lavaland Engineering"
+
+/area/ruin/unpowered/syndicate_lava_base/medbay
+ name = "Syndicate Lavaland Medbay"
+
+/area/ruin/unpowered/syndicate_lava_base/arrivals
+ name = "Syndicate Lavaland Arrivals"
+
+/area/ruin/unpowered/syndicate_lava_base/bar
+ name = "Syndicate Lavaland Bar"
+
+/area/ruin/unpowered/syndicate_lava_base/main
+ name = "Syndicate Lavaland Primary Hallway"
+
+/area/ruin/unpowered/syndicate_lava_base/cargo
+ name = "Syndicate Lavaland Cargo Bay"
+
+/area/ruin/unpowered/syndicate_lava_base/chemistry
+ name = "Syndicate Lavaland Chemistry"
+
+/area/ruin/unpowered/syndicate_lava_base/virology
+ name = "Syndicate Lavaland Virology"
+
+/area/ruin/unpowered/syndicate_lava_base/testlab
+ name = "Syndicate Lavaland Experimentation Lab"
+
+/area/ruin/unpowered/syndicate_lava_base/dormitories
+ name = "Syndicate Lavaland Dormitories"
+
+/area/ruin/unpowered/syndicate_lava_base/telecomms
+ name = "Syndicate Lavaland Telecommunications"
+
+//Xeno Nest
+
+/area/ruin/unpowered/xenonest
+ name = "The Hive"
+ always_unpowered = TRUE
+ power_environ = FALSE
+ power_equip = FALSE
+ power_light = FALSE
+ poweralm = FALSE
+
+//ash walker nest
+/area/ruin/unpowered/ash_walkers
+ icon_state = "red"
\ No newline at end of file
diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm
index c6edd09575e..e35a7b5bd51 100644
--- a/code/game/asteroid.dm
+++ b/code/game/asteroid.dm
@@ -30,7 +30,9 @@ var/global/max_secret_rooms = 6
T.ChangeTurf(floor)
room_turfs["floors"] += T
+ var/old_area = T.loc
A.contents += T
+ T.change_area(old_area, A)
return room_turfs
@@ -87,7 +89,7 @@ var/global/max_secret_rooms = 6
if("cavein")
theme = "cavein"
walltypes = list(/turf/simulated/mineral/random/high_chance=1)
- floortypes = list(/turf/simulated/floor/plating/airless/asteroid, /turf/simulated/floor/beach/sand)
+ floortypes = list(/turf/simulated/floor/plating/asteroid/airless, /turf/simulated/floor/beach/sand)
treasureitems = list(/obj/mecha/working/ripley/mining=1, /obj/item/pickaxe/drill/diamonddrill=2,
/obj/item/resonator/upgraded=1, /obj/item/pickaxe/drill/jackhammer=5)
fluffitems = list(/obj/effect/decal/cleanable/blood=3,/obj/effect/decal/remains/human=1,/obj/item/clothing/under/overalls=1,
@@ -96,7 +98,7 @@ var/global/max_secret_rooms = 6
if("xenoden")
theme = "xenoden"
walltypes = list(/turf/simulated/mineral/random/high_chance=1)
- floortypes = list(/turf/simulated/floor/plating/airless/asteroid, /turf/simulated/floor/beach/sand)
+ floortypes = list(/turf/simulated/floor/plating/asteroid/airless, /turf/simulated/floor/beach/sand)
treasureitems = list(/obj/item/clothing/mask/facehugger=1,/obj/item/stack/sheet/animalhide/xeno=2,/obj/item/clothing/suit/xenos=2,/obj/item/clothing/head/xenos=2,/obj/item/guardiancreator/biological/choose=1)
fluffitems = list(/obj/effect/decal/remains/human=1,/obj/effect/decal/cleanable/blood/xeno=5)
@@ -104,7 +106,7 @@ var/global/max_secret_rooms = 6
theme = "hitech"
walltypes = list(/turf/simulated/wall/r_wall=5,/turf/simulated/mineral/random=1)
floortypes = list(/turf/simulated/floor/greengrid,/turf/simulated/floor/bluegrid)
- treasureitems = list(/obj/item/stock_parts/cell/hyper=1, /obj/machinery/chem_dispenser/constructable=1,/obj/machinery/computer/telescience=1, /obj/machinery/r_n_d/protolathe=1,
+ treasureitems = list(/obj/item/stock_parts/cell/hyper=1, /obj/item/circuitboard/chem_dispenser=1,/obj/machinery/computer/telescience=1, /obj/machinery/r_n_d/protolathe=1,
/obj/machinery/biogenerator=1)
fluffitems = list(/obj/structure/table/reinforced=2,/obj/item/stock_parts/scanning_module/phasic=3,
/obj/item/stock_parts/matter_bin/super=3,/obj/item/stock_parts/manipulator/pico=3,
@@ -139,7 +141,7 @@ var/global/max_secret_rooms = 6
possiblethemes -= theme //once a theme is selected, it's out of the running!
var/floor = pick(floortypes)
- turfs = get_area_turfs(/area/mine/dangerous/unexplored)
+ turfs = get_area_turfs(/area/mine/unexplored)
if(!turfs.len)
return 0
@@ -177,7 +179,7 @@ var/global/max_secret_rooms = 6
valid = 0
continue
- if(locate(/turf/simulated/floor/plating/airless/asteroid) in range(5,T))//A little less strict than the other checks due to tunnels
+ if(locate(/turf/simulated/floor/plating/asteroid/airless) in range(5,T))//A little less strict than the other checks due to tunnels
valid = 0
continue
@@ -188,10 +190,6 @@ var/global/max_secret_rooms = 6
if(room)//time to fill it with stuff
var/list/emptyturfs = room["floors"]
- for(var/turf/simulated/floor/A in emptyturfs) //remove pls doesn't fix problem
- if(istype(A))
- spawn(2)
- A.fullUpdateMineralOverlays()
T = pick(emptyturfs)
if(T)
new /obj/structure/glowshroom/single(T) //Just to make it a little more visible
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 91132a5f9bd..757f036c691 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -1,5 +1,6 @@
/atom
- layer = 2
+ layer = TURF_LAYER
+ plane = GAME_PLANE
var/level = 2
var/flags = NONE
var/flags_2 = NONE
@@ -11,7 +12,7 @@
var/last_bumped = 0
var/pass_flags = 0
var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom.
- var/simulated = 1 //filter for actions - used by lighting overlays
+ var/simulated = TRUE //filter for actions - used by lighting overlays
var/atom_say_verb = "says"
var/dont_save = 0 // For atoms that are temporary by necessity - like lighting overlays
@@ -47,6 +48,9 @@
var/list/remove_overlays // a very temporary list of overlays to remove
var/list/add_overlays // a very temporary list of overlays to add
+ var/list/atom_colours //used to store the different colors on an atom
+ //its inherent color, the colored paint applied on it, special color effect etc...
+
/atom/New(loc, ...)
if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
_preloader.load(src)
@@ -80,6 +84,9 @@
stack_trace("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
+ if(color)
+ add_atom_colour(color, FIXED_COLOUR_PRIORITY)
+
if(light_power && light_range)
update_light()
@@ -144,9 +151,12 @@
alternate_appearances = null
QDEL_NULL(reagents)
- invisibility = 101
+ invisibility = INVISIBILITY_MAXIMUM
LAZYCLEARLIST(overlays)
LAZYCLEARLIST(priority_overlays)
+
+ QDEL_NULL(light)
+
return ..()
//Hook for running code when a dir change occurs
@@ -333,6 +343,9 @@
if(AM && isturf(AM.loc))
step(AM, turn(AM.dir, 180))
+/atom/proc/get_spooked()
+ return
+
/atom/proc/add_hiddenprint(mob/living/M as mob)
if(isnull(M)) return
if(isnull(M.key)) return
@@ -348,7 +361,7 @@
fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key)
fingerprintslast = H.ckey
return 0
- if(!( fingerprints ))
+ if(!fingerprints)
if(fingerprintslast != H.ckey)
//Add the list if it does not exist.
if(!fingerprintshidden)
@@ -642,15 +655,22 @@ var/list/blood_splatter_icons = list()
update_icons() //apply the now updated overlays to the mob
-/atom/proc/add_vomit_floor(mob/living/carbon/M as mob, var/toxvomit = 0)
- if( istype(src, /turf/simulated) )
- var/obj/effect/decal/cleanable/vomit/this = new /obj/effect/decal/cleanable/vomit(src)
+/atom/proc/add_vomit_floor(toxvomit = 0, green = FALSE)
+ playsound(src, 'sound/effects/splat.ogg', 50, 1)
+ if(!isspaceturf(src))
+ var/type = green ? /obj/effect/decal/cleanable/vomit/green : /obj/effect/decal/cleanable/vomit
+ var/vomit_reagent = green ? "green_vomit" : "vomit"
+ for(var/obj/effect/decal/cleanable/vomit/V in get_turf(src))
+ if(V.type == type)
+ V.reagents.add_reagent(vomit_reagent, 5)
+ return
+
+ var/obj/effect/decal/cleanable/vomit/this = new type(src)
// Make toxins vomit look different
if(toxvomit)
this.icon_state = "vomittox_[pick(1,4)]"
-
/atom/proc/get_global_map_pos()
if(!islist(global_map) || isemptylist(global_map)) return
var/cur_x = null
@@ -674,16 +694,17 @@ var/list/blood_splatter_icons = list()
//the sight changes to give to the mob whose perspective is set to that atom (e.g. A mob with nightvision loses its nightvision while looking through a normal camera)
/atom/proc/update_remote_sight(mob/living/user)
+ user.sync_lighting_plane_alpha()
return
/atom/proc/checkpass(passflag)
return pass_flags&passflag
/atom/proc/isinspace()
- if(istype(get_turf(src), /turf/space))
- return 1
+ if(isspaceturf(get_turf(src)))
+ return TRUE
else
- return 0
+ return FALSE
/atom/proc/handle_fall()
return
@@ -722,6 +743,8 @@ var/list/blood_splatter_icons = list()
switch(var_name)
if("light_power", "light_range", "light_color")
update_light()
+ if("color")
+ add_atom_colour(color, ADMIN_COLOUR_PRIORITY)
/atom/vv_get_dropdown()
@@ -752,3 +775,52 @@ var/list/blood_splatter_icons = list()
/atom/Exited(atom/movable/AM, atom/newLoc)
SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, newLoc)
+
+/*
+ Adds an instance of colour_type to the atom's atom_colours list
+*/
+/atom/proc/add_atom_colour(coloration, colour_priority)
+ if(!atom_colours || !atom_colours.len)
+ atom_colours = list()
+ atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently.
+ if(!coloration)
+ return
+ if(colour_priority > atom_colours.len)
+ return
+ atom_colours[colour_priority] = coloration
+ update_atom_colour()
+
+
+/*
+ Removes an instance of colour_type from the atom's atom_colours list
+*/
+/atom/proc/remove_atom_colour(colour_priority, coloration)
+ if(!atom_colours)
+ atom_colours = list()
+ atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently.
+ if(colour_priority > atom_colours.len)
+ return
+ if(coloration && atom_colours[colour_priority] != coloration)
+ return //if we don't have the expected color (for a specific priority) to remove, do nothing
+ atom_colours[colour_priority] = null
+ update_atom_colour()
+
+
+/*
+ Resets the atom's color to null, and then sets it to the highest priority
+ colour available
+*/
+/atom/proc/update_atom_colour()
+ if(!atom_colours)
+ atom_colours = list()
+ atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently.
+ color = null
+ for(var/C in atom_colours)
+ if(islist(C))
+ var/list/L = C
+ if(L.len)
+ color = L
+ return
+ else if(C)
+ color = C
+ return
\ No newline at end of file
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 2d3f01a139d..1a23dc71070 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -58,13 +58,17 @@
pulledby = null
return ..()
+//Returns an atom's power cell, if it has one. Overload for individual items.
+/atom/movable/proc/get_cell()
+ return
+
/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
if(QDELETED(AM))
return FALSE
if(!(AM.can_be_pulled(src, state, force)))
return FALSE
- // If we're pulling something then drop what we're currently pulling and pull this instead.
+ // if we're pulling something then drop what we're currently pulling and pull this instead.
if(pulling)
if(state == 0)
stop_pulling()
@@ -114,7 +118,9 @@
if(pulling.anchored)
stop_pulling()
return
-
+ if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move.
+ pulledby.stop_pulling()
+
/atom/movable/proc/can_be_pulled(user, grab_state, force)
if(src == user || !isturf(loc))
return FALSE
@@ -137,36 +143,55 @@
. = ..()
else //Diagonal move, split it into cardinal moves
moving_diagonally = FIRST_DIAG_STEP
- if(direct & 1)
- if(direct & 4)
- if(step(src, NORTH))
+ var/first_step_dir
+ // The `&& moving_diagonally` checks are so that a forceMove taking
+ // place due to a Crossed, Bumped, etc. call will interrupt
+ // the second half of the diagonal movement, or the second attempt
+ // at a first half if step() fails because we hit something.
+ if(direct & NORTH)
+ if(direct & EAST)
+ if(step(src, NORTH) && moving_diagonally)
+ first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
- else if(step(src, EAST))
+ else if(moving_diagonally && step(src, EAST))
+ first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
- else if(direct & 8)
- if(step(src, NORTH))
+ else if(direct & WEST)
+ if(step(src, NORTH) && moving_diagonally)
+ first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
- else if(step(src, WEST))
+ else if(moving_diagonally && step(src, WEST))
+ first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
- else if(direct & 2)
- if(direct & 4)
- if(step(src, SOUTH))
+ else if(direct & SOUTH)
+ if(direct & EAST)
+ if(step(src, SOUTH) && moving_diagonally)
+ first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
- else if(step(src, EAST))
+ else if(moving_diagonally && step(src, EAST))
+ first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
- else if(direct & 8)
- if(step(src, SOUTH))
+ else if(direct & WEST)
+ if(step(src, SOUTH) && moving_diagonally)
+ first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
- else if(step(src, WEST))
+ else if(moving_diagonally && step(src, WEST))
+ first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
+ if(moving_diagonally == SECOND_DIAG_STEP)
+ if(!.)
+ setDir(first_step_dir)
+ else if(!inertia_moving)
+ inertia_next_move = world.time + inertia_move_delay
+ newtonian_move(direct)
moving_diagonally = 0
return
@@ -185,15 +210,16 @@
. = 0
// Called after a successful Move(). By this point, we've already moved
-/atom/movable/proc/Moved(atom/OldLoc, Dir)
+/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced)
if(!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(Dir)
- return 1
+ return TRUE
// Previously known as HasEntered()
// This is automatically called when something enters your square
-/atom/movable/Crossed(atom/movable/AM)
+/atom/movable/Crossed(atom/movable/AM, oldloc)
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
/atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump().
@@ -209,6 +235,7 @@
/atom/movable/proc/forceMove(atom/destination)
var/turf/old_loc = loc
loc = destination
+ moving_diagonally = 0
if(old_loc)
old_loc.Exited(src, destination)
@@ -218,8 +245,15 @@
if(destination)
destination.Entered(src)
for(var/atom/movable/AM in destination)
- AM.Crossed(src)
-
+ if(AM == src)
+ continue
+ AM.Crossed(src, old_loc)
+ var/turf/oldturf = get_turf(old_loc)
+ var/turf/destturf = get_turf(destination)
+ var/old_z = (oldturf ? oldturf.z : null)
+ var/dest_z = (destturf ? destturf.z : null)
+ if(old_z != dest_z)
+ onTransitZ(old_z, dest_z)
if(isturf(destination) && opacity)
var/turf/new_loc = destination
new_loc.reconsider_lights()
@@ -232,6 +266,11 @@
return 1
+/atom/movable/proc/onTransitZ(old_z,new_z)
+ for(var/item in src) // Notify contents of Z-transition. This can be overridden if we know the items contents do not care.
+ var/atom/movable/AM = item
+ AM.onTransitZ(old_z,new_z)
+
/mob/living/forceMove(atom/destination)
if(buckled)
addtimer(CALLBACK(src, .proc/check_buckled), 1, TIMER_UNIQUE)
@@ -364,30 +403,28 @@
SSthrowing.processing[src] = TT
TT.tick()
+ return TRUE
//Overlays
/atom/movable/overlay
var/atom/master = null
- anchored = 1
+ anchored = TRUE
+ simulated = FALSE
/atom/movable/overlay/New()
verbs.Cut()
return
/atom/movable/overlay/attackby(a, b, c)
- if(src.master)
- return src.master.attackby(a, b, c)
- return
-
+ if(master)
+ return master.attackby(a, b, c)
/atom/movable/overlay/attack_hand(a, b, c)
- if(src.master)
- return src.master.attack_hand(a, b, c)
- return
+ if(master)
+ return master.attack_hand(a, b, c)
-
-/atom/movable/proc/water_act(var/volume, var/temperature, var/source) //amount of water acting : temperature of water in kelvin : object that called it (for shennagins)
- return 1
+/atom/movable/proc/water_act(volume, temperature, source, method = TOUCH) //amount of water acting : temperature of water in kelvin : object that called it (for shennagins)
+ return TRUE
/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
if(!buckled_mob.Move(newloc, direct))
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 178605853e8..1370b64ecc7 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -78,10 +78,11 @@
return 1
return 0
-//helper for getting the appropriate health status UPDATED BY PUCKABOO2 TO INCLUDE NEGATIVES.
+//helper for getting the appropriate health status
/proc/RoundHealth(mob/living/M)
if(M.stat == DEAD || (M.status_flags & FAKEDEATH))
- return "health-100" //what's our health? it doesn't matter, we're dead, or faking
+ return "health-100-dead" //what's our health? it doesn't matter, we're dead, or faking
+
var/maxi_health = M.maxHealth
if(iscarbon(M) && M.health < 0)
maxi_health = 100 //so crit shows up right for aliens and other high-health carbon mobs; noncarbons don't have crit.
@@ -91,7 +92,7 @@
if(100 to INFINITY)
return "health100"
if(95 to 100)
- return "health95" //For telling patients to eat a warm donk pocket and go on with their shift.
+ return "health95"
if(90 to 95)
return "health90"
if(80 to 90)
@@ -127,13 +128,13 @@
if(-70 to -60)
return "health-60"
if(-80 to -70)
- return "health-70" //Doc?
+ return "health-70"
if(-90 to -80)
- return "health-80" //Hey, doc?
+ return "health-80"
if(-100 to -90)
- return "health-90" //HURRY UP, DOC!
+ return "health-90"
else
- return "health-100" //doc u had 1 job
+ return "health-100" //past this point, you're just in trouble
return "0"
@@ -217,7 +218,7 @@
/mob/living/carbon/human/proc/sec_hud_set_security_status()
var/image/holder = hud_list[WANTED_HUD]
var/perpname = get_visible_name(TRUE) //gets the name of the perp, works if they have an id or if their face is uncovered
- if(!ticker) return //wait till the game starts or the monkeys runtime....
+ if(!SSticker) return //wait till the game starts or the monkeys runtime....
if(perpname)
var/datum/data/record/R = find_record("name", perpname, data_core.security)
if(R)
@@ -438,4 +439,4 @@
if(weedlevel < 1) // You don't want to see these icons if the value is small
holder.icon_state = ""
return
- holder.icon_state = "hudweed[RoundPlantBar(weedlevel/10)]"
+ holder.icon_state = "hudweed[RoundPlantBar(weedlevel/10)]"
\ No newline at end of file
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index 061d8ef91e7..c0d977d0ee9 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -437,4 +437,18 @@ var/global/list/bad_blocks[0]
var/datum/species/S = data["species"]
species = new S
b_type = data["b_type"]
- real_name = data["real_name"]
\ No newline at end of file
+ real_name = data["real_name"]
+
+/datum/dna/proc/transfer_identity(mob/living/carbon/human/destination)
+ if(!istype(destination))
+ return
+
+ // We manually set the species to ensure all proper species change procs are called.
+ destination.set_species(species.type, retain_damage = TRUE)
+ var/datum/dna/new_dna = Clone()
+ new_dna.species = destination.dna.species
+ destination.dna = new_dna
+ destination.dna.species.handle_dna(destination) // Handle DNA has to be re-called as the DNA was changed.
+
+ destination.UpdateAppearance()
+ domutcheck(destination, null, MUTCHK_FORCED)
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index 708d8467fb0..e4b1f1e8a49 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -537,7 +537,7 @@
occupantData["isViableSubject"] = 0
occupantData["health"] = connected.occupant.health
occupantData["maxHealth"] = connected.occupant.maxHealth
- occupantData["minHealth"] = config.health_threshold_dead
+ occupantData["minHealth"] = HEALTH_THRESHOLD_DEAD
occupantData["uniqueEnzymes"] = connected.occupant.dna.unique_enzymes
occupantData["uniqueIdentity"] = connected.occupant.dna.uni_identity
occupantData["structuralEnzymes"] = connected.occupant.dna.struc_enzymes
diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm
index 9ab851e86bf..506ef5714f8 100644
--- a/code/game/dna/genes/vg_powers.dm
+++ b/code/game/dna/genes/vg_powers.dm
@@ -188,9 +188,19 @@
..()
block=REMOTETALKBLOCK
+/datum/dna/gene/basic/grant_spell/remotetalk/activate(mob/user)
+ ..()
+ user.AddSpell(new /obj/effect/proc_holder/spell/targeted/mindscan(null))
+
+/datum/dna/gene/basic/grant_spell/remotetalk/deactivate(mob/user)
+ ..()
+ for(var/obj/effect/proc_holder/spell/S in user.mob_spell_list)
+ if(istype(S, /obj/effect/proc_holder/spell/targeted/mindscan))
+ user.RemoveSpell(S)
+
/obj/effect/proc_holder/spell/targeted/remotetalk
name = "Project Mind"
- desc = "Make people understand your thoughts at any range!"
+ desc = "Make people understand your thoughts!"
charge_max = 0
clothes_req = 0
@@ -242,6 +252,89 @@
for(var/mob/dead/observer/G in GLOB.player_list)
G.show_message("Telepathic message from [user] ([ghost_follow_link(user, ghost=G)]) to [target] ([ghost_follow_link(target, ghost=G)]): [say]")
+/obj/effect/proc_holder/spell/targeted/mindscan
+ name = "Scan Mind"
+ desc = "Offer people a chance to share their thoughts!"
+ charge_max = 0
+ clothes_req = 0
+ stat_allowed = 0
+ invocation_type = "none"
+ range = -2
+ selection_type = "range"
+ action_icon_state = "genetic_mindscan"
+ var/list/available_targets = list()
+
+/obj/effect/proc_holder/spell/targeted/mindscan/choose_targets(mob/user = usr)
+ var/list/targets = new /list()
+ var/list/validtargets = new /list()
+ var/turf/T = get_turf(user)
+ for(var/mob/living/M in range(14, T))
+ if(M && M.mind)
+ if(M == user)
+ continue
+ validtargets += M
+
+ if(!validtargets.len)
+ to_chat(user, "There are no valid targets!")
+ start_recharge()
+ return
+
+ targets += input("Choose the target to listen to.", "Targeting") as null|mob in validtargets
+
+ if(!targets.len || !targets[1]) //doesn't waste the spell
+ revert_cast(user)
+ return
+
+ perform(targets, user = user)
+
+/obj/effect/proc_holder/spell/targeted/mindscan/cast(list/targets, mob/user = usr)
+ if(!ishuman(user))
+ return
+ for(var/mob/living/target in targets)
+ var/message = "You feel your mind expand briefly... (Click to send a message.)"
+ if(REMOTE_TALK in target.mutations)
+ message = "You feel [user.real_name] request a response from you... (Click here to project mind.)"
+ user.show_message("You offer your mind to [target.name].")
+ target.show_message("[message]")
+ available_targets += target
+ addtimer(CALLBACK(src, .proc/removeAvailability, target), 100)
+
+/obj/effect/proc_holder/spell/targeted/mindscan/proc/removeAvailability(mob/living/target)
+ if(target in available_targets)
+ available_targets -= target
+ if(!(target in available_targets))
+ target.show_message("You feel the sensation fade...")
+
+/obj/effect/proc_holder/spell/targeted/mindscan/Topic(href, href_list)
+ var/mob/living/user
+ if(href_list["user"])
+ user = locateUID(href_list["user"])
+ if(href_list["target"])
+ if(!user)
+ return
+ var/mob/living/target = locateUID(href_list["target"])
+ if(!(target in available_targets))
+ return
+ available_targets -= target
+ var/say = input("What do you wish to say") as text|null
+ if(!say)
+ return
+ say = strip_html(say)
+ say = pencode_to_html(say, target, format = 0, fields = 0)
+
+ log_say("(TPATH to [key_name(target)]) [say]", user)
+ if(REMOTE_TALK in target.mutations)
+ target.show_message("You project your mind into [user.name]: [say]")
+ else
+ target.show_message("You fill the space in your thoughts: [say]")
+ user.show_message("You hear [target.name]'s voice: [say]")
+ for(var/mob/dead/observer/G in GLOB.player_list)
+ G.show_message("Telepathic response from [target] ([ghost_follow_link(target, ghost=G)]) to [user] ([ghost_follow_link(user, ghost=G)]): [say]")
+
+/obj/effect/proc_holder/spell/targeted/mindscan/Destroy()
+ available_targets.Cut()
+ return ..()
+
/datum/dna/gene/basic/grant_spell/remoteview
name="Remote Viewing"
activation_messages=list("Your mind can see things from afar.")
diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm
index bf9fbb5a9e5..2137888d0b8 100644
--- a/code/game/gamemodes/autotraitor/autotraitor.dm
+++ b/code/game/gamemodes/autotraitor/autotraitor.dm
@@ -96,7 +96,8 @@
for(var/obj/item/implant/mindshield/I in H.contents)
if(I && I.implanted)
possible_traitors -= player
-
+ if(!H.job || H.mind.offstation_role) //Golems, special events stuff, etc.
+ possible_traitors -= player
//message_admins("Live Players: [playercount]")
//message_admins("Live Traitors: [traitorcount]")
// message_admins("Potential Traitors:")
@@ -130,8 +131,10 @@
forge_traitor_objectives(newtraitor.mind)
if(istype(newtraitor, /mob/living/silicon))
+ SEND_SOUND(newtraitor, 'sound/ambience/antag/malf.ogg')
add_law_zero(newtraitor)
else
+ SEND_SOUND(newtraitor, 'sound/ambience/antag/tatoralert.ogg')
equip_traitor(newtraitor)
traitors += newtraitor.mind
diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm
index 41068876a54..df61106c4ab 100644
--- a/code/game/gamemodes/blob/blob.dm
+++ b/code/game/gamemodes/blob/blob.dm
@@ -3,6 +3,8 @@ var/list/blobs = list()
var/list/blob_cores = list()
var/list/blob_nodes = list()
+/datum/game_mode
+ var/list/blob_overminds = list()
/datum/game_mode/blob
name = "blob"
@@ -12,7 +14,6 @@ var/list/blob_nodes = list()
required_enemies = 1
recommended_enemies = 1
restricted_jobs = list("Cyborg", "AI")
- free_golems_disabled = TRUE
var/declared = 0
var/burst = 0
@@ -41,9 +42,11 @@ var/list/blob_nodes = list()
for(var/j = 0, j < cores_to_spawn, j++)
if(!possible_blobs.len)
break
+
var/datum/mind/blob = pick(possible_blobs)
infected_crew += blob
blob.special_role = SPECIAL_ROLE_BLOB
+ update_blob_icons_added(blob)
blob.restricted_roles = restricted_jobs
log_game("[key_name(blob)] has been selected as a Blob")
possible_blobs -= blob
@@ -65,8 +68,11 @@ var/list/blob_nodes = list()
var/datum/mind/blobmind = blob.mind
if(!istype(blobmind))
return 0
+
infected_crew += blobmind
blobmind.special_role = SPECIAL_ROLE_BLOB
+ update_blob_icons_added(blobmind)
+
log_game("[key_name(blob)] has been selected as a Blob")
greet_blob(blobmind)
to_chat(blob, "You feel very tired and bloated! You don't have long before you burst!")
@@ -184,16 +190,21 @@ var/list/blob_nodes = list()
return ..()
/datum/game_mode/blob/proc/stage(var/stage)
-
switch(stage)
if(0)
send_intercept(1)
declared = 1
-
if(1)
event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
-
if(2)
send_intercept(2)
- return
+/datum/game_mode/proc/update_blob_icons_added(datum/mind/mob_mind)
+ var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_BLOB]
+ antaghud.join_hud(mob_mind.current)
+ set_antag_hud(mob_mind.current, "hudblob")
+
+/datum/game_mode/proc/update_blob_icons_removed(datum/mind/mob_mind)
+ var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_BLOB]
+ antaghud.leave_hud(mob_mind.current)
+ set_antag_hud(mob_mind.current, null)
\ No newline at end of file
diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm
index 3d65a41eeb8..53a98de7028 100644
--- a/code/game/gamemodes/blob/blob_report.dm
+++ b/code/game/gamemodes/blob/blob_report.dm
@@ -64,13 +64,15 @@
src.floor += 1
if(istype(T, /turf/simulated/wall))
- if(T:intact)
+ var/turf/simulated/wall/W = T
+ if(W.intact)
src.wall += 2
else
src.wall += 1
if(istype(T, /turf/simulated/wall/r_wall))
- if(T:intact)
+ var/turf/simulated/wall/r_wall/R = T
+ if(R.intact)
src.r_wall += 2
else
src.r_wall += 1
diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm
index a96b3e18620..bf2143b9784 100644
--- a/code/game/gamemodes/blob/blobs/blob_mobs.dm
+++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm
@@ -12,6 +12,8 @@
minbodytemp = 0
maxbodytemp = 360
universal_speak = 1 //So mobs can understand them when a blob uses Blob Broadcast
+ sentience_type = SENTIENCE_OTHER
+ gold_core_spawnable = CHEM_MOB_SPAWN_INVALID
var/mob/camera/blob/overmind = null
/mob/living/simple_animal/hostile/blob/proc/adjustcolors(var/a_color)
@@ -21,6 +23,7 @@
/mob/living/simple_animal/hostile/blob/blob_act()
return
+
////////////////
// BLOB SPORE //
////////////////
@@ -42,7 +45,6 @@
var/obj/structure/blob/factory/factory = null
var/list/human_overlays = list()
var/is_zombie = 0
- gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
pressure_resistance = 100 //100 kPa difference required to push
throw_pressure_limit = 120 //120 kPa difference required to throw
@@ -65,15 +67,17 @@
/mob/living/simple_animal/hostile/blob/blobspore/Life(seconds, times_fired)
if(!is_zombie && isturf(src.loc))
- for(var/mob/living/carbon/human/H in oview(src,1)) //Only for corpse right next to/on same tile
- if(H.stat == DEAD)
+ for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile
+ if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
Zombify(H)
break
..()
-/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(var/mob/living/carbon/human/H)
+/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(mob/living/carbon/human/H)
+ if(!H.check_death_method())
+ H.death()
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
- is_zombie = 1
+ is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
if(A.armor && A.armor["melee"])
@@ -87,14 +91,15 @@
icon = H.icon
speak_emote = list("groans")
icon_state = "zombie2_s"
- head_organ.h_style = null
+ if(head_organ)
+ head_organ.h_style = null
H.update_hair()
human_overlays = H.overlays
update_icons()
- H.loc = src
+ H.forceMove(src)
pressure_resistance = 20 //5 kPa difference required to push lowered
throw_pressure_limit = 30 //15 kPa difference required to throw lowered
- loc.visible_message("The corpse of [H.name] suddenly rises!")
+ visible_message("The corpse of [H.name] suddenly rises!")
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
// Only execute the below if we successfuly died
@@ -132,9 +137,9 @@
..()
if(overmind && overmind.blob_reagent_datum)
- adjustcolors(overmind.blob_reagent_datum.color)
+ adjustcolors(overmind.blob_reagent_datum.complementary_color)
else
- adjustcolors(color) //to ensure zombie/other overlays update
+ adjustcolors(overmind.blob_reagent_datum.complementary_color) //to ensure zombie/other overlays update
/mob/living/simple_animal/hostile/blob/blobspore/adjustcolors(var/a_color)
@@ -144,8 +149,8 @@
overlays.Cut()
overlays = human_overlays
var/image/I = image('icons/mob/blob.dmi', icon_state = "blob_head")
- I.color = color
- color = initial(color)//looks better.
+ I.color = overmind.blob_reagent_datum.complementary_color
+ color = initial(overmind.blob_reagent_datum.complementary_color)//looks better.
overlays += I
/////////////////
@@ -171,10 +176,10 @@
force_threshold = 10
mob_size = MOB_SIZE_LARGE
environment_smash = ENVIRONMENT_SMASH_RWALLS
- gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
pressure_resistance = 100 //100 kPa difference required to push
throw_pressure_limit = 120 //120 kPa difference required to throw
-
+ see_in_dark = 8
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
/mob/living/simple_animal/hostile/blob/blobbernaut/blob_act()
return
diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm
index 4bdc2cafddd..91c6df639e5 100644
--- a/code/game/gamemodes/blob/blobs/core.dm
+++ b/code/game/gamemodes/blob/blobs/core.dm
@@ -4,6 +4,7 @@
icon_state = "blank_blob"
health = 200
fire_resist = 2
+ point_return = -1
var/mob/camera/blob/overmind = null // the blob core's overmind
var/overmind_get_delay = 0 // we don't want to constantly try to find an overmind, do it every 5 minutes
var/resource_delay = 0
@@ -13,7 +14,7 @@
/obj/structure/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, offspring)
blob_cores += src
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
GLOB.poi_list |= src
adjustcolors(color) //so it atleast appears
if(!overmind)
@@ -41,7 +42,7 @@
if(overmind)
overmind.blob_core = null
overmind = null
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
GLOB.poi_list.Remove(src)
return ..()
@@ -81,7 +82,7 @@
continue
var/obj/structure/blob/normal/B = locate() in get_step(src, b_dir)
if(B)
- B.change_to(/obj/structure/blob/shield)
+ B.change_to(/obj/structure/blob/shield/core)
if(B && overmind)
B.color = overmind.blob_reagent_datum.color
else
@@ -104,7 +105,11 @@
spawn()
if(!new_overmind)
- candidates = pollCandidates("Do you want to play as a blob?", ROLE_BLOB, 1)
+ if(is_offspring)
+ candidates = pollCandidates("Do you want to play as a blob offspring?", ROLE_BLOB, 1)
+ else
+ candidates = pollCandidates("Do you want to play as a blob?", ROLE_BLOB, 1)
+
if(candidates.len)
C = pick(candidates)
else
@@ -117,10 +122,10 @@
src.overmind = B
color = overmind.blob_reagent_datum.color
if(B.mind && !B.mind.special_role)
- B.mind.special_role = SPECIAL_ROLE_BLOB_OVERMIND
+ B.mind.make_Overmind()
spawn(0)
if(is_offspring)
- B.verbs -= /mob/camera/blob/verb/split_consciousness
+ B.is_offspring = TRUE
/obj/structure/blob/core/proc/lateblobtimer()
addtimer(CALLBACK(src, .proc/lateblobcheck), 50)
@@ -129,8 +134,13 @@
if(overmind)
overmind.add_points(60)
if(overmind.mind)
- overmind.mind.special_role = SPECIAL_ROLE_BLOB_OVERMIND
+ overmind.mind.make_Overmind()
else
log_debug("/obj/structure/blob/core/proc/lateblobcheck: Blob core lacks a overmind.mind.")
else
- log_debug("/obj/structure/blob/core/proc/lateblobcheck: Blob core lacks an overmind.")
\ No newline at end of file
+ log_debug("/obj/structure/blob/core/proc/lateblobcheck: Blob core lacks an overmind.")
+
+/obj/structure/blob/core/onTransitZ(old_z, new_z)
+ if(overmind && is_station_level(new_z))
+ overmind.forceMove(get_turf(src))
+ return ..()
\ No newline at end of file
diff --git a/code/game/gamemodes/blob/blobs/factory.dm b/code/game/gamemodes/blob/blobs/factory.dm
index 81d3ab47493..fd6aa8c9f4a 100644
--- a/code/game/gamemodes/blob/blobs/factory.dm
+++ b/code/game/gamemodes/blob/blobs/factory.dm
@@ -4,6 +4,7 @@
icon_state = "blob_factory"
health = 100
fire_resist = 2
+ point_return = 18
var/list/spores = list()
var/max_spores = 3
var/spore_delay = 0
@@ -22,13 +23,12 @@
/obj/structure/blob/factory/run_action()
if(spores.len >= max_spores)
- return 0
+ return
if(spore_delay > world.time)
- return 0
+ return
+ flick("blob_factory_glow", src)
spore_delay = world.time + 100 // 10 seconds
var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore(src.loc, src)
- BS.color = color
+ BS.color = overmind.blob_reagent_datum.complementary_color
BS.overmind = overmind
overmind.blob_mobs.Add(BS)
- return 0
-
diff --git a/code/game/gamemodes/blob/blobs/node.dm b/code/game/gamemodes/blob/blobs/node.dm
index 32b6ce1f408..4a2699802c1 100644
--- a/code/game/gamemodes/blob/blobs/node.dm
+++ b/code/game/gamemodes/blob/blobs/node.dm
@@ -4,11 +4,12 @@
icon_state = "blank_blob"
health = 100
fire_resist = 2
+ point_return = 18
var/mob/camera/blob/overmind
/obj/structure/blob/node/New(loc, var/h = 100)
blob_nodes += src
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
..(loc, h)
/obj/structure/blob/node/adjustcolors(var/a_color)
@@ -25,7 +26,7 @@
/obj/structure/blob/node/Destroy()
blob_nodes -= src
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/structure/blob/node/Life(seconds, times_fired)
diff --git a/code/game/gamemodes/blob/blobs/resource.dm b/code/game/gamemodes/blob/blobs/resource.dm
index f5d838fd0a2..14c240f681b 100644
--- a/code/game/gamemodes/blob/blobs/resource.dm
+++ b/code/game/gamemodes/blob/blobs/resource.dm
@@ -4,6 +4,7 @@
icon_state = "blob_resource"
health = 30
fire_resist = 2
+ point_return = 12
var/mob/camera/blob/overmind = null
var/resource_delay = 0
@@ -12,13 +13,9 @@
qdel(src)
/obj/structure/blob/resource/run_action()
-
if(resource_delay > world.time)
- return 0
-
+ return
+ flick("blob_resource_glow", src)
resource_delay = world.time + 40 // 4 seconds
-
if(overmind)
overmind.add_points(1)
- return 0
-
diff --git a/code/game/gamemodes/blob/blobs/shield.dm b/code/game/gamemodes/blob/blobs/shield.dm
index 696a33d94b9..0e74e601957 100644
--- a/code/game/gamemodes/blob/blobs/shield.dm
+++ b/code/game/gamemodes/blob/blobs/shield.dm
@@ -5,8 +5,12 @@
desc = "Some blob creature thingy"
health = 75
fire_resist = 2
+ point_return = 4
var/maxHealth = 75
+/obj/structure/blob/shield/core
+ point_return = 0
+
/obj/structure/blob/shield/update_icon()
if(health <= 0)
qdel(src)
@@ -27,11 +31,12 @@
brute_resist = 0
health = 50
maxHealth = 50
+ point_return = 9
flags_2 = CHECK_RICOCHET_1
var/reflect_chance = 80 //80% chance to reflect
/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P)
- if(P.is_reflectable && prob(reflect_chance))
+ if(P.is_reflectable && prob(reflect_chance) && !P.legacy)
var/P_turf = get_turf(P)
var/face_direction = get_dir(src, P_turf)
var/face_angle = dir2angle(face_direction)
@@ -43,6 +48,9 @@
P.firer = src //so people who fired the lasers are not immune to them when it reflects
visible_message("[P] reflects off [src]!")
return -1// complete projectile permutation
+ else if(P.is_reflectable && P.legacy) //to stop legacy projectile exploits
+ visible_message("[P] disperses into energy from [src]!")
+ qdel(P)
else
playsound(src, P.hitsound, 50, 1)
visible_message("[src] is hit by \a [P]!")
diff --git a/code/game/gamemodes/blob/blobs/storage.dm b/code/game/gamemodes/blob/blobs/storage.dm
index 8c9da104edf..00f6d7b4e0c 100644
--- a/code/game/gamemodes/blob/blobs/storage.dm
+++ b/code/game/gamemodes/blob/blobs/storage.dm
@@ -4,6 +4,7 @@
icon_state = "blob_resource"
health = 30
fire_resist = 2
+ point_return = 12
var/mob/camera/blob/overmind = null
/obj/structure/blob/storage/update_icon()
diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm
index c0f2e4a4a9e..4489aaf707b 100644
--- a/code/game/gamemodes/blob/overmind.dm
+++ b/code/game/gamemodes/blob/overmind.dm
@@ -5,8 +5,8 @@
icon_state = "marker"
see_in_dark = 8
- see_invisible = SEE_INVISIBLE_MINIMUM
invisibility = INVISIBILITY_OBSERVER
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
pass_flags = PASSBLOB
faction = list("blob")
@@ -15,9 +15,11 @@
var/blob_points = 0
var/max_blob_points = 100
var/last_attack = 0
+ var/nodes_required = TRUE //if the blob needs nodes to place resource and factory blobs
+ var/split_used = FALSE
+ var/is_offspring = FALSE
var/datum/reagent/blob/blob_reagent_datum = new/datum/reagent/blob()
var/list/blob_mobs = list()
- var/ghostimage = null
/mob/camera/blob/New()
var/new_name = "[initial(name)] ([rand(1, 999)])"
@@ -31,9 +33,7 @@
if(blob_core)
blob_core.adjustcolors(blob_reagent_datum.color)
- ghostimage = image(src.icon,src,src.icon_state)
- ghost_darkness_images |= ghostimage //so ghosts can see the blob cursor when they disable darkness
- updateallghostimages()
+ color = blob_reagent_datum.complementary_color
..()
/mob/camera/blob/Life(seconds, times_fired)
@@ -41,26 +41,10 @@
qdel(src)
..()
-/mob/camera/blob/Destroy()
- if(ghostimage)
- ghost_darkness_images -= ghostimage
- QDEL_NULL(ghostimage)
- updateallghostimages()
- return ..()
-
/mob/camera/blob/Login()
..()
sync_mind()
- to_chat(src, "You are the overmind!")
- to_chat(src, "Your randomly chosen reagent is: [blob_reagent_datum.name]!")
- to_chat(src, "You are the overmind and can control the blob! You can expand, which will attack people, and place new blob pieces such as...")
- to_chat(src, "Normal Blob will expand your reach and allow you to upgrade into special blobs that perform certain functions.")
- to_chat(src, "Shield Blob is a strong and expensive blob which can take more damage. It is fireproof and can block air, use this to protect yourself from station fires.")
- to_chat(src, "Reflective Blobis an upgraded Shield Blob which has a high chance of deflecting energy projectiles, but is vulnerable to ballistics and brute damage.")
- to_chat(src, "Resource Blob is a blob which will collect more resources for you, try to build these earlier to get a strong income. It will benefit from being near your core or multiple nodes, by having an increased resource rate; put it alone and it won't create resources at all.")
- to_chat(src, "Node Blob is a blob which will grow, like the core. Unlike the core it won't give you a small income but it can power resource and factory blobs to increase their rate.")
- to_chat(src, "Factory Blob is a blob which will spawn blob spores which will attack nearby food. Putting this nearby nodes and your core will increase the spawn rate; put it alone and it will not spawn any spores.")
- to_chat(src, "Shortcuts: CTRL Click = Expand Blob / Middle Mouse Click = Rally Spores / Alt Click = Create Shield")
+ blob_help()
update_health()
/mob/camera/blob/proc/update_health()
@@ -103,7 +87,7 @@
if(isovermind(M) || isobserver(M))
M.show_message(rendered, 2)
-/mob/camera/blob/emote(var/act,var/m_type=1,var/message = null)
+/mob/camera/blob/emote(act, m_type = 1, message = null, force)
return
/mob/camera/blob/blob_act()
diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm
index 4491b80d2e4..d6d4a91cf19 100644
--- a/code/game/gamemodes/blob/powers.dm
+++ b/code/game/gamemodes/blob/powers.dm
@@ -25,12 +25,23 @@
if(blob_nodes.len)
var/list/nodes = list()
for(var/i = 1; i <= blob_nodes.len; i++)
- nodes["Blob Node #[i]"] = blob_nodes[i]
+ var/obj/structure/blob/node/B = blob_nodes[i]
+ nodes["Blob Node #[i] ([get_location_name(B)])"] = B
var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes
var/obj/structure/blob/node/chosen_node = nodes[node_name]
if(chosen_node)
src.loc = chosen_node.loc
+/mob/camera/blob/verb/toggle_node_req()
+ set category = "Blob"
+ set name = "Toggle Node Requirement"
+ set desc = "Toggle requiring nodes to place resource and factory blobs."
+ nodes_required = !nodes_required
+ if(nodes_required)
+ to_chat(src, "You now require a nearby node or core to place factory and resource blobs.")
+ else
+ to_chat(src, "You no longer require a nearby node or core to place factory and resource blobs.")
+
/mob/camera/blob/verb/create_shield_power()
set category = "Blob"
set name = "Create/Upgrade Shield Blob (15)"
@@ -43,7 +54,7 @@
var/obj/structure/blob/B = locate(/obj/structure/blob) in T
var/obj/structure/blob/shield/S = locate(/obj/structure/blob/shield) in T
-
+
if(!S)
if(!B)//We are on a blob
to_chat(src, "There is no blob here!")
@@ -59,7 +70,7 @@
B.color = blob_reagent_datum.color
B.change_to(/obj/structure/blob/shield)
else
-
+
if(istype(S, /obj/structure/blob/shield/reflective))
to_chat(src, "There's already a reflector blob here!")
return
@@ -68,12 +79,12 @@
else if(S.health < S.maxHealth * 0.5)
to_chat(src, "This shield blob is too damaged to be modified properly!")
return
-
+
else if (!can_buy(15))
return
-
+
to_chat(src, "You secrete a reflective ooze over the shield blob, allowing it to reflect energy projectiles at the cost of reduced intregrity.")
-
+
S.change_to(/obj/structure/blob/shield/reflective)
S.color = blob_reagent_datum.color
return
@@ -103,6 +114,11 @@
to_chat(src, "There is a resource blob nearby, move more than 4 tiles away from it!")
return
+ if(nodes_required)
+ if(!(locate(/obj/structure/blob/node) in orange(3, T)) && !(locate(/obj/structure/blob/core) in orange(4, T)))
+ to_chat(src, "You need to place this blob closer to a node or core!")
+ return //handholdotron 2000
+
if(!can_buy(40))
return
@@ -174,6 +190,11 @@
to_chat(src, "There is a factory blob nearby, move more than 7 tiles away from it!")
return
+ if(nodes_required)
+ if(!(locate(/obj/structure/blob/node) in orange(3, T)) && !(locate(/obj/structure/blob/core) in orange(4, T)))
+ to_chat(src, "You need to place this blob closer to a node or core!")
+ return //handholdotron 2000
+
if(!can_buy(60))
return
@@ -210,7 +231,7 @@
var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut (get_turf(B))
if(blobber)
qdel(B)
- blobber.color = blob_reagent_datum.color
+ blobber.color = blob_reagent_datum.complementary_color
blobber.overmind = src
blob_mobs.Add(blobber)
return
@@ -245,21 +266,28 @@
/mob/camera/blob/verb/revert()
set category = "Blob"
set name = "Remove Blob"
- set desc = "Removes a blob."
+ set desc = "Removes a blob. You will receive 30% cost refund for special Blob structures."
var/turf/T = get_turf(src)
- if(!T)
- return
+ remove_blob(T)
+
+/mob/camera/blob/proc/remove_blob(var/turf/T)
var/obj/structure/blob/B = locate(/obj/structure/blob) in T
+ if(!T)
+ return
if(!B)
- to_chat(src, "You must be on a blob!")
+ to_chat(src, "There is no blob there!")
return
-
- if(istype(B, /obj/structure/blob/core))
- to_chat(src, "Unable to remove this blob.")
+ if(B.point_return < 0)
+ to_chat(src, "Unable to remove this blob.")
return
-
+ if(max_blob_points < B.point_return + blob_points)
+ to_chat(src, "You have too many resources to remove this blob!")
+ return
+ if(B.point_return)
+ add_points(B.point_return)
+ to_chat(src, "Gained [B.point_return] resources from removing \the [B].")
qdel(B)
return
@@ -304,17 +332,13 @@
/mob/camera/blob/verb/rally_spores_power()
set category = "Blob"
- set name = "Rally Spores (5)"
+ set name = "Rally Spores"
set desc = "Rally the spores to move to your location."
var/turf/T = get_turf(src)
rally_spores(T)
/mob/camera/blob/proc/rally_spores(var/turf/T)
-
- if(!can_buy(5))
- return
-
to_chat(src, "You rally your spores.")
var/list/surrounding_turfs = block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + 1, T.y + 1, T.z))
@@ -327,45 +351,53 @@
BS.Goto(pick(surrounding_turfs), BS.move_to_delay)
return
-
/mob/camera/blob/verb/split_consciousness()
set category = "Blob"
set name = "Split consciousness (100) (One use)"
- set desc = "Expend resources to attempt to produce another sentient overmind"
+ set desc = "Expend resources to attempt to produce another sentient overmind."
- if(!blob_nodes || !blob_nodes.len)
- to_chat(src, "A node is required to birth your offspring...")
+ var/turf/T = get_turf(src)
+ if(!T)
return
- var/obj/structure/blob/node/N = locate(/obj/structure/blob) in blob_nodes
+ if(split_used)
+ to_chat(src, "You have already produced an offspring.")
+ return
+ if(is_offspring)
+ to_chat(src, "You cannot split as an offspring of another Blob.")
+ return
+
+ var/obj/structure/blob/N = (locate(/obj/structure/blob) in T)
if(!N)
- to_chat(src, "A node is required to birth your offspring...")
+ to_chat(src, "A node is required to birth your offspring.")
+ return
+ if(!istype(N, /obj/structure/blob/node))
+ to_chat(src, "A node is required to birth your offspring.")
return
-
if(!can_buy(100))
return
- verbs -= /mob/camera/blob/verb/split_consciousness //we've used our split_consciousness
+ split_used = TRUE
new /obj/structure/blob/core/ (get_turf(N), 200, null, blob_core.point_rate, "offspring")
qdel(N)
- if(ticker && ticker.mode.name == "blob")
- var/datum/game_mode/blob/BL = ticker.mode
+ if(SSticker && SSticker.mode.name == "blob")
+ var/datum/game_mode/blob/BL = SSticker.mode
BL.blobwincount += initial(BL.blobwincount)
-
/mob/camera/blob/verb/blob_broadcast()
set category = "Blob"
set name = "Blob Broadcast"
set desc = "Speak with your blob spores and blobbernauts as your mouthpieces. This action is free."
- var/speak_text = input(usr, "What would you like to say with your minions?", "Blob Broadcast", null) as text
+ var/speak_text = clean_input("What would you like to say with your minions?", "Blob Broadcast", null)
if(!speak_text)
return
else
to_chat(usr, "You broadcast with your minions, [speak_text]")
for(var/mob/living/simple_animal/hostile/blob_minion in blob_mobs)
- blob_minion.say(speak_text)
+ if(blob_minion.stat == CONSCIOUS)
+ blob_minion.say(speak_text)
return
/mob/camera/blob/verb/create_storage()
@@ -409,7 +441,7 @@
/mob/camera/blob/verb/chemical_reroll()
set category = "Blob"
set name = "Reactive Chemical Adaptation (50)"
- set desc = "Replaces your chemical with a different one"
+ set desc = "Replaces your chemical with a random, different one."
if(!can_buy(50))
return
@@ -417,10 +449,31 @@
var/datum/reagent/blob/B = pick((subtypesof(/datum/reagent/blob) - blob_reagent_datum.type))
blob_reagent_datum = new B
+ color = blob_reagent_datum.complementary_color
+
for(var/obj/structure/blob/BL in blobs)
BL.adjustcolors(blob_reagent_datum.color)
for(var/mob/living/simple_animal/hostile/blob/BLO)
- BLO.adjustcolors(blob_reagent_datum.color)
+ BLO.adjustcolors(blob_reagent_datum.complementary_color)
- to_chat(src, "Your reagent is now: [blob_reagent_datum.name]!")
+ to_chat(src, "Your reagent is now: [blob_reagent_datum.name] - [blob_reagent_datum.description]")
+
+/mob/camera/blob/verb/blob_help()
+ set category = "Blob"
+ set name = "*Blob Help*"
+ set desc = "Help on how to blob."
+ to_chat(src, "As the overmind, you can control the blob!")
+ to_chat(src, "Your blob reagent is: [blob_reagent_datum.name] - [blob_reagent_datum.description]")
+ to_chat(src, "You can expand, which will attack people, damage objects, or place a Normal Blob if the tile is clear.")
+ to_chat(src, "Normal Blobs will expand your reach and can be upgraded into special blobs that perform certain functions.")
+ to_chat(src, "You can upgrade normal blobs into the following types of blob:")
+ to_chat(src, "Shield Blobs are strong and expensive blobs which take more damage. In additon, they are fireproof and can block air, use these to protect yourself from station fires. Upgrading them again will result in a Reflective blob, capable of reflecting laser projectiles at the cost of the strong blob's extra health.")
+ to_chat(src, "Resource Blobs are blobs which produce more resources for you, build as many of these as possible to consume the station. This type of blob must be placed near node blobs or your core to work.")
+ to_chat(src, "Factory Blobs are blobs that spawn blob spores which will attack nearby enemies. This type of blob must be placed near node blobs or your core to work.")
+ to_chat(src, "Blobbernauts can be produced from factories for a cost, and are hard to kill, powerful, but ultimately dumb. The factory used to create one will be destroyed in the process.")
+ to_chat(src, "Storage Blobs are storage towers which will store extra resources for you. This increases your max resource cap by 50.")
+ to_chat(src, "Node Blobs are blobs which grow, like the core. Like the core it can activate resource and factory blobs.")
+ to_chat(src, "In addition to the buttons on your HUD, there are a few click shortcuts to speed up expansion and defense.")
+ to_chat(src, "Shortcuts: Click = Expand Blob | CTRL Click = Create Shield Blob | Middle Mouse Click = Rally Spores | Alt Click = Remove Blob")
+ to_chat(src, "Attempting to talk will send a message to all other overminds, allowing you to coordinate with them.")
diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm
index ba3ad1dada8..ed06ec4086d 100644
--- a/code/game/gamemodes/blob/theblob.dm
+++ b/code/game/gamemodes/blob/theblob.dm
@@ -7,6 +7,7 @@
density = 0
opacity = 0
anchored = 1
+ var/point_return = 0 //How many points the blob gets back when it removes a blob of that type. If less than 0, blob cannot be removed.
var/health = 30
var/health_timestamp = 0
var/brute_resist = 4
@@ -31,8 +32,10 @@
/obj/structure/blob/CanPass(atom/movable/mover, turf/target, height=0)
- if(height==0) return 1
- if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
+ if(height==0)
+ return 1
+ if(istype(mover) && mover.checkpass(PASSBLOB))
+ return 1
return 0
/obj/structure/blob/CanAStarPass(ID, dir, caller)
@@ -139,7 +142,7 @@
take_damage(Proj.damage, Proj.damage_type)
return 0
-/obj/structure/blob/Crossed(var/mob/living/L)
+/obj/structure/blob/Crossed(var/mob/living/L, oldloc)
..()
L.blob_act(src)
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index d0ac848d905..038f331f924 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -240,10 +240,10 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
var/geneticpoints = 10
var/purchasedpowers = list()
var/mimicing = ""
- var/canrespec = 0
+ var/canrespec = FALSE //set to TRUE in absorb.dm
var/changeling_speak = 0
var/datum/dna/chosen_dna
- var/obj/effect/proc_holder/changeling/sting/chosen_sting
+ var/datum/action/changeling/sting/chosen_sting
var/regenerating = FALSE
/datum/changeling/New(gender=FEMALE)
@@ -329,4 +329,4 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
return 1
/proc/can_absorb_species(datum/species/S)
- return !(NO_DNA in S.species_traits)
\ No newline at end of file
+ return !(NO_DNA in S.species_traits)
diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm
index 387e7ce9d61..69142049280 100644
--- a/code/game/gamemodes/changeling/changeling_power.dm
+++ b/code/game/gamemodes/changeling/changeling_power.dm
@@ -3,10 +3,10 @@
* TODO: combine atleast some of the functionality with /proc_holder/spell
*/
-/obj/effect/proc_holder/changeling
- panel = "Changeling"
+/datum/action/changeling
name = "Prototype Sting"
desc = "" // Fluff
+ background_icon_state = "bg_changeling"
var/helptext = "" // Details
var/chemical_cost = 0 // negative chemical cost is for passive abilities (chemical glands)
var/dna_cost = -1 //cost of the sting in dna points. 0 = auto-purchase, -1 = cannot be purchased
@@ -16,20 +16,26 @@
var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss.
var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet.
var/always_keep = 0 // important for abilities like regenerate that screw you if you lose them.
+ var/needs_button = TRUE // for passive abilities like hivemind that dont need a button
+ var/active = FALSE // used by a few powers that toggle
-/obj/effect/proc_holder/changeling/proc/on_purchase(var/mob/user)
- return
+/*
+changeling code now relies on on_purchase to grant powers.
+if you override it, MAKE SURE you call parent or it will not be usable
+the same goes for Remove(). if you override Remove(), call parent or else your power wont be removed on respec
+*/
-/obj/effect/proc_holder/changeling/proc/on_refund(mob/user)
- return
+/datum/action/changeling/proc/on_purchase(var/mob/user)
+ if(needs_button)
+ Grant(user)
-/obj/effect/proc_holder/changeling/Click()
- var/mob/user = usr
+/datum/action/changeling/Trigger()
+ var/mob/user = owner
if(!user || !user.mind || !user.mind.changeling)
return
try_to_sting(user)
-/obj/effect/proc_holder/changeling/proc/try_to_sting(var/mob/user, var/mob/target)
+/datum/action/changeling/proc/try_to_sting(var/mob/user, var/mob/target)
if(!user.mind || !user.mind.changeling)
return
if(!can_sting(user, target))
@@ -39,18 +45,18 @@
sting_feedback(user, target)
take_chemical_cost(c)
-/obj/effect/proc_holder/changeling/proc/sting_action(var/mob/user, var/mob/target)
+/datum/action/changeling/proc/sting_action(var/mob/user, var/mob/target)
return 0
-/obj/effect/proc_holder/changeling/proc/sting_feedback(var/mob/user, var/mob/target)
+/datum/action/changeling/proc/sting_feedback(var/mob/user, var/mob/target)
return 0
-/obj/effect/proc_holder/changeling/proc/take_chemical_cost(var/datum/changeling/changeling)
+/datum/action/changeling/proc/take_chemical_cost(var/datum/changeling/changeling)
changeling.chem_charges -= chemical_cost
changeling.geneticdamage += genetic_damage
//Fairly important to remember to return 1 on success >.<
-/obj/effect/proc_holder/changeling/proc/can_sting(var/mob/user, var/mob/target)
+/datum/action/changeling/proc/can_sting(var/mob/user, var/mob/target)
if(!ishuman(user)) //typecast everything from mob to carbon from this point onwards
return 0
if(req_human && (!ishuman(user) || issmall(user)))
@@ -75,7 +81,7 @@
return 1
//used in /mob/Stat()
-/obj/effect/proc_holder/changeling/proc/can_be_used_by(var/mob/user)
+/datum/action/changeling/proc/can_be_used_by(var/mob/user)
if(!ishuman(user))
return 0
if(req_human && !ishuman(user))
@@ -83,10 +89,10 @@
return 1
// Transform the target to the chosen dna. Used in transform.dm and tiny_prick.dm (handy for changes since it's the same thing done twice)
-/obj/effect/proc_holder/changeling/proc/transform_dna(var/mob/living/carbon/human/H, var/datum/dna/D)
+/datum/action/changeling/proc/transform_dna(var/mob/living/carbon/human/H, var/datum/dna/D)
if(!D)
return
-
+
H.set_species(D.species.type, retain_damage = TRUE)
H.dna = D.Clone()
H.real_name = D.real_name
diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm
index befdf899253..b6a0213f82f 100644
--- a/code/game/gamemodes/changeling/evolution_menu.dm
+++ b/code/game/gamemodes/changeling/evolution_menu.dm
@@ -1,24 +1,24 @@
var/list/sting_paths
// totally stolen from the new player panel. YAYY
-/obj/effect/proc_holder/changeling/evolution_menu
+/datum/action/changeling/evolution_menu
name = "-Evolution Menu-" //Dashes are so it's listed before all the other abilities.
desc = "Choose our method of subjugation."
+ button_icon_state = "changelingsting"
dna_cost = 0
-/obj/effect/proc_holder/changeling/evolution_menu/Click()
+/datum/action/changeling/evolution_menu/Trigger()
if(!usr || !usr.mind || !usr.mind.changeling)
return
var/datum/changeling/changeling = usr.mind.changeling
if(!sting_paths)
- sting_paths = init_subtypes(/obj/effect/proc_holder/changeling)
+ sting_paths = init_subtypes(/datum/action/changeling)
var/dat = create_menu(changeling)
usr << browse(dat, "window=powers;size=600x700")//900x480
-
-/obj/effect/proc_holder/changeling/evolution_menu/proc/create_menu(var/datum/changeling/changeling)
+/datum/action/changeling/evolution_menu/proc/create_menu(var/datum/changeling/changeling)
var/dat
dat +="Changeling Evolution Menu"
@@ -230,7 +230,7 @@ var/list/sting_paths
"}
var/i = 1
- for(var/obj/effect/proc_holder/changeling/cling_power in sting_paths)
+ for(var/datum/action/changeling/cling_power in sting_paths)
if(cling_power.dna_cost <= 0) //Let's skip the crap we start with. Keeps the evolution menu uncluttered.
continue
@@ -283,7 +283,7 @@ var/list/sting_paths
return dat
-/obj/effect/proc_holder/changeling/evolution_menu/Topic(href, href_list)
+/datum/action/changeling/evolution_menu/Topic(href, href_list)
..()
if(!(iscarbon(usr) && usr.mind && usr.mind.changeling))
return
@@ -297,12 +297,10 @@ var/list/sting_paths
/////
/datum/changeling/proc/purchasePower(var/mob/living/carbon/user, var/sting_name)
+ var/datum/action/changeling/thepower = null
+ var/list/all_powers = init_subtypes(/datum/action/changeling)
- var/obj/effect/proc_holder/changeling/thepower = null
-
- if(!sting_paths)
- sting_paths = init_subtypes(/obj/effect/proc_holder/changeling)
- for(var/obj/effect/proc_holder/changeling/cling_sting in sting_paths)
+ for(var/datum/action/changeling/cling_sting in all_powers)
if(cling_sting.name == sting_name)
thepower = cling_sting
@@ -343,21 +341,19 @@ var/list/sting_paths
to_chat(user, "We have removed our evolutions from this form, and are now ready to readapt.")
user.remove_changeling_powers(1)
canrespec = 0
- user.make_changeling()
+ user.make_changeling(FALSE)
return 1
else
to_chat(user, "You lack the power to readapt your evolutions!")
return 0
-/mob/proc/make_changeling()
+/mob/proc/make_changeling(var/get_free_powers = TRUE)
if(!mind)
return
if(!ishuman(src))
return
if(!mind.changeling)
mind.changeling = new /datum/changeling(gender)
- if(!sting_paths)
- sting_paths = init_subtypes(/obj/effect/proc_holder/changeling)
if(mind.changeling.purchasedpowers)
remove_changeling_powers(1)
@@ -366,13 +362,23 @@ var/list/sting_paths
for(var/language in languages)
mind.changeling.absorbed_languages |= language
- // purchase free powers.
- for(var/obj/effect/proc_holder/changeling/path in sting_paths)
- //var/obj/effect/proc_holder/changeling/S = new path()
- if(!path.dna_cost)
- if(!mind.changeling.has_sting(path))
- mind.changeling.purchasedpowers += path
- path.on_purchase(src)
+ if(get_free_powers)
+ var/list/all_powers = init_subtypes(/datum/action/changeling)
+ for(var/datum/action/changeling/path in all_powers) // purchase free powers.
+ if(!path.dna_cost)
+ if(!mind.changeling.has_sting(path))
+ mind.changeling.purchasedpowers += path
+ path.on_purchase(src)
+ else //for respec
+ var/datum/action/changeling/hivemind_upload/S1 = new
+ if(!mind.changeling.has_sting(S1))
+ mind.changeling.purchasedpowers+=S1
+ S1.Grant(src)
+
+ var/datum/action/changeling/hivemind_download/S2 = new
+ if(!mind.changeling.has_sting(S2))
+ mind.changeling.purchasedpowers+=S2
+ S2.Grant(src)
var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste
mind.changeling.absorbed_dna |= C.dna.Clone()
@@ -406,18 +412,18 @@ var/list/sting_paths
digitalcamo = 0
mind.changeling.changeling_speak = 0
mind.changeling.reset()
- for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers)
+ for(var/datum/action/changeling/p in mind.changeling.purchasedpowers)
if((p.dna_cost == 0 && keep_free_powers) || p.always_keep)
continue
mind.changeling.purchasedpowers -= p
- p.on_refund(src)
+ p.Remove(src)
remove_language("Changeling")
if(hud_used)
hud_used.lingstingdisplay.icon_state = null
hud_used.lingstingdisplay.invisibility = 101
-/datum/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power)
- for(var/obj/effect/proc_holder/changeling/P in purchasedpowers)
+/datum/changeling/proc/has_sting(datum/action/power)
+ for(var/datum/action/P in purchasedpowers)
if(power.name == P.name)
return 1
return 0
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index b60cfee4718..b5ad5ab9f8a 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -1,12 +1,13 @@
-/obj/effect/proc_holder/changeling/absorbDNA
+/datum/action/changeling/absorbDNA
name = "Absorb DNA"
- desc = "Absorb the DNA of our victim."
+ desc = "Absorb the DNA of our victim. Requires us to strangle them."
+ button_icon_state = "absorb_dna"
chemical_cost = 0
dna_cost = 0
req_human = 1
max_genetic_damage = 100
-/obj/effect/proc_holder/changeling/absorbDNA/can_sting(var/mob/living/carbon/user)
+/datum/action/changeling/absorbDNA/can_sting(mob/living/carbon/user)
if(!..())
return
@@ -26,7 +27,7 @@
var/mob/living/carbon/target = G.affecting
return changeling.can_absorb_dna(user,target)
-/obj/effect/proc_holder/changeling/absorbDNA/sting_action(var/mob/user)
+/datum/action/changeling/absorbDNA/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/obj/item/grab/G = user.get_active_hand()
var/mob/living/carbon/human/target = G.affecting
diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
index bf16d90d55e..b0b77a456d5 100644
--- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
+++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
@@ -1,36 +1,40 @@
//Augmented Eyesight: Gives you thermal and night vision - bye bye, flashlights. Also, high DNA cost because of how powerful it is.
//Possible todo: make a custom message for directing a penlight/flashlight at the eyes - not sure what would display though.
-/obj/effect/proc_holder/changeling/augmented_eyesight
+/datum/action/changeling/augmented_eyesight
name = "Augmented Eyesight"
desc = "Creates heat receptors in our eyes and dramatically increases light sensing ability."
- helptext = "Grants us thermal vision or flash protection. We will become a lot more vulnerable to flash-based devices while thermal vision is active."
+ helptext = "Grants us thermal vision or flash protection. We will become a lot more vulnerable to flash based devices while thermal vision is active."
+ button_icon_state = "augmented_eyesight"
chemical_cost = 0
dna_cost = 2 //Would be 1 without thermal vision
+ active = FALSE
-/obj/effect/proc_holder/changeling/augmented_eyesight/sting_action(mob/living/carbon/human/user)
+/datum/action/changeling/augmented_eyesight/on_purchase(mob/user) //The ability starts inactive, so we should be protected from flashes.
+ ..()
+ var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/shield/ling()
+ O.insert(user)
+ active = FALSE
+
+/datum/action/changeling/augmented_eyesight/sting_action(mob/living/carbon/user)
if(!istype(user))
return
- if(user.get_int_organ(/obj/item/organ/internal/cyberimp/eyes/thermals/ling))
- var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/shield/ling()
- O.insert(user)
-
- else
+ if(!active)
var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/thermals/ling()
O.insert(user)
-
+ active = TRUE
+ else
+ var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/shield/ling()
+ O.insert(user)
+ active = FALSE
return 1
-
-/obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user)
+/datum/action/changeling/augmented_eyesight/Remove(mob/user)
var/obj/item/organ/internal/cyberimp/eyes/O = user.get_organ_slot("eye_ling")
if(O)
O.remove(user)
qdel(O)
-
-
-
-
+ ..()
/obj/item/organ/internal/cyberimp/eyes/shield/ling
name = "protective membranes"
@@ -53,7 +57,6 @@
S.reagents.add_reagent("oculine", 15)
return S
-
/obj/item/organ/internal/cyberimp/eyes/thermals/ling
name = "heat receptors"
desc = "These heat receptors dramatically increases eyes light sensing ability."
diff --git a/code/game/gamemodes/changeling/powers/biodegrade.dm b/code/game/gamemodes/changeling/powers/biodegrade.dm
index 5142734183b..c8a7721a5f5 100644
--- a/code/game/gamemodes/changeling/powers/biodegrade.dm
+++ b/code/game/gamemodes/changeling/powers/biodegrade.dm
@@ -1,12 +1,13 @@
-/obj/effect/proc_holder/changeling/biodegrade
+/datum/action/changeling/biodegrade
name = "Biodegrade"
- desc = "Dissolves restraints or other objects preventing free movement."
+ desc = "Dissolves restraints or other objects preventing free movement. Costs 30 chemicals."
helptext = "This is obvious to nearby people, and can destroy standard restraints and closets."
+ button_icon_state = "biodegrade"
chemical_cost = 30 //High cost to prevent spam
dna_cost = 2
req_human = 1
-/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
+/datum/action/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
var/used = FALSE // only one form of shackles removed per use
if(!user.restrained() && !istype(user.loc, /obj/structure/closet) && !istype(user.loc, /obj/structure/spider/cocoon))
to_chat(user, "We are already free!")
@@ -30,7 +31,6 @@
addtimer(CALLBACK(src, .proc/dissolve_straightjacket, user, S), 30)
used = TRUE
-
if(istype(user.loc, /obj/structure/closet) && !used)
var/obj/structure/closet/C = user.loc
if(!istype(C))
@@ -53,21 +53,21 @@
feedback_add_details("changeling_powers","BD")
return TRUE
-/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_handcuffs(mob/living/carbon/human/user, obj/O)
+/datum/action/changeling/biodegrade/proc/dissolve_handcuffs(mob/living/carbon/human/user, obj/O)
if(O && user.handcuffed == O)
user.unEquip(O)
O.visible_message("[O] dissolves into a puddle of sizzling goop.")
O.forceMove(get_turf(user))
qdel(O)
-/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S)
+/datum/action/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S)
if(S && user.wear_suit == S)
user.unEquip(S)
S.visible_message("[S] dissolves into a puddle of sizzling goop.")
S.forceMove(get_turf(user))
qdel(S)
-/obj/effect/proc_holder/changeling/biodegrade/proc/open_closet(mob/living/carbon/human/user, obj/structure/closet/C)
+/datum/action/changeling/biodegrade/proc/open_closet(mob/living/carbon/human/user, obj/structure/closet/C)
if(C && user.loc == C)
C.visible_message("[C]'s door breaks and opens!")
C.welded = FALSE
@@ -76,7 +76,7 @@
C.open()
to_chat(user, "We open the container restraining us!")
-/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_cocoon(mob/living/carbon/human/user, obj/structure/spider/cocoon/C)
+/datum/action/changeling/biodegrade/proc/dissolve_cocoon(mob/living/carbon/human/user, obj/structure/spider/cocoon/C)
if(C && user.loc == C)
qdel(C) //The cocoon's destroy will move the changeling outside of it without interference
to_chat(user, "We dissolve the cocoon!")
diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
index 07340cf3e84..7de16801153 100644
--- a/code/game/gamemodes/changeling/powers/chameleon_skin.dm
+++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
@@ -1,12 +1,13 @@
-/obj/effect/proc_holder/changeling/chameleon_skin
+/datum/action/changeling/chameleon_skin
name = "Chameleon Skin"
- desc = "Our skin pigmentation rapidly changes to suit our current environment."
+ desc = "Our skin pigmentation rapidly changes to suit our current environment. Costs 25 chemicals."
helptext = "Allows us to become invisible after a few seconds of standing still. Can be toggled on and off."
+ button_icon_state = "chameleon_skin"
dna_cost = 2
chemical_cost = 25
req_human = 1
-/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
+/datum/action/changeling/chameleon_skin/sting_action(mob/user)
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
if(!istype(H)) // req_human could be done in can_sting stuff.
return
@@ -20,8 +21,9 @@
feedback_add_details("changeling_powers","CS")
return TRUE
-/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user)
+/datum/action/changeling/chameleon_skin/Remove(mob/user)
var/mob/living/carbon/C = user
if(C.dna.GetSEState(CHAMELEONBLOCK))
C.dna.SetSEState(CHAMELEONBLOCK, 0)
genemutcheck(C, CHAMELEONBLOCK, null, MUTCHK_FORCED)
+ ..()
diff --git a/code/game/gamemodes/changeling/powers/digitalcamo.dm b/code/game/gamemodes/changeling/powers/digitalcamo.dm
index bc5879f67be..dd309b55060 100644
--- a/code/game/gamemodes/changeling/powers/digitalcamo.dm
+++ b/code/game/gamemodes/changeling/powers/digitalcamo.dm
@@ -1,11 +1,12 @@
-/obj/effect/proc_holder/changeling/digitalcamo
+/datum/action/changeling/digitalcamo
name = "Digital Camouflage"
desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras."
helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us... uncanny."
+ button_icon_state = "digital_camo"
dna_cost = 1
//Prevents AIs tracking you but makes you easily detectable to the human-eye.
-/obj/effect/proc_holder/changeling/digitalcamo/sting_action(var/mob/user)
+/datum/action/changeling/digitalcamo/sting_action(var/mob/user)
if(user.digitalcamo)
to_chat(user, "We return to normal.")
diff --git a/code/game/gamemodes/changeling/powers/epinephrine.dm b/code/game/gamemodes/changeling/powers/epinephrine.dm
index 4e783f111cc..786ad0660ee 100644
--- a/code/game/gamemodes/changeling/powers/epinephrine.dm
+++ b/code/game/gamemodes/changeling/powers/epinephrine.dm
@@ -1,19 +1,21 @@
-/obj/effect/proc_holder/changeling/epinephrine
+/datum/action/changeling/epinephrine
name = "Epinephrine Overdose"
- desc = "We evolve additional sacs of adrenaline throughout our body."
- helptext = "Removes all stuns instantly and adds a short-term reduction in further stuns. Can be used while unconscious. Continued use poisons the body."
+ desc = "We evolve additional sacs of adrenaline throughout our body. Costs 30 chemicals."
+ helptext = "Removes all stuns instantly and adds a short term reduction in further stuns. Can be used while unconscious. Continued use poisons the body."
+ button_icon_state = "adrenaline"
chemical_cost = 30
dna_cost = 2
req_human = 1
req_stat = UNCONSCIOUS
//Recover from stuns.
-/obj/effect/proc_holder/changeling/epinephrine/sting_action(var/mob/living/user)
+/datum/action/changeling/epinephrine/sting_action(var/mob/living/user)
if(user.lying)
to_chat(user, "We arise.")
else
to_chat(user, "Adrenaline rushes through us.")
+ user.SetSleeping(0)
user.stat = 0
user.SetParalysis(0)
user.SetStunned(0)
diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm
index 19cbbbdc3bd..d403059b0c7 100644
--- a/code/game/gamemodes/changeling/powers/fakedeath.dm
+++ b/code/game/gamemodes/changeling/powers/fakedeath.dm
@@ -1,6 +1,7 @@
-/obj/effect/proc_holder/changeling/fakedeath
+/datum/action/changeling/fakedeath
name = "Regenerative Stasis"
- desc = "We fall into a stasis, allowing us to regenerate."
+ desc = "We fall into a stasis, allowing us to regenerate and trick our enemies. Costs 15 chemicals."
+ button_icon_state = "fake_death"
chemical_cost = 15
dna_cost = 0
req_dna = 1
@@ -8,7 +9,7 @@
max_genetic_damage = 100
//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay.
-/obj/effect/proc_holder/changeling/fakedeath/sting_action(var/mob/living/user)
+/datum/action/changeling/fakedeath/sting_action(var/mob/living/user)
to_chat(user, "We begin our stasis, preparing energy to arise once more.")
if(user.stat != DEAD)
@@ -26,12 +27,13 @@
feedback_add_details("changeling_powers","FD")
return 1
-/obj/effect/proc_holder/changeling/fakedeath/proc/ready_to_regenerate(mob/user)
+/datum/action/changeling/fakedeath/proc/ready_to_regenerate(mob/user)
if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers)
to_chat(user, "We are ready to regenerate.")
- user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null)
+ var/datum/action/changeling/revive/R = new
+ R.Grant(user)
-/obj/effect/proc_holder/changeling/fakedeath/can_sting(var/mob/user)
+/datum/action/changeling/fakedeath/can_sting(var/mob/user)
if(user.status_flags & FAKEDEATH)
to_chat(user, "We are already regenerating.")
return
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index 6dbd4badc30..f7475090660 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -1,7 +1,8 @@
-/obj/effect/proc_holder/changeling/fleshmend
+/datum/action/changeling/fleshmend
name = "Fleshmend"
- desc = "Our flesh rapidly regenerates, healing our wounds."
- helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious."
+ desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath. Costs 20 chemicals."
+ helptext = "If we are on fire, the healing effect will not function. Does not regrow limbs or restore lost blood. Functions while unconscious."
+ button_icon_state = "fleshmend"
chemical_cost = 20
dna_cost = 2
req_stat = UNCONSCIOUS
@@ -11,20 +12,20 @@
// divided by healing_ticks to get heal/tick
var/total_healing = 100
-/obj/effect/proc_holder/changeling/fleshmend/New()
+/datum/action/changeling/fleshmend/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
-/obj/effect/proc_holder/changeling/fleshmend/Destroy()
- processing_objects.Remove(src)
+/datum/action/changeling/fleshmend/Destroy()
+ STOP_PROCESSING(SSobj, src)
return ..()
-/obj/effect/proc_holder/changeling/fleshmend/process()
+/datum/action/changeling/fleshmend/process()
if(recent_uses > 1)
recent_uses = max(1, recent_uses - (1 / healing_ticks))
//Starts healing you every second for 10 seconds. Can be used whilst unconscious.
-/obj/effect/proc_holder/changeling/fleshmend/sting_action(var/mob/living/user)
+/datum/action/changeling/fleshmend/sting_action(var/mob/living/user)
to_chat(user, "We begin to heal rapidly.")
if(recent_uses > 1)
to_chat(user, "Our healing's effectiveness is reduced \
@@ -35,14 +36,11 @@
feedback_add_details("changeling_powers","RR")
return TRUE
-/obj/effect/proc_holder/changeling/fleshmend/proc/fleshmend(mob/living/user)
+/datum/action/changeling/fleshmend/proc/fleshmend(mob/living/user)
// The healing itself - doesn't heal toxin damage
// (that's anatomic panacea) and the effectiveness decreases with
// each use in a short timespan
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- H.shock_stage = 0
for(var/i in 1 to healing_ticks)
if(user)
var/healpertick = -(total_healing / healing_ticks)
diff --git a/code/game/gamemodes/changeling/powers/headcrab.dm b/code/game/gamemodes/changeling/powers/headcrab.dm
index a950ec7a9c9..b39a2bba0d5 100644
--- a/code/game/gamemodes/changeling/powers/headcrab.dm
+++ b/code/game/gamemodes/changeling/powers/headcrab.dm
@@ -1,17 +1,18 @@
-/obj/effect/proc_holder/changeling/headcrab
+/datum/action/changeling/headcrab
name = "Last Resort"
- desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel."
+ desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel that can plant our likeness in a new host. Costs 20 chemicals."
helptext = "We will be placed in control of a small, fragile creature. We may attack a corpse like this to plant an egg which will slowly mature into a new form for us."
+ button_icon_state = "last_resort"
chemical_cost = 20
dna_cost = 1
req_human = 1
-/obj/effect/proc_holder/changeling/headcrab/try_to_sting(mob/user, mob/target)
+/datum/action/changeling/headcrab/try_to_sting(mob/user, mob/target)
if(alert("Are you sure you wish to do this? This action cannot be undone.",,"Yes","No")=="No")
return
..()
-/obj/effect/proc_holder/changeling/headcrab/sting_action(mob/user)
+/datum/action/changeling/headcrab/sting_action(mob/user)
var/datum/mind/M = user.mind
var/list/organs = user.get_organs_zone("head", 1)
@@ -42,4 +43,4 @@
to_chat(crab, "You burst out of the remains of your former body in a shower of gore!")
user.gib()
feedback_add_details("changeling_powers","LR")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm
index 0976f0da36d..af375cad368 100644
--- a/code/game/gamemodes/changeling/powers/hivemind.dm
+++ b/code/game/gamemodes/changeling/powers/hivemind.dm
@@ -1,34 +1,38 @@
//HIVEMIND COMMUNICATION (:g)
-/obj/effect/proc_holder/changeling/hivemind_comms
+/datum/action/changeling/hivemind_comms
name = "Hivemind Communication"
desc = "We tune our senses to the airwaves to allow us to discreetly communicate and exchange DNA with other changelings."
helptext = "We will be able to talk with other changelings with :g. Exchanged DNA do not count towards absorb objectives."
dna_cost = 0
chemical_cost = -1
+ needs_button = FALSE
-/obj/effect/proc_holder/changeling/hivemind_comms/on_purchase(var/mob/user)
+/datum/action/changeling/hivemind_comms/on_purchase(var/mob/user)
..()
var/datum/changeling/changeling=user.mind.changeling
changeling.changeling_speak = 1
to_chat(user, "Use say \":g message\" to communicate with the other changelings.")
- var/obj/effect/proc_holder/changeling/hivemind_upload/S1 = new
+ var/datum/action/changeling/hivemind_upload/S1 = new
if(!changeling.has_sting(S1))
changeling.purchasedpowers+=S1
- var/obj/effect/proc_holder/changeling/hivemind_download/S2 = new
+ S1.Grant(user)
+ var/datum/action/changeling/hivemind_download/S2 = new
if(!changeling.has_sting(S2))
+ S2.Grant(user)
changeling.purchasedpowers+=S2
return
// HIVE MIND UPLOAD/DOWNLOAD DNA
var/list/datum/dna/hivemind_bank = list()
-/obj/effect/proc_holder/changeling/hivemind_upload
+/datum/action/changeling/hivemind_upload
name = "Hive Channel DNA"
- desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it."
+ desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it. Costs 10 chemicals."
+ button_icon_state = "hivemind_channel"
chemical_cost = 10
dna_cost = -1
-/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/user)
+/datum/action/changeling/hivemind_upload/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna))
@@ -52,13 +56,14 @@ var/list/datum/dna/hivemind_bank = list()
feedback_add_details("changeling_powers","HU")
return 1
-/obj/effect/proc_holder/changeling/hivemind_download
+/datum/action/changeling/hivemind_download
name = "Hive Absorb DNA"
- desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives."
+ desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives. Costs 10 chemicals."
+ button_icon_state = "hive_absorb"
chemical_cost = 10
dna_cost = -1
-/obj/effect/proc_holder/changeling/hivemind_download/can_sting(var/mob/living/carbon/user)
+/datum/action/changeling/hivemind_download/can_sting(var/mob/living/carbon/user)
if(!..())
return
var/datum/changeling/changeling = user.mind.changeling
@@ -67,7 +72,7 @@ var/list/datum/dna/hivemind_bank = list()
return
return 1
-/obj/effect/proc_holder/changeling/hivemind_download/sting_action(var/mob/user)
+/datum/action/changeling/hivemind_download/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
for(var/datum/dna/DNA in hivemind_bank)
@@ -87,4 +92,4 @@ var/list/datum/dna/hivemind_bank = list()
changeling.store_dna(chosen_dna, user)
to_chat(user, "We absorb the DNA of [S] from the air.")
feedback_add_details("changeling_powers","HD")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm
index 72b0e821e66..f9b214c513c 100644
--- a/code/game/gamemodes/changeling/powers/humanform.dm
+++ b/code/game/gamemodes/changeling/powers/humanform.dm
@@ -1,14 +1,14 @@
-/obj/effect/proc_holder/changeling/humanform
+/datum/action/changeling/humanform
name = "Human form"
- desc = "We change into a human."
+ desc = "We change into a human. Costs 5 chemicals."
+ button_icon_state = "human_form"
chemical_cost = 5
genetic_damage = 3
req_dna = 1
max_genetic_damage = 3
-
//Transform into a human.
-/obj/effect/proc_holder/changeling/humanform/sting_action(var/mob/living/carbon/human/user)
+/datum/action/changeling/humanform/sting_action(var/mob/living/carbon/human/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna))
@@ -38,7 +38,7 @@
user.UpdateAppearance()
changeling.purchasedpowers -= src
- //O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/lesserform(null)
+ //O.mind.changeling.purchasedpowers += new /datum/action/changeling/lesserform(null)
+ src.Remove(user)
feedback_add_details("changeling_powers","LFT")
return 1
-
diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm
index 2197163cbd5..0dd112b66dd 100644
--- a/code/game/gamemodes/changeling/powers/lesserform.dm
+++ b/code/game/gamemodes/changeling/powers/lesserform.dm
@@ -1,13 +1,15 @@
-/obj/effect/proc_holder/changeling/lesserform
+/datum/action/changeling/lesserform
name = "Lesser form"
- desc = "We debase ourselves and become lesser. We become a monkey."
+ desc = "We debase ourselves and become lesser. We become a monkey. Costs 5 chemicals."
+ helptext = "The transformation greatly reduces our size, allowing us to slip out of cuffs and climb through vents."
+ button_icon_state = "lesser_form"
chemical_cost = 5
dna_cost = 1
genetic_damage = 3
req_human = 1
//Transform into a monkey.
-/obj/effect/proc_holder/changeling/lesserform/sting_action(var/mob/living/carbon/human/user)
+/datum/action/changeling/lesserform/sting_action(var/mob/living/carbon/human/user)
var/datum/changeling/changeling = user.mind.changeling
if(!user)
return 0
@@ -25,6 +27,10 @@
changeling.geneticdamage = 30
to_chat(H, "Our genes cry out!")
H.monkeyize()
- changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
+
+ var/datum/action/changeling/humanform/HF = new
+ changeling.purchasedpowers += HF
+ HF.Grant(user)
+
feedback_add_details("changeling_powers","LF")
return 1
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/powers/linglink.dm b/code/game/gamemodes/changeling/powers/linglink.dm
index b9f984b57c0..ba203a3e71f 100644
--- a/code/game/gamemodes/changeling/powers/linglink.dm
+++ b/code/game/gamemodes/changeling/powers/linglink.dm
@@ -1,12 +1,14 @@
-/obj/effect/proc_holder/changeling/linglink
+/datum/action/changeling/linglink
name = "Hivemind Link"
- desc = "Link your victim's mind into the hivemind for personal interrogation"
+ desc = "We link our victim's mind into the hivemind for personal interrogation."
+ helptext = "If we find a human mad enough to support our cause, this can be a helpful tool to stay in touch."
+ button_icon_state = "hivemind_link"
chemical_cost = 0
dna_cost = 0
req_human = 1
max_genetic_damage = 100
-/obj/effect/proc_holder/changeling/linglink/can_sting(mob/living/carbon/user)
+/datum/action/changeling/linglink/can_sting(mob/living/carbon/user)
if(!..())
return
var/datum/changeling/changeling = user.mind.changeling
@@ -34,7 +36,7 @@
return
return changeling.can_absorb_dna(user,target)
-/obj/effect/proc_holder/changeling/linglink/sting_action(mob/user)
+/datum/action/changeling/linglink/sting_action(mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/obj/item/grab/G = user.get_active_hand()
var/mob/living/carbon/target = G.affecting
diff --git a/code/game/gamemodes/changeling/powers/mimic_voice.dm b/code/game/gamemodes/changeling/powers/mimic_voice.dm
index 21693a84c3a..27211bd8a79 100644
--- a/code/game/gamemodes/changeling/powers/mimic_voice.dm
+++ b/code/game/gamemodes/changeling/powers/mimic_voice.dm
@@ -1,14 +1,15 @@
-/obj/effect/proc_holder/changeling/mimicvoice
+/datum/action/changeling/mimicvoice
name = "Mimic Voice"
- desc = "We shape our vocal glands to sound like a desired voice."
+ desc = "We shape our vocal glands to sound like a desired voice. Maintaining this power slows chemical production."
helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this."
+ button_icon_state = "mimic_voice"
chemical_cost = 0 //constant chemical drain hardcoded
dna_cost = 1
req_human = 1
// Fake Voice
-/obj/effect/proc_holder/changeling/mimicvoice/sting_action(var/mob/user)
+/datum/action/changeling/mimicvoice/sting_action(var/mob/user)
var/datum/changeling/changeling=user.mind.changeling
if(changeling.mimicing)
changeling.mimicing = ""
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index 0c8d22b5a8b..59e93e2d513 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -9,7 +9,7 @@
//Parent to shields and blades because muh copypasted code.
-/obj/effect/proc_holder/changeling/weapon
+/datum/action/changeling/weapon
name = "Organic Weapon"
desc = "Go tell a coder if you see this"
helptext = "Yell at coderbus"
@@ -21,7 +21,7 @@
var/weapon_type
var/weapon_name_simple
-/obj/effect/proc_holder/changeling/weapon/try_to_sting(var/mob/user, var/mob/target)
+/datum/action/changeling/weapon/try_to_sting(var/mob/user, var/mob/target)
if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh
qdel(user.l_hand)
if(!silent)
@@ -36,7 +36,7 @@
return
..(user, target)
-/obj/effect/proc_holder/changeling/weapon/sting_action(var/mob/user)
+/datum/action/changeling/weapon/sting_action(var/mob/user)
if(!user.drop_item())
to_chat(user, "The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!")
return
@@ -45,7 +45,7 @@
return W
//Parent to space suits and armor.
-/obj/effect/proc_holder/changeling/suit
+/datum/action/changeling/suit
name = "Organic Suit"
desc = "Go tell a coder if you see this"
helptext = "Yell at coderbus"
@@ -60,7 +60,7 @@
var/recharge_slowdown = 0
var/blood_on_castoff = 0
-/obj/effect/proc_holder/changeling/suit/try_to_sting(var/mob/user, var/mob/target)
+/datum/action/changeling/suit/try_to_sting(var/mob/user, var/mob/target)
var/datum/changeling/changeling = user.mind.changeling
if(!ishuman(user) || !changeling)
return
@@ -84,7 +84,7 @@
return
..(H, target)
-/obj/effect/proc_holder/changeling/suit/sting_action(var/mob/living/carbon/human/user)
+/datum/action/changeling/suit/sting_action(var/mob/living/carbon/human/user)
if(!user.unEquip(user.wear_suit))
to_chat(user, "\the [user.wear_suit] is stuck to your body, you cannot grow a [suit_name_simple] over it!")
return
@@ -107,10 +107,11 @@
/***************************************\
|***************ARM BLADE***************|
\***************************************/
-/obj/effect/proc_holder/changeling/weapon/arm_blade
+/datum/action/changeling/weapon/arm_blade
name = "Arm Blade"
- desc = "We reform one of our arms into a deadly blade."
- helptext = "Cannot be used while in lesser form."
+ desc = "We reform one of our arms into a deadly blade. Costs 25 chemicals."
+ helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form."
+ button_icon_state = "armblade"
chemical_cost = 25
dna_cost = 2
genetic_damage = 10
@@ -132,15 +133,6 @@
throw_range = 0
throw_speed = 0
-/obj/item/melee/arm_blade/New()
- ..()
- if(ismob(loc))
- loc.visible_message("A grotesque blade forms around [loc.name]\'s arm!", "Our arm twists and mutates, transforming it into a deadly blade.", "You hear organic matter ripping and tearing!")
-
-/obj/item/melee/arm_blade/dropped(mob/user)
- user.visible_message("With a sickening crunch, [user] reforms [user.p_their()] blade into an arm!", "We assimilate the blade back into our body.", "You hear organic matter ripping and tearing!")
- . = ..()
-
/obj/item/melee/arm_blade/afterattack(atom/target, mob/user, proximity)
if(!proximity)
return
@@ -177,12 +169,13 @@
|***********COMBAT TENTACLES*************|
\***************************************/
-/obj/effect/proc_holder/changeling/weapon/tentacle
+/datum/action/changeling/weapon/tentacle
name = "Tentacle"
- desc = "We ready a tentacle to grab items or victims with."
+ desc = "We ready a tentacle to grab items or victims with. Costs 10 chemicals."
helptext = "We can use it once to retrieve a distant item. If used on living creatures, the effect depends on the intent: \
Help will simply drag them closer, Disarm will grab whatever they are holding instead of them, Grab will put the victim in our hold after catching it, \
and Harm will stun it, and stab it if we are also holding a sharp weapon. Cannot be used while in lesser form."
+ button_icon_state = "tentacle"
chemical_cost = 10
dna_cost = 2
genetic_damage = 5
@@ -220,7 +213,7 @@
/obj/item/gun/magic/tentacle/suicide_act(mob/user)
user.visible_message("[user] coils [src] tightly around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide.")
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/ammo_casing/magic/tentacle
name = "tentacle"
@@ -350,10 +343,11 @@
/***************************************\
|****************SHIELD*****************|
\***************************************/
-/obj/effect/proc_holder/changeling/weapon/shield
+/datum/action/changeling/weapon/shield
name = "Organic Shield"
- desc = "We reform one of our arms into a hard shield."
- helptext = "Organic tissue cannot resist damage forever, the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
+ desc = "We reform one of our arms into a hard shield. Costs 20 chemicals."
+ helptext = "Organic tissue cannot resist damage forever. The shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
+ button_icon_state = "organic_shield"
chemical_cost = 20
dna_cost = 1
genetic_damage = 12
@@ -363,7 +357,7 @@
weapon_type = /obj/item/shield/changeling
weapon_name_simple = "shield"
-/obj/effect/proc_holder/changeling/weapon/shield/sting_action(var/mob/user)
+/datum/action/changeling/weapon/shield/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling //So we can read the absorbedcount.
if(!changeling)
return
@@ -404,10 +398,11 @@
/***************************************\
|*********SPACE SUIT + HELMET***********|
\***************************************/
-/obj/effect/proc_holder/changeling/suit/organic_space_suit
+/datum/action/changeling/suit/organic_space_suit
name = "Organic Space Suit"
- desc = "We grow an organic suit to protect ourselves from space exposure."
- helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Retreating the suit damages our genomes. Cannot be used in lesser form."
+ desc = "We grow an organic suit to protect ourselves from space exposure. Costs 20 chemicals."
+ helptext = "We must constantly repair our form to make it space proof, reducing chemical production while we are protected. Cannot be used in lesser form."
+ button_icon_state = "organic_suit"
chemical_cost = 20
dna_cost = 2
genetic_damage = 8
@@ -433,7 +428,7 @@
..()
if(ismob(loc))
loc.visible_message("[loc.name]\'s flesh rapidly inflates, forming a bloated mass around [loc.p_their()] body!", "We inflate our flesh, creating a spaceproof suit!", "You hear organic matter ripping and tearing!")
- processing_objects += src
+ START_PROCESSING(SSobj, src)
/obj/item/clothing/suit/space/changeling/process()
if(ishuman(loc))
@@ -451,10 +446,11 @@
/***************************************\
|*****************ARMOR*****************|
\***************************************/
-/obj/effect/proc_holder/changeling/suit/armor
+/datum/action/changeling/suit/armor
name = "Chitinous Armor"
- desc = "We turn our skin into tough chitin to protect us from damage."
- helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form."
+ desc = "We turn our skin into tough chitin to protect us from damage. Costs 25 chemicals."
+ helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form."
+ button_icon_state = "chitinous_armor"
chemical_cost = 25
dna_cost = 2
genetic_damage = 11
@@ -477,7 +473,6 @@
flags_inv = HIDEJUMPSUIT
cold_protection = 0
heat_protection = 0
- species_fit = null
sprite_sheets = null
/obj/item/clothing/suit/armor/changeling/New()
diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm
index 8f4fe0ac394..6e6d69cc1dd 100644
--- a/code/game/gamemodes/changeling/powers/panacea.dm
+++ b/code/game/gamemodes/changeling/powers/panacea.dm
@@ -1,13 +1,14 @@
-/obj/effect/proc_holder/changeling/panacea
+/datum/action/changeling/panacea
name = "Anatomic Panacea"
- desc = "Expels impurifications from our form; curing diseases, removing parasites, sobering us, purging toxins and radiation, and resetting our genetic code completely."
+ desc = "Expels impurifications from our form, curing diseases, removing parasites, sobering us, purging toxins and radiation, and resetting our genetic code completely. Costs 20 chemicals."
helptext = "Can be used while unconscious."
+ button_icon_state = "panacea"
chemical_cost = 20
dna_cost = 1
req_stat = UNCONSCIOUS
//Heals the things that the other regenerative abilities don't.
-/obj/effect/proc_holder/changeling/panacea/sting_action(var/mob/user)
+/datum/action/changeling/panacea/sting_action(var/mob/user)
to_chat(user, "We cleanse impurities from our form.")
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index 83f221a95d3..740d9fb25dc 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -1,11 +1,12 @@
-/obj/effect/proc_holder/changeling/revive
+/datum/action/changeling/revive
name = "Regenerate"
desc = "We regenerate, healing all damage from our form."
+ button_icon_state = "revive"
req_stat = DEAD
always_keep = 1
//Revive from regenerative stasis
-/obj/effect/proc_holder/changeling/revive/sting_action(var/mob/living/carbon/user)
+/datum/action/changeling/revive/sting_action(var/mob/living/carbon/user)
user.setToxLoss(0, FALSE)
user.setOxyLoss(0, FALSE)
user.setCloneLoss(0, FALSE)
@@ -27,8 +28,6 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.restore_blood()
- H.traumatic_shock = 0
- H.shock_stage = 0
H.next_pain_time = 0
H.dna.species.create_organs(H)
// Now that recreating all organs is necessary, the rest of this organ stuff probably
@@ -51,6 +50,8 @@
IO.rejuvenate()
IO.trace_chemicals.Cut()
H.remove_all_embedded_objects()
+ for(var/datum/disease/critical/C in user.viruses)
+ C.cure()
user.status_flags &= ~(FAKEDEATH)
user.updatehealth("revive sting")
user.update_blind_effects()
@@ -62,7 +63,7 @@
user.regenerate_icons()
user.update_revive() //Handle waking up the changeling after the regenerative stasis has completed.
- user.mind.changeling.purchasedpowers -= src
+ src.Remove(user)
user.med_hud_set_status()
user.med_hud_set_health()
feedback_add_details("changeling_powers","CR")
diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm
index 1c60013fbb8..068092dde0d 100644
--- a/code/game/gamemodes/changeling/powers/shriek.dm
+++ b/code/game/gamemodes/changeling/powers/shriek.dm
@@ -1,13 +1,14 @@
-/obj/effect/proc_holder/changeling/resonant_shriek
+/datum/action/changeling/resonant_shriek
name = "Resonant Shriek"
- desc = "Our lungs and vocal chords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded."
- helptext = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors."
+ desc = "Our lungs and vocal cords shift, allowing us to briefly emit a noise that deafens and confuses the weak minded. Costs 30 chemicals."
+ helptext = "Emits a high frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors."
+ button_icon_state = "resonant_shriek"
chemical_cost = 30
dna_cost = 1
req_human = 1
-//A flashy ability, good for crowd control and sewing chaos.
-/obj/effect/proc_holder/changeling/resonant_shriek/sting_action(var/mob/user)
+//A flashy ability, good for crowd control and sowing chaos.
+/datum/action/changeling/resonant_shriek/sting_action(var/mob/user)
for(var/mob/living/M in get_mobs_in_view(4, user))
if(iscarbon(M))
if(!M.mind || !M.mind.changeling)
@@ -28,14 +29,15 @@
feedback_add_details("changeling_powers","RS")
return 1
-/obj/effect/proc_holder/changeling/dissonant_shriek
+/datum/action/changeling/dissonant_shriek
name = "Dissonant Shriek"
- desc = "We shift our vocal cords to release a high-frequency sound that overloads nearby electronics."
+ desc = "We shift our vocal cords to release a high frequency sound that overloads nearby electronics. Costs 30 chemicals."
+ button_icon_state = "dissonant_shriek"
chemical_cost = 30
dna_cost = 1
//A flashy ability, good for crowd control and sewing chaos.
-/obj/effect/proc_holder/changeling/dissonant_shriek/sting_action(var/mob/user)
+/datum/action/changeling/dissonant_shriek/sting_action(var/mob/user)
for(var/obj/machinery/light/L in range(5, usr))
L.on = 1
L.broken()
diff --git a/code/game/gamemodes/changeling/powers/spiders.dm b/code/game/gamemodes/changeling/powers/spiders.dm
index 348924c7d7b..82b2db6ac7b 100644
--- a/code/game/gamemodes/changeling/powers/spiders.dm
+++ b/code/game/gamemodes/changeling/powers/spiders.dm
@@ -1,13 +1,14 @@
-/obj/effect/proc_holder/changeling/spiders
+/datum/action/changeling/spiders
name = "Spread Infestation"
desc = "Our form divides, creating arachnids which will grow into deadly beasts."
helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 5 DNA absorptions."
+ button_icon_state = "spread_infestation"
chemical_cost = 45
dna_cost = 1
req_dna = 5
//Makes some spiderlings. Good for setting traps and causing general trouble.
-/obj/effect/proc_holder/changeling/spiders/sting_action(var/mob/user)
+/datum/action/changeling/spiders/sting_action(var/mob/user)
for(var/i=0, i<2, i++)
var/obj/structure/spider/spiderling/S = new(user.loc)
S.grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/hunter
diff --git a/code/game/gamemodes/changeling/powers/strained_muscles.dm b/code/game/gamemodes/changeling/powers/strained_muscles.dm
index 28884c2653a..10f8a5a5d77 100644
--- a/code/game/gamemodes/changeling/powers/strained_muscles.dm
+++ b/code/game/gamemodes/changeling/powers/strained_muscles.dm
@@ -1,17 +1,18 @@
//Strained Muscles: Temporary speed boost at the cost of rapid damage
//Limited because of hardsuits and such; ideally, used for a quick getaway
-/obj/effect/proc_holder/changeling/strained_muscles
+/datum/action/changeling/strained_muscles
name = "Strained Muscles"
desc = "We evolve the ability to reduce the acid buildup in our muscles, allowing us to move much faster."
helptext = "The strain will make us tired, and we will rapidly become fatigued. Standard weight restrictions, like hardsuits, still apply. Cannot be used in lesser form."
+ button_icon_state = "strained_muscles"
chemical_cost = 0
dna_cost = 1
req_human = 1
var/stacks = 0 //Increments every 5 seconds; damage increases over time
var/enabled = 0 //Whether or not you are a hedgehog
-/obj/effect/proc_holder/changeling/strained_muscles/sting_action(var/mob/living/carbon/user)
+/datum/action/changeling/strained_muscles/sting_action(var/mob/living/carbon/user)
enabled = !enabled
if(enabled)
to_chat(user, "Our muscles tense and strengthen.")
diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm
index 7f0164535c2..e0fc1107729 100644
--- a/code/game/gamemodes/changeling/powers/swap_form.dm
+++ b/code/game/gamemodes/changeling/powers/swap_form.dm
@@ -1,12 +1,13 @@
-/obj/effect/proc_holder/changeling/swap_form
+/datum/action/changeling/swap_form
name = "Swap Forms"
- desc = "We force ourselves into the body of another form, pushing their consciousness into the form we left behind."
+ desc = "We force ourselves into the body of another form, pushing their consciousness into the form we left behind. Costs 40 chemicals."
helptext = "We will bring all our abilities with us, but we will lose our old form DNA in exchange for the new one. The process will seem suspicious to any observers."
+ button_icon_state = "mindswap"
chemical_cost = 40
dna_cost = 1
req_human = 1 //Monkeys can't grab
-/obj/effect/proc_holder/changeling/swap_form/can_sting(var/mob/living/carbon/user)
+/datum/action/changeling/swap_form/can_sting(var/mob/living/carbon/user)
if(!..())
return
var/obj/item/grab/G = user.get_active_hand()
@@ -20,10 +21,12 @@
if(!istype(target) || issmall(target) || NO_DNA in target.dna.species.species_traits)
to_chat(user, "[target] is not compatible with this ability.")
return
+ if(target.mind.changeling)
+ to_chat(user, "We are unable to swap forms with another changeling!")
+ return
return 1
-
-/obj/effect/proc_holder/changeling/swap_form/sting_action(var/mob/living/carbon/user)
+/datum/action/changeling/swap_form/sting_action(var/mob/living/carbon/user)
var/obj/item/grab/G = user.get_active_hand()
var/mob/living/carbon/human/target = G.affecting
var/datum/changeling/changeling = user.mind.changeling
@@ -38,6 +41,10 @@
to_chat(target, "[user] tightens [user.p_their()] grip as a painful sensation invades your body.")
+ var/lingpowers = list()
+ for(var/power in changeling.purchasedpowers)
+ lingpowers += power
+
changeling.absorbed_dna -= changeling.find_dna(user.dna)
changeling.protected_dna -= changeling.find_dna(user.dna)
changeling.absorbedcount -= 1
@@ -55,6 +62,13 @@
user.Paralyse(2)
target.add_language("Changeling")
user.remove_language("Changeling")
+ user.regenerate_icons()
+
+ for(var/power in lingpowers)
+ var/datum/action/changeling/S = power
+ target.mind.changeling.purchasedpowers += S
+ if(istype(S) && S.needs_button)
+ S.Grant(target)
to_chat(target, "Our genes cry out as we swap our [user] form for [target].")
return 1
diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm
index 58afbb73dfe..94bde26674b 100644
--- a/code/game/gamemodes/changeling/powers/tiny_prick.dm
+++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm
@@ -1,10 +1,10 @@
-/obj/effect/proc_holder/changeling/sting
+/datum/action/changeling/sting
name = "Tiny Prick"
desc = "Stabby stabby"
var/sting_icon = null
-/obj/effect/proc_holder/changeling/sting/Click()
- var/mob/user = usr
+/datum/action/changeling/sting/Trigger()
+ var/mob/user = owner
if(!user || !user.mind || !user.mind.changeling)
return
if(!(user.mind.changeling.chosen_sting))
@@ -13,13 +13,13 @@
unset_sting(user)
return
-/obj/effect/proc_holder/changeling/sting/proc/set_sting(var/mob/user)
+/datum/action/changeling/sting/proc/set_sting(var/mob/user)
to_chat(user, "We prepare our sting, use alt+click or middle mouse button on target to sting them.")
user.mind.changeling.chosen_sting = src
user.hud_used.lingstingdisplay.icon_state = sting_icon
user.hud_used.lingstingdisplay.invisibility = 0
-/obj/effect/proc_holder/changeling/sting/proc/unset_sting(var/mob/user)
+/datum/action/changeling/sting/proc/unset_sting(var/mob/user)
to_chat(user, "We retract our sting, we can't sting anyone for now.")
user.mind.changeling.chosen_sting = null
user.hud_used.lingstingdisplay.icon_state = null
@@ -29,7 +29,7 @@
if(mind && mind.changeling && mind.changeling.chosen_sting)
mind.changeling.chosen_sting.unset_sting(src)
-/obj/effect/proc_holder/changeling/sting/can_sting(var/mob/user, var/mob/target)
+/datum/action/changeling/sting/can_sting(var/mob/user, var/mob/target)
if(!..())
return
if(!user.mind.changeling.chosen_sting)
@@ -51,7 +51,7 @@
return
return 1
-/obj/effect/proc_holder/changeling/sting/sting_feedback(var/mob/user, var/mob/target)
+/datum/action/changeling/sting/sting_feedback(var/mob/user, var/mob/target)
if(!target)
return
to_chat(user, "We stealthily sting [target.name].")
@@ -60,18 +60,18 @@
add_attack_logs(user, target, "Unsuccessful sting (changeling)")
return 1
-
-/obj/effect/proc_holder/changeling/sting/transformation
+/datum/action/changeling/sting/transformation
name = "Transformation Sting"
- desc = "We silently sting a human, injecting a retrovirus that forces them to transform."
+ desc = "We silently sting a human, injecting a retrovirus that forces them to transform. Costs 50 chemicals."
helptext = "The victim will transform much like a changeling would. The effects will be obvious to the victim, and the process will damage our genomes."
+ button_icon_state = "sting_transform"
sting_icon = "sting_transform"
chemical_cost = 50
dna_cost = 3
genetic_damage = 100
var/datum/dna/selected_dna = null
-/obj/effect/proc_holder/changeling/sting/transformation/Click()
+/datum/action/changeling/sting/transformation/Trigger()
var/mob/user = usr
var/datum/changeling/changeling = user.mind.changeling
if(changeling.chosen_sting)
@@ -85,7 +85,7 @@
return
..()
-/obj/effect/proc_holder/changeling/sting/transformation/can_sting(var/mob/user, var/mob/target)
+/datum/action/changeling/sting/transformation/can_sting(var/mob/user, var/mob/target)
if(!..())
return
if((HUSK in target.mutations) || (!ishuman(target)))
@@ -98,7 +98,7 @@
return FALSE
return TRUE
-/obj/effect/proc_holder/changeling/sting/transformation/sting_action(var/mob/user, var/mob/target)
+/datum/action/changeling/sting/transformation/sting_action(var/mob/user, var/mob/target)
add_attack_logs(user, target, "Transformation sting (changeling) (new identity is [selected_dna.real_name])")
if(issmall(target))
to_chat(user, "Our genes cry out as we sting [target.name]!")
@@ -114,48 +114,51 @@
feedback_add_details("changeling_powers","TS")
return TRUE
-obj/effect/proc_holder/changeling/sting/extract_dna
+datum/action/changeling/sting/extract_dna
name = "Extract DNA Sting"
- desc = "We stealthily sting a target and extract their DNA."
+ desc = "We stealthily sting a target and extract their DNA. Costs 25 chemicals."
helptext = "Will give you the DNA of your target, allowing you to transform into them."
+ button_icon_state = "sting_extract"
sting_icon = "sting_extract"
chemical_cost = 25
dna_cost = 0
-/obj/effect/proc_holder/changeling/sting/extract_dna/can_sting(var/mob/user, var/mob/target)
+/datum/action/changeling/sting/extract_dna/can_sting(var/mob/user, var/mob/target)
if(..())
return user.mind.changeling.can_absorb_dna(user, target)
-/obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(var/mob/user, var/mob/living/carbon/human/target)
+/datum/action/changeling/sting/extract_dna/sting_action(var/mob/user, var/mob/living/carbon/human/target)
add_attack_logs(user, target, "Extraction sting (changeling)")
if(!(user.mind.changeling.has_dna(target.dna)))
user.mind.changeling.absorb_dna(target, user)
feedback_add_details("changeling_powers","ED")
return 1
-obj/effect/proc_holder/changeling/sting/mute
+datum/action/changeling/sting/mute
name = "Mute Sting"
- desc = "We silently sting a human, completely silencing them for a short time."
+ desc = "We silently sting a human, completely silencing them for a short time. Costs 20 chemicals."
helptext = "Does not provide a warning to the victim that they have been stung, until they try to speak and cannot."
+ button_icon_state = "sting_mute"
sting_icon = "sting_mute"
chemical_cost = 20
dna_cost = 2
-/obj/effect/proc_holder/changeling/sting/mute/sting_action(var/mob/user, var/mob/living/carbon/target)
+/datum/action/changeling/sting/mute/sting_action(var/mob/user, var/mob/living/carbon/target)
add_attack_logs(user, target, "Mute sting (changeling)")
target.AdjustSilence(30)
feedback_add_details("changeling_powers","MS")
return 1
-obj/effect/proc_holder/changeling/sting/blind
+datum/action/changeling/sting/blind
name = "Blind Sting"
- desc = "Temporarily blinds the target."
- helptext = "This sting completely blinds a target for a short time."
+ desc = "We temporarily blind our victim. Costs 25 chemicals."
+ helptext = "This sting completely blinds a target for a short time, and leaves them with blurred vision for a long time."
+ button_icon_state = "sting_blind"
sting_icon = "sting_blind"
chemical_cost = 25
dna_cost = 1
-/obj/effect/proc_holder/changeling/sting/blind/sting_action(var/mob/living/user, var/mob/living/target)
+/datum/action/changeling/sting/blind/sting_action(var/mob/living/user, var/mob/living/target)
add_attack_logs(user, target, "Blind sting (changeling)")
to_chat(target, "Your eyes burn horrifically!")
target.BecomeNearsighted()
@@ -164,15 +167,16 @@ obj/effect/proc_holder/changeling/sting/blind
feedback_add_details("changeling_powers","BS")
return 1
-obj/effect/proc_holder/changeling/sting/LSD
+datum/action/changeling/sting/LSD
name = "Hallucination Sting"
- desc = "Causes terror in the target."
+ desc = "We cause mass terror to our victim. Costs 10 chemicals."
helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung, and the effect occurs after 30 to 60 seconds."
+ button_icon_state = "sting_lsd"
sting_icon = "sting_lsd"
chemical_cost = 10
dna_cost = 1
-/obj/effect/proc_holder/changeling/sting/LSD/sting_action(var/mob/user, var/mob/living/carbon/target)
+/datum/action/changeling/sting/LSD/sting_action(var/mob/user, var/mob/living/carbon/target)
add_attack_logs(user, target, "LSD sting (changeling)")
spawn(rand(300,600))
if(target)
@@ -180,15 +184,16 @@ obj/effect/proc_holder/changeling/sting/LSD
feedback_add_details("changeling_powers","HS")
return 1
-obj/effect/proc_holder/changeling/sting/cryo //Enable when mob cooling is fixed so that frostoil actually makes you cold, instead of mostly just hungry.
+datum/action/changeling/sting/cryo //Enable when mob cooling is fixed so that frostoil actually makes you cold, instead of mostly just hungry.
name = "Cryogenic Sting"
- desc = "We silently sting a human with a cocktail of chemicals that freeze them."
+ desc = "We silently sting our victim with a cocktail of chemicals that freezes them from the inside. Costs 15 chemicals."
helptext = "Does not provide a warning to the victim, though they will likely realize they are suddenly freezing."
+ button_icon_state = "sting_cryo"
sting_icon = "sting_cryo"
chemical_cost = 15
dna_cost = 2
-/obj/effect/proc_holder/changeling/sting/cryo/sting_action(var/mob/user, var/mob/target)
+/datum/action/changeling/sting/cryo/sting_action(var/mob/user, var/mob/target)
add_attack_logs(user, target, "Cryo sting (changeling)")
if(target.reagents)
target.reagents.add_reagent("frostoil", 30)
diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm
index eb50ae0b750..417fbaa052d 100644
--- a/code/game/gamemodes/changeling/powers/transform.dm
+++ b/code/game/gamemodes/changeling/powers/transform.dm
@@ -1,6 +1,7 @@
-/obj/effect/proc_holder/changeling/transform
+/datum/action/changeling/transform
name = "Transform"
- desc = "We take on the appearance and voice of one we have absorbed."
+ desc = "We take on the appearance and voice of one we have absorbed. Costs 5 chemicals."
+ button_icon_state = "transform"
chemical_cost = 5
dna_cost = 0
req_dna = 1
@@ -8,7 +9,7 @@
max_genetic_damage = 3
//Change our DNA to that of somebody we've absorbed.
-/obj/effect/proc_holder/changeling/transform/sting_action(var/mob/living/carbon/human/user)
+/datum/action/changeling/transform/sting_action(var/mob/living/carbon/human/user)
var/datum/changeling/changeling = user.mind.changeling
var/datum/dna/chosen_dna = changeling.select_dna("Select the target DNA: ", "Target DNA")
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 865d8e603d2..9442c319dcb 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -1,11 +1,10 @@
-#define SUMMON_POSSIBILITIES 3
var/global/list/all_cults = list()
/datum/game_mode
var/list/datum/mind/cult = list()
/proc/iscultist(mob/living/M as mob)
- return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult)
+ return istype(M) && M.mind && SSticker && SSticker.mode && (M.mind in SSticker.mode.cult)
/proc/is_convertable_to_cult(datum/mind/mind)
@@ -30,8 +29,8 @@ var/global/list/all_cults = list()
return 1
/proc/is_sacrifice_target(datum/mind/mind)
- if(istype(ticker.mode.name, "cult"))
- var/datum/game_mode/cult/cult_mode = ticker.mode
+ if(SSticker.mode.name == "cult")
+ var/datum/game_mode/cult/cult_mode = SSticker.mode
if(mind == cult_mode.sacrifice_target)
return 1
return 0
@@ -44,7 +43,6 @@ var/global/list/all_cults = list()
required_players = 30
required_enemies = 3
recommended_enemies = 4
- free_golems_disabled = TRUE
var/datum/mind/sacrifice_target = null
var/finished = 0
@@ -121,7 +119,7 @@ var/global/list/all_cults = list()
var/datum/action/innate/cultcomm/C = new()
C.Grant(cult_mind.current)
update_cult_icons_added(cult_mind)
- to_chat(cult_mind.current, "You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].")
+ to_chat(cult_mind.current, "You catch a glimpse of the Realm of [SSticker.cultdat.entity_name], [SSticker.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [SSticker.cultdat.entity_name].")
first_phase()
@@ -135,16 +133,16 @@ var/global/list/all_cults = list()
if("survive")
explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station."
if("convert")
- explanation = "We must increase our influence before we can summon [ticker.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ explanation = "We must increase our influence before we can summon [SSticker.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
if("bloodspill")
- explanation = "We must prepare this place for [ticker.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
+ explanation = "We must prepare this place for [SSticker.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
if("sacrifice")
if(sacrifice_target)
explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune and three acolytes to do so."
else
explanation = "Free objective."
if("eldergod")
- explanation = "Summon [ticker.cultdat.entity_name] by invoking the 'Tear Reality' rune.The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin."
+ explanation = "Summon [SSticker.cultdat.entity_name] by invoking the 'Tear Reality' rune.The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin."
to_chat(cult_mind.current, "Objective #[obj_count]: [explanation]")
cult_mind.memory += "Objective #[obj_count]: [explanation] "
@@ -179,12 +177,13 @@ var/global/list/all_cults = list()
/datum/game_mode/proc/add_cultist(datum/mind/cult_mind) //BASE
if(!istype(cult_mind))
return 0
- var/datum/game_mode/cult/cult_mode = ticker.mode
+ var/datum/game_mode/cult/cult_mode = SSticker.mode
if(!(cult_mind in cult) && is_convertable_to_cult(cult_mind))
cult += cult_mind
cult_mind.current.faction |= "cult"
var/datum/action/innate/cultcomm/C = new()
C.Grant(cult_mind.current)
+ SEND_SOUND(cult_mind.current, 'sound/ambience/antag/bloodcult.ogg')
cult_mind.current.create_attack_log("Has been converted to the cult!")
if(jobban_isbanned(cult_mind.current, ROLE_CULTIST) || jobban_isbanned(cult_mind.current, ROLE_SYNDICATE))
replace_jobbanned_player(cult_mind.current, ROLE_CULTIST)
@@ -313,10 +312,10 @@ var/global/list/all_cults = list()
feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
if("eldergod")
if(!eldergod)
- explanation = "Summon [ticker.cultdat.entity_name]. Success!"
+ explanation = "Summon [SSticker.cultdat.entity_name]. Success!"
feedback_add_details("cult_objective","cult_narsie|SUCCESS")
else
- explanation = "Summon [ticker.cultdat.entity_name]. Fail."
+ explanation = "Summon [SSticker.cultdat.entity_name]. Fail."
feedback_add_details("cult_objective","cult_narsie|FAIL")
if("slaughter")
if(demons_summoned)
@@ -344,10 +343,10 @@ var/global/list/all_cults = list()
if("harvest")
if(harvested > harvest_target)
- explanation = "Offer [harvest_target] humans for [ticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Success!"
+ explanation = "Offer [harvest_target] humans for [SSticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Success!"
feedback_add_details("cult_objective","cult_harvest|SUCCESS")
else
- explanation = "Offer [harvest_target] humans for [ticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Fail!"
+ explanation = "Offer [harvest_target] humans for [SSticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Fail!"
feedback_add_details("cult_objective","cult_harvest|FAIL")
if("hijack")
@@ -374,7 +373,7 @@ var/global/list/all_cults = list()
/datum/game_mode/proc/auto_declare_completion_cult()
- if(cult.len || (ticker && GAMEMODE_IS_CULT))
+ if(cult.len || (SSticker && GAMEMODE_IS_CULT))
var/text = "The cultists were:"
for(var/datum/mind/cultist in cult)
diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm
index 2fbbcdc413d..2586c63bc91 100644
--- a/code/game/gamemodes/cult/cult_comms.dm
+++ b/code/game/gamemodes/cult/cult_comms.dm
@@ -39,10 +39,10 @@
my_message = "Harbringer of the Slaughter: [message]"
else
my_message = "[(ishuman(user) ? "Acolyte" : "Construct")] [user]: [message]"
- for(var/mob/M in GLOB.mob_list)
+ for(var/mob/M in GLOB.player_list)
if(iscultist(M))
to_chat(M, my_message)
- else if(M in GLOB.dead_mob_list)
+ else if((M in GLOB.dead_mob_list) && !isnewplayer(M))
to_chat(M, "(F) [my_message] ")
log_say("(CULT) [message]", user)
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 8b09d4d1577..7e849b54bbe 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -200,7 +200,7 @@
increment = 5
max = 40
prefix = "darkened"
- claw_damage_increase = 2
+ claw_damage_increase = 4
/obj/item/whetstone/cult/update_icon()
icon_state = "cult_sharpener[used ? "_used" : ""]"
@@ -217,7 +217,7 @@
name = "zealot's blindfold"
icon_state = "blindfold"
item_state = "blindfold"
- darkness_view = 8
+ see_in_dark = 8
flash_protect = 1
/obj/item/clothing/glasses/night/cultblind/equipped(mob/user, slot)
@@ -366,9 +366,19 @@
/obj/item/clothing/head/culthood/alt/ghost
flags = NODROP | DROPDEL
-/obj/item/clothing/suit/cultrobes/alt/ghost
+/obj/item/clothing/suit/cultrobesghost
+ name = "ghostly cult robes"
+ desc = "A set of ethreal armored robes worn by the undead followers of a cult."
+ icon_state = "cultrobesalt"
+ item_state = "cultrobesalt"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
+ allowed = list(/obj/item/tome,/obj/item/melee/cultblade)
+ armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0)
+ flags_inv = HIDEJUMPSUIT
+
flags = NODROP | DROPDEL
+
/obj/item/clothing/shoes/cult/ghost
flags = NODROP | DROPDEL
@@ -376,7 +386,7 @@
name = "Cultist Ghost"
uniform = /obj/item/clothing/under/color/black
- suit = /obj/item/clothing/suit/cultrobes/alt/ghost
+ suit = /obj/item/clothing/suit/cultrobesghost
shoes = /obj/item/clothing/shoes/cult/ghost
head = /obj/item/clothing/head/culthood/alt/ghost
r_hand = /obj/item/melee/cultblade/ghost
\ No newline at end of file
diff --git a/code/game/gamemodes/cult/cult_objectives.dm b/code/game/gamemodes/cult/cult_objectives.dm
index beef75e103b..c31ebaf9b84 100644
--- a/code/game/gamemodes/cult/cult_objectives.dm
+++ b/code/game/gamemodes/cult/cult_objectives.dm
@@ -19,10 +19,10 @@
switch(new_objective)
if("convert")
- explanation = "We must increase our influence before we can summon [ticker.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ explanation = "We must increase our influence before we can summon [SSticker.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
if("bloodspill")
spilltarget = 100 + rand(0,GLOB.player_list.len * 3)
- explanation = "We must prepare this place for [ticker.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
+ explanation = "We must prepare this place for [SSticker.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
if("sacrifice")
explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for [sacrifice_target.p_their()] blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual."
@@ -59,8 +59,8 @@
message_admins("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.")
log_admin("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.")
else
- message_admins("There are less than 4 cultists! [ticker.cultdat.entity_name] objective unlocked.")
- log_admin("There are less than 4 cultists! [ticker.cultdat.entity_name] objective unlocked.")
+ message_admins("There are less than 4 cultists! [SSticker.cultdat.entity_name] objective unlocked.")
+ log_admin("There are less than 4 cultists! [SSticker.cultdat.entity_name] objective unlocked.")
gtfo_phase()
if(!sacrificed.len && (new_objective != "sacrifice"))
@@ -76,10 +76,10 @@
switch(new_objective)
if("convert")
- explanation = "We must increase our influence before we can summon [ticker.cultdat.entity_name]. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ explanation = "We must increase our influence before we can summon [SSticker.cultdat.entity_name]. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
if("bloodspill")
spilltarget = 100 + rand(0,GLOB.player_list.len * 3)
- explanation = "We must prepare this place for [ticker.cultdat.entity_title1]'s coming. Spread blood and gibs over [spilltarget] of the Station's floor tiles."
+ explanation = "We must prepare this place for [SSticker.cultdat.entity_title1]'s coming. Spread blood and gibs over [spilltarget] of the Station's floor tiles."
if("sacrifice")
explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for [sacrifice_target.p_their()] blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual."
@@ -111,7 +111,7 @@
if(prob(40))//split the chance of this
objectives += "eldergod"
- explanation = "Summon [ticker.cultdat.entity_name] on the Station via the use of the Tear Reality rune. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin."
+ explanation = "Summon [SSticker.cultdat.entity_name] on the Station via the use of the Tear Reality rune. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin."
else
objectives += "slaughter"
explanation = "Bring the Slaughter via the rune 'Bring forth the slaughter'. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin."
@@ -135,11 +135,11 @@
switch(last_objective)
if("harvest")
- explanation = "[ticker.cultdat.entity_title1] hungers for their first meal of this never-ending day. Offer them [harvest_target] humans in sacrifice."
+ explanation = "[SSticker.cultdat.entity_title1] hungers for their first meal of this never-ending day. Offer them [harvest_target] humans in sacrifice."
if("hijack")
- explanation = "[ticker.cultdat.entity_name] wishes for their troops to start the assault on Centcom immediately. Hijack the escape shuttle and don't let a single non-cultist board it."
+ explanation = "[SSticker.cultdat.entity_name] wishes for their troops to start the assault on Centcom immediately. Hijack the escape shuttle and don't let a single non-cultist board it."
if("massacre")
- explanation = "[ticker.cultdat.entity_name] wants to watch you as you massacre the remaining humans on the station (until less than [massacre_target] humans are left alive)."
+ explanation = "[SSticker.cultdat.entity_name] wants to watch you as you massacre the remaining humans on the station (until less than [massacre_target] humans are left alive)."
for(var/datum/mind/cult_mind in cult)
if(cult_mind)
@@ -163,6 +163,16 @@
possible_sac_targets += player.mind
return possible_sac_targets
+// Handles the updating of sacrifice objectives after the sacrifice target goes to cryo and ghosts
+/datum/game_mode/cult/proc/update_sac_objective(previous_target, previous_role)
+ for(var/datum/mind/cult_mind in cult)
+ if(cult_mind)
+ var/updated_memory = cult_mind.memory
+ updated_memory = replacetext("[cult_mind.memory]", "[previous_target]", "[sacrifice_target]")
+ updated_memory = replacetext("[updated_memory]", "[previous_role]", "[sacrifice_target.assigned_role]")
+ cult_mind.memory = updated_memory
+
+
/datum/game_mode/cult/proc/pick_objective()
var/list/possible_objectives = list()
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index 63e0626f481..c6a6a3b7490 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -169,8 +169,8 @@
var/list/blacklisted_pylon_turfs = typecacheof(list(
/turf/simulated/floor/engine/cult,
/turf/space,
- /turf/unsimulated/floor/lava,
- /turf/unsimulated/floor/chasm,
+ /turf/simulated/floor/plating/lava,
+ /turf/simulated/floor/chasm,
/turf/simulated/wall,
))
@@ -193,11 +193,11 @@ var/list/blacklisted_pylon_turfs = typecacheof(list(
return
/obj/structure/cult/functional/pylon/New()
- processing_objects |= src
+ START_PROCESSING(SSobj, src)
..()
/obj/structure/cult/functional/pylon/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/structure/cult/functional/pylon/process()
@@ -271,7 +271,7 @@ var/list/blacklisted_pylon_turfs = typecacheof(list(
return
return
-/obj/effect/gateway/Crossed(AM as mob|obj)
+/obj/effect/gateway/Crossed(AM as mob|obj, oldloc)
spawn(0)
return
return
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index a16cf76d9f1..fb6bb95a4a8 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -11,7 +11,7 @@
return
/obj/effect/rune/proc/check_icon()
- if(!ticker.mode)//work around for maps with runes and cultdat is not loaded all the way
+ if(!SSticker.mode)//work around for maps with runes and cultdat is not loaded all the way
var/bits = make_bit_triplet()
icon = get_rune(bits)
else
@@ -39,16 +39,16 @@
canbypass = 1
/obj/item/tome/New()
- if(!ticker.mode)
+ if(!SSticker.mode)
icon_state = "tome"
else
- icon_state = ticker.cultdat.tome_icon
+ icon_state = SSticker.cultdat.tome_icon
..()
/obj/item/tome/examine(mob/user)
..()
if(iscultist(user) || user.stat == DEAD)
- to_chat(user, "The scriptures of [ticker.cultdat.entity_title3]. Allows the scribing of runes and access to the knowledge archives of the cult of [ticker.cultdat.entity_name].")
+ to_chat(user, "The scriptures of [SSticker.cultdat.entity_title3]. Allows the scribing of runes and access to the knowledge archives of the cult of [SSticker.cultdat.entity_name].")
to_chat(user, "Striking another cultist with it will purge holy water from them.")
to_chat(user, "Striking a noncultist, however, will sear their flesh.")
@@ -91,7 +91,7 @@
/obj/item/tome/proc/read_tome(mob/user)
var/text = list()
- text += "
Archives of [ticker.cultdat.entity_title1]
"
+ text += "
Archives of [SSticker.cultdat.entity_title1]
"
text += "A rune's name and effects can be revealed by examining the rune.<
"
text += "Rite of Binding This rune is one of the most important runes the cult has, being the only way to create new talismans. A blank sheet of paper must be on top of the rune. After \
@@ -102,7 +102,7 @@
text += "Rite of Enlightenment This rune is critical to the success of the cult. It will allow you to convert normal crew members into cultists. \
To do this, simply place the crew member upon the rune and invoke it. This rune requires two invokers to use. If the target to be converted is mindshielded or a certain assignment, they will \
- be unable to be converted. People [ticker.cultdat.entity_title3] wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like the null rod will not be converted. \
+ be unable to be converted. People [SSticker.cultdat.entity_title3] wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like the null rod will not be converted. \
Successful conversions will produce a tome for the new cultist.
"
text += "Rite of Tribute This rune is necessary to achieve your goals. Simply place any dead creature upon the rune and invoke it (this will not \
@@ -135,12 +135,12 @@
text += "Leeching When invoked, this rune will transfer lifeforce from the victim to the invoker.
"
- text += "Rite of Spectral Manifestation This rune allows you to summon spirits as humanoid fighters. When invoked, a spirit above the rune will be brought to life as a human, wearing nothing, that seeks only to serve you and [ticker.cultdat.entity_title3]. \
+ text += "Rite of Spectral Manifestation This rune allows you to summon spirits as humanoid fighters. When invoked, a spirit above the rune will be brought to life as a human, wearing nothing, that seeks only to serve you and [SSticker.cultdat.entity_title3]. \
However, the spirit's link to reality is fragile - you must remain on top of the rune, and you will slowly take damage. Upon stepping off the rune, all summoned spirits will dissipate, dropping their items to the ground. You may manifest \
multiple spirits with one rune, but you will rapidly take damage in doing so.
"
text += "Ritual of Dimensional Rending This rune is necessary to achieve your goals. On attempting to scribe it, it will produce shields around you and alert everyone you are attempting to scribe it; it takes a very long time to scribe, \
- and does massive damage to the one attempting to scribe it. Invoking it requires 9 invokers and the sacrifice of a specific crewmember, and once invoked, will summon [ticker.cultdat.entity_title3], [ticker.cultdat.entity_name]. \
+ and does massive damage to the one attempting to scribe it. Invoking it requires 9 invokers and the sacrifice of a specific crewmember, and once invoked, will summon [SSticker.cultdat.entity_title3], [SSticker.cultdat.entity_name]. \
This will complete your objectives.
"
text += "Talisman of Teleportation The talisman form of the Teleport rune will transport the invoker to a selected Teleport rune once.
"
@@ -201,12 +201,12 @@
return 1
/obj/item/tome/proc/finale_runes_ok(mob/living/user, obj/effect/rune/rune_to_scribe)
- var/datum/game_mode/cult/cult_mode = ticker.mode
+ var/datum/game_mode/cult/cult_mode = SSticker.mode
var/area/A = get_area(src)
if(GAMEMODE_IS_CULT)
if(!canbypass)//not an admin-tome, check things
if(!cult_mode.narsie_condition_cleared)
- to_chat(user, "There is still more to do before unleashing [ticker.cultdat.entity_name] power!")
+ to_chat(user, "There is still more to do before unleashing [SSticker.cultdat.entity_name] power!")
return 0
if(!cult_mode.eldergod)
to_chat(user, "\"I am already here. There is no need to try to summon me now.\"")
@@ -215,19 +215,19 @@
to_chat(user, "\"We are already here. There is no need to try to summon us now.\"")
return 0
if(!((CULT_ELDERGOD in cult_mode.objectives) || (CULT_SLAUGHTER in cult_mode.objectives)))
- to_chat(user, "[ticker.cultdat.entity_name]'s power does not wish to be unleashed!")
+ to_chat(user, "[SSticker.cultdat.entity_name]'s power does not wish to be unleashed!")
return 0
if(!(A in summon_spots))
- to_chat(user, "[ticker.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(summon_spots)]!")
+ to_chat(user, "[SSticker.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(summon_spots)]!")
return 0
- var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [ticker.cultdat.entity_name]!", "No")
+ var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [SSticker.cultdat.entity_name]!", "No")
if(confirm_final == "No" || confirm_final == null)
to_chat(user, "You decide to prepare further before scribing the rune.")
return 0
else
return 1
else//the game mode is not cult..but we ARE a cultist...ALL ON THE ADMINBUS
- var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [ticker.cultdat.entity_name]!", "No")
+ var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [SSticker.cultdat.entity_name]!", "No")
if(confirm_final == "No" || confirm_final == null)
to_chat(user, "You decide to prepare further before scribing the rune.")
return 0
@@ -236,6 +236,8 @@
/obj/item/tome/proc/scribe_rune(mob/living/user)
var/turf/runeturf = get_turf(user)
+ if(isspaceturf(runeturf))
+ return
var/chosen_keyword
var/obj/effect/rune/rune_to_scribe
var/entered_rune_name
@@ -294,7 +296,7 @@
var/mob/living/carbon/human/H = user
var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
var/obj/item/organ/external/affecting = H.get_organ(ran_zone(dam_zone))
- user.visible_message("[user] cuts open [user.p_their()] [affecting] and begins writing in [user.p_their()] own blood!", "You slice open your [affecting] and begin drawing a sigil of [ticker.cultdat.entity_title3].")
+ user.visible_message("[user] cuts open [user.p_their()] [affecting] and begins writing in [user.p_their()] own blood!", "You slice open your [affecting] and begin drawing a sigil of [SSticker.cultdat.entity_title3].")
user.apply_damage(initial(rune_to_scribe.scribe_damage), BRUTE , affecting)
if(!do_after(user, initial(rune_to_scribe.scribe_delay)-scribereduct, target = get_turf(user)))
for(var/V in shields)
@@ -306,7 +308,7 @@
to_chat(user, "There is already a rune here.")
return
user.visible_message("[user] creates a strange circle in [user.p_their()] own blood.", \
- "You finish drawing the arcane markings of [ticker.cultdat.entity_title3].")
+ "You finish drawing the arcane markings of [SSticker.cultdat.entity_title3].")
for(var/V in shields)
var/obj/machinery/shield/S = V
if(S && !QDELETED(S))
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 1ed5e812989..ad073b4bf54 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -197,7 +197,7 @@ structure_check() searches for nearby cultist structures required for the invoca
..()
for(var/M in invokers)
var/mob/living/L = M
- to_chat(L, "You feel your life force draining. [ticker.cultdat.entity_title3] is displeased.")
+ to_chat(L, "You feel your life force draining. [SSticker.cultdat.entity_title3] is displeased.")
qdel(src)
/mob/proc/null_rod_check() //The null rod, if equipped, will protect the holder from the effects of most runes
@@ -372,12 +372,12 @@ var/list/teleport_runes = list()
new_cultist.visible_message("[new_cultist] writhes in pain as the markings below them glow a bloody red!", \
"AAAAAAAAAAAAAA-")
- ticker.mode.add_cultist(new_cultist.mind, 1)
+ SSticker.mode.add_cultist(new_cultist.mind, 1)
new /obj/item/tome(get_turf(src))
new_cultist.mind.special_role = "Cultist"
to_chat(new_cultist, "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
and something evil takes root.")
- to_chat(new_cultist, "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve [ticker.cultdat.entity_title3] above all else. Bring it back.\
+ to_chat(new_cultist, "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve [SSticker.cultdat.entity_title3] above all else. Bring it back.\
")
//Rite of Tribute: Sacrifices a crew member to Nar-Sie. Places them into a soul shard if they're in their body.
@@ -391,7 +391,7 @@ var/list/teleport_runes = list()
/obj/effect/rune/sacrifice/New()
..()
- cultist_desc = "sacrifices a crew member to [ticker.cultdat.entity_title3]. May place them into a soul shard if their spirit remains in their body."
+ cultist_desc = "sacrifices a crew member to [SSticker.cultdat.entity_title3]. May place them into a soul shard if their spirit remains in their body."
/obj/effect/rune/sacrifice/invoke(var/list/invokers)
if(rune_in_use)
@@ -432,7 +432,7 @@ var/list/teleport_runes = list()
/obj/effect/rune/sacrifice/proc/sac(var/list/invokers, mob/living/T)
var/sacrifice_fulfilled
- var/datum/game_mode/cult/cult_mode = ticker.mode
+ var/datum/game_mode/cult/cult_mode = SSticker.mode
if(T)
if(istype(T, /mob/living/simple_animal/pet/corgi))
for(var/M in invokers)
@@ -445,7 +445,7 @@ var/list/teleport_runes = list()
if(is_sacrifice_target(T.mind))
sacrifice_fulfilled = 1
new /obj/effect/temp_visual/cult/sac(loc)
- if(ticker && ticker.mode && ticker.mode.name == "cult")
+ if(SSticker && SSticker.mode && SSticker.mode.name == "cult")
cult_mode.harvested++
for(var/M in invokers)
@@ -494,9 +494,8 @@ var/list/teleport_runes = list()
/obj/effect/rune/narsie/New()
..()
- cultist_name = "Summon [ticker.cultdat.entity_name]"
- cultist_desc = "tears apart dimensional barriers, calling forth [ticker.cultdat.entity_title3]. Requires 9 invokers."
-
+ cultist_name = "Summon [SSticker.cultdat ? SSticker.cultdat.entity_name : "your god"]"
+ cultist_desc = "tears apart dimensional barriers, calling forth [SSticker.cultdat ? SSticker.cultdat.entity_title3 : "your god"]. Requires 9 invokers."
/obj/effect/rune/narsie/check_icon()
return
@@ -508,7 +507,7 @@ var/list/teleport_runes = list()
if(used)
return
var/mob/living/user = invokers[1]
- var/datum/game_mode/cult/cult_mode = ticker.mode
+ var/datum/game_mode/cult/cult_mode = SSticker.mode
if(!(CULT_ELDERGOD in cult_mode.objectives))
message_admins("[key_name_admin(user)] tried to summonn an eldritch horror when the objective was wrong")
burn_invokers(invokers)
@@ -521,7 +520,7 @@ var/list/teleport_runes = list()
return
if(!cult_mode.eldergod)
for(var/M in invokers)
- to_chat(M, "[ticker.cultdat.entity_name] is already on this plane!")
+ to_chat(M, "[SSticker.cultdat.entity_name] is already on this plane!")
log_game("Summon god rune failed - already summoned")
return
//BEGIN THE SUMMONING
@@ -594,7 +593,7 @@ var/list/teleport_runes = list()
if(used)
return
var/mob/living/user = invokers[1]
- var/datum/game_mode/cult/cult_mode = ticker.mode
+ var/datum/game_mode/cult/cult_mode = SSticker.mode
if(!(CULT_SLAUGHTER in cult_mode.objectives))
message_admins("[key_name_admin(user)] tried to summon demons when the objective was wrong")
burn_invokers(invokers)
@@ -856,10 +855,10 @@ var/list/teleport_runes = list()
/obj/effect/rune/summon/invoke(var/list/invokers)
var/mob/living/user = invokers[1]
var/list/cultists = list()
- for(var/datum/mind/M in ticker.mode.cult)
+ for(var/datum/mind/M in SSticker.mode.cult)
if(!(M.current in invokers) && M.current && M.current.stat != DEAD)
cultists |= M.current
- var/mob/living/cultist_to_summon = input(user, "Who do you wish to call to [src]?", "Followers of [ticker.cultdat.entity_title3]") as null|anything in cultists
+ var/mob/living/cultist_to_summon = input(user, "Who do you wish to call to [src]?", "Followers of [SSticker.cultdat.entity_title3]") as null|anything in cultists
if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
return
if(!cultist_to_summon)
@@ -868,7 +867,7 @@ var/list/teleport_runes = list()
log_game("Summon Cultist rune failed - no target")
return
if(!iscultist(cultist_to_summon))
- to_chat(user, "[cultist_to_summon] is not a follower of [ticker.cultdat.entity_title3]!")
+ to_chat(user, "[cultist_to_summon] is not a follower of [SSticker.cultdat.entity_title3]!")
fail_invoke()
log_game("Summon Cultist rune failed - no target")
return
@@ -977,7 +976,7 @@ var/list/teleport_runes = list()
/obj/effect/rune/manifest/New(loc)
..()
- cultist_desc = "manifests a spirit as a servant of [ticker.cultdat.entity_title3]. The invoker must not move from atop the rune, and will take damage for each summoned spirit."
+ cultist_desc = "manifests a spirit as a servant of [SSticker.cultdat.entity_title3]. The invoker must not move from atop the rune, and will take damage for each summoned spirit."
notify_ghosts("Manifest rune created in [get_area(src)].", ghost_sound='sound/effects/ghost2.ogg', source = src)
@@ -1033,10 +1032,10 @@ var/list/teleport_runes = list()
N.health = 20
N.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
new_human.key = ghost_to_spawn.key
- ticker.mode.add_cultist(new_human.mind, 0)
+ SSticker.mode.add_cultist(new_human.mind, 0)
summoned_guys |= new_human
ghosts++
- to_chat(new_human, "You are a servant of [ticker.cultdat.entity_title3]. You have been made semi-corporeal by the cult of [ticker.cultdat.entity_name], and you are to serve them at all costs.")
+ to_chat(new_human, "You are a servant of [SSticker.cultdat.entity_title3]. You have been made semi-corporeal by the cult of [SSticker.cultdat.entity_name], and you are to serve them at all costs.")
while(user in get_turf(src))
if(user.stat)
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 875e8a3d1e9..08633ef92f4 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -1,4 +1,5 @@
/obj/item/paper/talisman
+ icon = 'icons/obj/paper.dmi'
icon_state = "paper_talisman"
var/cultist_name = "talisman"
var/cultist_desc = "A basic talisman. It serves no purpose."
@@ -7,6 +8,9 @@
var/uses = 1
var/health_cost = 0 //The amount of health taken from the user when invoking the talisman
+/obj/item/paper/talisman/update_icon()//overriding this so the update_icon doesn't turn them into normal looking paper
+ SEND_SIGNAL(src, COMSIG_OBJ_UPDATE_ICON)
+
/obj/item/paper/talisman/examine(mob/user)
if(iscultist(user) || user.stat == DEAD)
to_chat(user, "Name: [cultist_name]")
@@ -41,7 +45,7 @@
invocation = "Ra'sha yoka!"
/obj/item/paper/talisman/malformed/invoke(mob/living/user, successfuluse = 1)
- to_chat(user, "You feel a pain in your head. [ticker.cultdat.entity_title3] is displeased.")
+ to_chat(user, "You feel a pain in your head. [SSticker.cultdat.entity_title3] is displeased.")
if(iscarbon(user))
var/mob/living/carbon/C = user
C.apply_damage(10, BRUTE, "head")
@@ -49,6 +53,7 @@
//Supply Talisman: Has a few unique effects. Granted only to starter cultists.
/obj/item/paper/talisman/supply
cultist_name = "Supply Talisman"
+ icon_state = "supply"
cultist_desc = "A multi-use talisman that can create various objects. Intended to increase the cult's strength early on."
invocation = null
uses = 3
@@ -117,6 +122,7 @@
//Rite of Translocation: Same as rune
/obj/item/paper/talisman/teleport
cultist_name = "Talisman of Teleportation"
+ icon_state = "teleport"
cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword."
invocation = "Sas'so c'arta forbici!"
health_cost = 5
@@ -159,6 +165,7 @@
/obj/item/paper/talisman/summon_tome
cultist_name = "Talisman of Tome Summoning"
+ icon_state = "tome"
cultist_desc = "A one-use talisman that will call an untranslated tome from the archives of a cult."
invocation = "N'ath reth sh'yro eth d'raggathnor!"
health_cost = 1
@@ -173,6 +180,7 @@
/obj/item/paper/talisman/true_sight
cultist_name = "Talisman of Veiling"
+ icon_state = "veil"
cultist_desc = "A multi-use talisman that hides nearby runes. On its second use, will reveal nearby runes."
invocation = "Kla'atu barada nikt'o!"
health_cost = 1
@@ -197,6 +205,7 @@
//Rite of False Truths: Same as rune
/obj/item/paper/talisman/make_runes_fake
cultist_name = "Talisman of Disguising"
+ icon_state = "disguising"
cultist_desc = "A talisman that will make nearby runes appear fake."
invocation = "By'o nar'nar!"
@@ -212,6 +221,7 @@
//Rite of Disruption: Weaker than rune
/obj/item/paper/talisman/emp
cultist_name = "Talisman of Electromagnetic Pulse"
+ icon_state = "emp"
cultist_desc = "A talisman that will cause a moderately-sized electromagnetic pulse."
invocation = "Ta'gh fara'qha fel d'amar det!"
health_cost = 5
@@ -226,6 +236,7 @@
//Rite of Disorientation: Stuns and inhibit speech on a single target for quite some time
/obj/item/paper/talisman/stun
cultist_name = "Talisman of Stunning"
+ icon_state = "stunning"
cultist_desc = "A talisman that will stun and inhibit speech on a single target. To use, attack target directly."
invocation = "Dream sign:Evil sealing talisman!"
health_cost = 10
@@ -271,6 +282,7 @@
//Rite of Arming: Equips cultist armor on the user, where available
/obj/item/paper/talisman/armor
cultist_name = "Talisman of Arming"
+ icon_state = "arming"
cultist_desc = "A talisman that will equip the invoker with cultist equipment if there is a slot to equip it to."
invocation = "N'ath reth sh'yro eth draggathnor!"
@@ -301,6 +313,7 @@
//Talisman of Horrors: Breaks the mind of the victim with nightmarish hallucinations
/obj/item/paper/talisman/horror
cultist_name = "Talisman of Horrors"
+ icon_state = "horror"
cultist_desc = "A talisman that will break the mind of the victim with nightmarish hallucinations."
invocation = "Lo'Nab Na'Dm!"
@@ -316,6 +329,7 @@
//Talisman of Fabrication: Creates a construct shell out of 25 metal sheets.
/obj/item/paper/talisman/construction
cultist_name = "Talisman of Construction"
+ icon_state = "construction"
cultist_desc = "Use this talisman on at least twenty-five metal sheets to create an empty construct shell or on plasteel to make runed metal"
invocation = "Ethra p'ni dedol!"
uses = 25
@@ -360,6 +374,7 @@
//Talisman of Shackling: Applies special cuffs directly from the talisman
/obj/item/paper/talisman/shackle
cultist_name = "Talisman of Shackling"
+ icon_state = "shackling"
cultist_desc = "Use this talisman on a victim to handcuff them with dark bindings."
invocation = "In'totum Lig'abis!"
uses = 4
diff --git a/code/game/gamemodes/devil/devilinfo.dm b/code/game/gamemodes/devil/devilinfo.dm
index e11d31f7d98..419034a9e1f 100644
--- a/code/game/gamemodes/devil/devilinfo.dm
+++ b/code/game/gamemodes/devil/devilinfo.dm
@@ -300,9 +300,9 @@ var/global/list/lawlorify = list (
to_chat(world, "SLOTH, WRATH, GLUTTONY, ACEDIA, ENVY, GREED, PRIDE! FIRES OF HELL AWAKEN!!")
world << 'sound/hallucinations/veryfar_noise.ogg'
sleep(50)
- if(!ticker.mode.devil_ascended)
+ if(!SSticker.mode.devil_ascended)
SSshuttle.emergency.request(null, 0.3)
- ticker.mode.devil_ascended++
+ SSticker.mode.devil_ascended++
/datum/devilinfo/proc/increase_arch_devil()
if(!ascendable)
diff --git a/code/game/gamemodes/devil/imp/imp.dm b/code/game/gamemodes/devil/imp/imp.dm
index b012edc1930..e863eaf1f6a 100644
--- a/code/game/gamemodes/devil/imp/imp.dm
+++ b/code/game/gamemodes/devil/imp/imp.dm
@@ -29,7 +29,7 @@
melee_damage_lower = 10
melee_damage_upper = 15
see_in_dark = 8
- see_invisible = SEE_INVISIBLE_MINIMUM
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
var/boost
var/playstyle_string = "You are an imp, a mischevious creature from hell. You are the lowest rank on the hellish totem pole \
Though you are not obligated to help, perhaps by aiding a higher ranking devil, you might just get a promotion. However, you are incapable \
diff --git a/code/game/gamemodes/devil/objectives.dm b/code/game/gamemodes/devil/objectives.dm
index 5214ab336ec..04d0217b599 100644
--- a/code/game/gamemodes/devil/objectives.dm
+++ b/code/game/gamemodes/devil/objectives.dm
@@ -68,7 +68,7 @@
explanation_text = "Ensure at least [target_amount] mortals are sintouched."
/datum/objective/devil/sintouch/check_completion()
- return target_amount <= ticker.mode.sintouched.len
+ return target_amount <= SSticker.mode.sintouched.len
diff --git a/code/game/gamemodes/devil/true_devil/_true_devil.dm b/code/game/gamemodes/devil/true_devil/_true_devil.dm
index 18058b42279..a6c04c5dcc0 100644
--- a/code/game/gamemodes/devil/true_devil/_true_devil.dm
+++ b/code/game/gamemodes/devil/true_devil/_true_devil.dm
@@ -30,22 +30,6 @@
E.insert()
..()
-
-/mob/living/carbon/true_devil/update_sight()
- if(stat == DEAD)
- sight |= SEE_TURFS
- sight |= SEE_MOBS
- sight |= SEE_OBJS
- see_in_dark = 8
- see_invisible = SEE_INVISIBLE_LEVEL_TWO
- else
- sight = (SEE_TURFS | SEE_OBJS)
- see_in_dark = 2
- see_invisible = SEE_INVISIBLE_LIVING
-
- if(see_override)
- see_invisible = see_override
-
// inventory system could use some love
/mob/living/carbon/true_devil/put_in_hands(obj/item/W)
if(!W)
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 891e377b5e1..aa366415f31 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -27,7 +27,6 @@
var/recommended_enemies = 0
var/newscaster_announcements = null
var/ert_disabled = 0
- var/free_golems_disabled = FALSE
var/uplink_welcome = "Syndicate Uplink Console:"
var/uplink_uses = 20
@@ -75,20 +74,19 @@
display_roundstart_logout_report()
feedback_set_details("round_start","[time2text(world.realtime)]")
- if(ticker && ticker.mode)
- feedback_set_details("game_mode","[ticker.mode]")
+ if(SSticker && SSticker.mode)
+ feedback_set_details("game_mode","[SSticker.mode]")
// if(revdata)
// feedback_set_details("revision","[revdata.revision]")
feedback_set_details("server_ip","[world.internet_address]:[world.port]")
generate_station_goals()
- check_free_golems()
start_state = new /datum/station_state()
start_state.count()
return 1
///process()
///Called by the gameticker
-/datum/game_mode/proc/process()
+/datum/game_mode/process()
return 0
//Called by the gameticker
@@ -228,7 +226,7 @@
// Assemble a list of active players without jobbans.
for(var/mob/new_player/player in GLOB.player_list)
- if(player.client && player.ready)
+ if(player.client && player.ready && player.has_valid_preferences())
if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext))
if(player_old_enough_antag(player.client,role))
players += player
@@ -246,7 +244,7 @@
// If we don't have enough antags, draft people who voted for the round.
if(candidates.len < recommended_enemies)
- for(var/key in round_voters)
+ for(var/key in SSvote.round_voters)
for(var/mob/new_player/player in players)
if(player.ckey == key)
player_draft_log += "[player.key] voted for this round, so we are drafting them."
@@ -357,7 +355,7 @@ proc/display_roundstart_logout_report()
if(L.stat)
if(L.suiciding) //Suicider
msg += "[L.name] ([L.ckey]), the [L.job] (Suicide)\n"
- job_master.FreeRole(L.job)
+ SSjobs.FreeRole(L.job)
message_admins("[key_name_admin(L)], the [L.job] has been freed due to (Early Round Suicide)\n")
continue //Disconnected client
if(L.stat == UNCONSCIOUS)
@@ -383,7 +381,7 @@ proc/display_roundstart_logout_report()
continue //Lolwhat
else
msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n"
- job_master.FreeRole(L.job)
+ SSjobs.FreeRole(L.job)
message_admins("[key_name_admin(L)], the [L.job] has been freed due to (Early Round Ghosted While Alive)\n")
continue //Ghosted while alive
@@ -513,12 +511,6 @@ proc/display_roundstart_logout_report()
var/datum/station_goal/G = V
G.print_result()
-/datum/game_mode/proc/check_free_golems() //check config and gamemode for free golems setting and run the prob to check if the round will have free golems spawned or not
- if((config.unrestricted_free_golems || !free_golems_disabled) && prob(config.prob_free_golems))
- for(var/obj/effect/landmark/free_golem_spawn/L in GLOB.landmarks_list)
- if(isturf(L.loc))
- new /obj/effect/mob_spawn/human/golem/adamantine(L.loc)
-
/datum/game_mode/proc/update_eventmisc_icons_added(datum/mind/mob_mind)
var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_EVENTMISC]
antaghud.join_hud(mob_mind.current)
diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm
index e8a3ff6c981..2b4d095b327 100644
--- a/code/game/gamemodes/heist/heist.dm
+++ b/code/game/gamemodes/heist/heist.dm
@@ -312,5 +312,5 @@ datum/game_mode/proc/auto_declare_completion_heist()
message_admins("[key_name_admin(user)] has pressed the vox win button.")
log_admin("[key_name(user)] pressed the vox win button during a vox round.")
- var/datum/game_mode/heist/H = ticker.mode
+ var/datum/game_mode/heist/H = SSticker.mode
H.win_button_triggered = 1
diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm
index 5e8be8b1229..d1d176f797e 100644
--- a/code/game/gamemodes/intercept_report.dm
+++ b/code/game/gamemodes/intercept_report.dm
@@ -113,10 +113,10 @@
if(man.client && man.client.prefs.nanotrasen_relation == "Opposed")
//don't include suspects who can't possibly be the antag based on their job (no suspecting the captain of being a damned dirty tator)
if(man.mind && man.mind.assigned_role)
- if((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs))
+ if((man.mind.assigned_role in SSticker.mode.protected_jobs) || (man.mind.assigned_role in SSticker.mode.restricted_jobs))
return
//don't include suspects who can't possibly be the antag based on their species (no suspecting the machines of being sneaky changelings)
- if(man.dna.species.name in ticker.mode.protected_species)
+ if(man.dna.species.name in SSticker.mode.protected_species)
return
dudes += man
for(var/i = 0, i < max(GLOB.player_list.len/10,2), i++)
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index 830ae26f3c1..8eeee9e4f2a 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -56,7 +56,7 @@
var/announced = 0
/obj/machinery/doomsday_device/Destroy()
- GLOB.fast_processing -= src
+ STOP_PROCESSING(SSfastprocess, src)
SSshuttle.emergencyNoEscape = 0
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
SSshuttle.emergency.mode = SHUTTLE_DOCKED
@@ -67,7 +67,7 @@
/obj/machinery/doomsday_device/proc/start()
detonation_timer = world.time + default_timer
timing = 1
- GLOB.fast_processing += src
+ START_PROCESSING(SSfastprocess, src)
SSshuttle.emergencyNoEscape = 1
/obj/machinery/doomsday_device/proc/seconds_remaining()
@@ -84,7 +84,7 @@
priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg')
qdel(src)
if(!timing)
- GLOB.fast_processing -= src
+ STOP_PROCESSING(SSfastprocess, src)
return
var/sec_left = seconds_remaining()
if(sec_left <= 0)
@@ -111,7 +111,7 @@
to_chat(L, "The blast wave from [src] tears you atom from atom!")
L.dust()
to_chat(world, "The AI cleansed the station of life with the doomsday device!")
- ticker.force_ending = 1
+ SSticker.force_ending = 1
/datum/AI_Module/large/upgrade_turrets
@@ -496,22 +496,22 @@
return
var/upgradedcams = 0
- see_override = SEE_INVISIBLE_MINIMUM //Night-vision, without which X-ray would be very limited in power.
+ RegisterSignal(src, COMSIG_MOB_UPDATE_SIGHT, .proc/update_upgraded_cameras_sight) //Makes sure the AI has night vision, without which X-ray would be very limited in power.
update_sight()
for(var/obj/machinery/camera/C in cameranet.cameras)
if(C.assembly)
- var/upgraded = 0
+ var/upgraded = FALSE
if(!C.isXRay())
C.upgradeXRay()
//Update what it can see.
cameranet.updateVisibility(C, 0)
- upgraded = 1
+ upgraded = TRUE
if(!C.isEmpProof())
C.upgradeEmpProof()
- upgraded = 1
+ upgraded = TRUE
if(upgraded)
upgradedcams++
@@ -519,6 +519,8 @@
to_chat(src, "OTA firmware distribution complete! Cameras upgraded: [upgradedcams]. Light amplification system online.")
verbs -= /mob/living/silicon/ai/proc/upgrade_cameras
+/mob/living/silicon/ai/proc/update_upgraded_cameras_sight()
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
/datum/AI_Module/large/eavesdrop
module_name = "Enhanced Surveillance"
diff --git a/code/game/gamemodes/miniantags/abduction/abductee_objectives.dm b/code/game/gamemodes/miniantags/abduction/abductee_objectives.dm
index 0d891edb3eb..5db63d3450d 100644
--- a/code/game/gamemodes/miniantags/abduction/abductee_objectives.dm
+++ b/code/game/gamemodes/miniantags/abduction/abductee_objectives.dm
@@ -26,7 +26,7 @@
explanation_text = "Capture"
/datum/objective/abductee/capture/New()
- var/list/jobs = job_master.occupations.Copy()
+ var/list/jobs = SSjobs.occupations.Copy()
for(var/datum/job/J in jobs)
if(J.current_positions < 1)
jobs -= J
diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm
index 587c2b3d476..aab75687df4 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction.dm
@@ -251,14 +251,14 @@
/datum/game_mode/proc/remove_abductor(datum/mind/abductor_mind)
if(abductor_mind in abductors)
- ticker.mode.abductors -= abductor_mind
+ SSticker.mode.abductors -= abductor_mind
abductor_mind.special_role = null
abductor_mind.current.create_attack_log("No longer abductor")
if(issilicon(abductor_mind.current))
to_chat(abductor_mind.current, "You have been turned into a robot! You are no longer an abductor.")
else
to_chat(abductor_mind.current, "You have been brainwashed! You are no longer an abductor.")
- ticker.mode.update_abductor_icons_removed(abductor_mind)
+ SSticker.mode.update_abductor_icons_removed(abductor_mind)
/datum/game_mode/proc/update_abductor_icons_added(datum/mind/alien_mind)
var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_ABDUCTOR]
diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
index 92ac300cc00..f6bed7b539f 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
@@ -23,7 +23,6 @@
var/datum/icon_snapshot/disguise
var/stealth_armor = list(melee = 15, bullet = 15, laser = 15, energy = 15, bomb = 15, bio = 15, rad = 15)
var/combat_armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 50, rad = 50)
- species_fit = null
sprite_sheets = null
/obj/item/clothing/suit/armor/abductor/vest/proc/toggle_nodrop()
@@ -110,15 +109,15 @@
M.SetStunned(0)
M.SetWeakened(0)
combat_cooldown = 0
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/clothing/suit/armor/abductor/vest/process()
combat_cooldown++
if(combat_cooldown==initial(combat_cooldown))
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
/obj/item/clothing/suit/armor/abductor/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
for(var/obj/machinery/abductor/console/C in GLOB.machines)
if(C.vest == src)
C.vest = null
diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm
index 8f058a872e6..2b0162829e1 100644
--- a/code/game/gamemodes/miniantags/abduction/gland.dm
+++ b/code/game/gamemodes/miniantags/abduction/gland.dm
@@ -320,69 +320,6 @@
for(var/mob/living/carbon/human/H in oview(3,owner)) //Blood decals for simple animals would be neat. aka Carp with blood on it.
H.add_mob_blood(owner)
-/obj/item/organ/internal/heart/gland/bodysnatch
- cooldown_low = 600
- cooldown_high = 600
- human_only = 1
- uses = 1
-
-/obj/item/organ/internal/heart/gland/bodysnatch/activate()
- to_chat(owner, "You feel something moving around inside you...")
- //spawn cocoon with clone greytide snpc inside
- if(ishuman(owner))
- var/obj/effect/cocoon/abductor/C = new (get_turf(owner))
- C.Copy(owner)
- C.Start()
- owner.adjustBruteLoss(40)
- owner.add_splatter_floor()
-
-/obj/effect/cocoon/abductor
- name = "slimy cocoon"
- desc = "Something is moving inside."
- icon = 'icons/effects/effects.dmi'
- icon_state = "cocoon_large3"
- color = rgb(10,120,10)
- density = 1
- var/hatch_time = 0
-
-/obj/effect/cocoon/abductor/proc/Copy(mob/living/carbon/human/H)
- var/mob/living/carbon/human/interactive/greytide/clone = new(src)
- var/datum/dna/owner_dna = H.dna
- clone.rename_character(clone.name, owner_dna.real_name)
- clone.set_species(owner_dna.species.type)
- clone.dna = owner_dna.Clone()
- clone.body_accessory = H.body_accessory
- domutcheck(clone)
-
- for(var/obj/item/I in clone)
- if(istype(I, /obj/item/implant))
- continue
- if(istype(I, /obj/item/organ))
- continue
- qdel(I)
-
- //There's no define for this / get all items ?
- var/list/slots = list(slot_back,slot_w_uniform,slot_wear_suit,\
- slot_wear_mask,slot_head,slot_shoes,slot_gloves,slot_l_ear,slot_r_ear,\
- slot_glasses,slot_belt,slot_s_store,slot_l_store,slot_r_store,slot_wear_id,slot_wear_pda)
-
- for(var/slot in slots)
- var/obj/item/I = H.get_item_by_slot(slot)
- if(I)
- clone.equip_to_slot_or_del(new I.type(clone), slot)
-
-/obj/effect/cocoon/abductor/proc/Start()
- hatch_time = world.time + 600
- processing_objects.Add(src)
-
-/obj/effect/cocoon/abductor/process()
- if(world.time > hatch_time)
- processing_objects.Remove(src)
- for(var/mob/M in contents)
- src.visible_message("[src] hatches!")
- M.forceMove(get_turf(src))
- qdel(src)
-
/obj/item/organ/internal/heart/gland/plasma
cooldown_low = 1200
diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm
index 53969aaf7d1..db6f07c1d24 100644
--- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm
+++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm
@@ -140,14 +140,14 @@
to_chat(H, "You can't remember how you got here...")
var/objtype = pick(subtypesof(/datum/objective/abductee/))
var/datum/objective/abductee/O = new objtype()
- ticker.mode.abductees += H.mind
+ SSticker.mode.abductees += H.mind
H.mind.objectives += O
var/obj_count = 1
to_chat(H, "Your current objectives:")
for(var/datum/objective/objective in H.mind.objectives)
to_chat(H, "Objective #[obj_count]: [objective.explanation_text]")
obj_count++
- ticker.mode.update_abductor_icons_added(H.mind)
+ SSticker.mode.update_abductor_icons_added(H.mind)
for(var/obj/item/organ/internal/heart/gland/G in H.internal_organs)
G.Start()
diff --git a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
index f7ff2864608..697d173716a 100644
--- a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
+++ b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
@@ -7,7 +7,8 @@
var/turf/teleport_target
/obj/machinery/abductor/pad/proc/Warp(mob/living/target)
- target.Move(src.loc)
+ if(!target.buckled)
+ target.forceMove(get_turf(src))
/obj/machinery/abductor/pad/proc/Send()
if(teleport_target == null)
diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm
index 34d1f64f0d0..fa797ac929b 100644
--- a/code/game/gamemodes/miniantags/borer/borer.dm
+++ b/code/game/gamemodes/miniantags/borer/borer.dm
@@ -32,7 +32,7 @@
return FALSE
return B.host.say_understands(other, speaking)
-/mob/living/captive_brain/emote(var/message)
+/mob/living/captive_brain/emote(act, m_type = 1, message = null, force)
return
/mob/living/captive_brain/resist()
@@ -157,7 +157,7 @@
if(!istype(S.speaking, /datum/language/corticalborer) && loc == host && !talk_inside_host)
to_chat(src, "You've disabled audible speech while inside a host! Re-enable it under the borer tab, or stick to borer communications.")
return
-
+
. = ..()
/mob/living/simple_animal/borer/verb/Communicate()
@@ -475,7 +475,7 @@
set category = "Borer"
set name = "Dominate Victim"
set desc = "Freeze the limbs of a potential host with supernatural fear."
-
+
if(world.time - used_dominate < 150)
to_chat(src, "You cannot use that ability again so soon.")
return
@@ -487,22 +487,22 @@
if(stat)
to_chat(src, "You cannot do that in your current state.")
return
-
+
if(attempting_to_dominate)
to_chat(src, "You're already targeting someone!")
return
-
+
var/list/choices = list()
for(var/mob/living/carbon/C in view(3,src))
if(C.stat != DEAD)
choices += C
-
+
if(world.time - used_dominate < 300)
to_chat(src, "You cannot use that ability again so soon.")
return
-
+
attempting_to_dominate = TRUE
-
+
var/mob/living/carbon/M = input(src,"Who do you wish to dominate?") in null|choices
if(!M)
@@ -519,8 +519,8 @@
if(incapacitated())
attempting_to_dominate = FALSE
- return
-
+ return
+
if(get_dist(src, M) > 7) //to avoid people remotely doing from across the map etc, 7 is the default view range
to_chat(src, "You're too far away!")
attempting_to_dominate = FALSE
@@ -760,10 +760,9 @@
to_chat(src, "Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body.")
visible_message("[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!")
B.chemicals -= 100
-
- new /obj/effect/decal/cleanable/vomit(get_turf(src))
- playsound(loc, 'sound/effects/splat.ogg', 50, 1)
- new /mob/living/simple_animal/borer(get_turf(src),B.generation + 1)
+ var/turf/T = get_turf(src)
+ T.add_vomit_floor()
+ new /mob/living/simple_animal/borer(T, B.generation + 1)
else
to_chat(src, "You need 100 chemicals to reproduce!")
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index 32abeaac947..fb3c10e25ec 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -1,5 +1,5 @@
////Deactivated swarmer shell////
-/obj/item/unactivated_swarmer
+/obj/item/deactivated_swarmer
name = "unactivated swarmer"
desc = "A currently unactivated swarmer. Swarmers can self activate at any time, it would be wise to immediately dispose of this."
icon = 'icons/mob/swarmer.dmi'
@@ -7,69 +7,49 @@
origin_tech = "bluespace=4;materials=4;programming=7"
materials = list(MAT_METAL=100, MAT_GLASS=400)
-/obj/item/unactivated_swarmer/New()
- if(!crit_fail)
- notify_ghosts("An unactivated swarmer has been created in [get_area(src)]!", enter_link = "(Click to enter)", source = src, action = NOTIFY_ATTACK)
- ..()
+/obj/effect/mob_spawn/swarmer
+ name = "unactivated swarmer"
+ desc = "A currently unactivated swarmer. Swarmers can self activate at any time, it would be wise to immediately dispose of this."
+ icon = 'icons/mob/swarmer.dmi'
+ icon_state = "swarmer_unactivated"
+ density = FALSE
+ anchored = FALSE
-/obj/item/unactivated_swarmer/Topic(href, href_list)
- if(..())
- return 1
- if(href_list["ghostjoin"])
- var/mob/dead/observer/ghost = usr
- if(istype(ghost))
- attack_ghost(ghost)
+ mob_type = /mob/living/simple_animal/hostile/swarmer
+ mob_name = "a swarmer"
+ death = FALSE
+ roundstart = FALSE
+ flavour_text = {"
+ You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate.
+ Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful.
+ Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.
+ Objectives:
+ 1. Consume resources and replicate until there are no more resources left.
+ 2. Ensure that this location is fit for invasion at a later date; do not perform actions that would render it dangerous or inhospitable.
+ 3. Biological resources will be harvested at a later date; do not harm them.
+ "}
-/obj/item/unactivated_swarmer/attackby(obj/item/W, mob/user, params)
- ..()
- if(istype(W, /obj/item/screwdriver) && !crit_fail)
+/obj/effect/mob_spawn/swarmer/Initialize(mapload)
+ . = ..()
+ var/area/A = get_area(src)
+ if(A)
+ notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
+
+/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user)
+ . = ..()
+ if(.)
+ return
+ to_chat(user, "Picking up the swarmer may cause it to activate. You should be careful about this.")
+
+/obj/effect/mob_spawn/swarmer/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/screwdriver) && user.a_intent != INTENT_HARM)
user.visible_message("[usr.name] deactivates [src].",
"After some fiddling, you find a way to disable [src]'s power source.",
"You hear clicking.")
- name = "deactivated swarmer"
- desc = "A shell of swarmer that was completely powered down. It can no longer activate itself."
- crit_fail = 1
-
-/obj/item/unactivated_swarmer/attack_ghost(mob/user as mob)
-
- if(crit_fail)
- to_chat(user, "This swarmer shell is completely depowered. You cannot activate it.")
- return
-
- if(jobban_isbanned(user, "Syndicate"))
- to_chat(user, "You are banned from antagonists!")
- return
-
- if(cannotPossess(user))
- to_chat(user, "Upon using the antagHUD you forfeited the ability to join the round.")
- return
-
- var/be_swarmer = alert("Become a swarmer? (Warning, You can no longer be cloned!)",,"Yes","No")
- if(be_swarmer == "No")
- return
-
- if(crit_fail)//in case it depowers while ghost is looking at yes/no
- to_chat(user, "This swarmer shell is completely depowered. You cannot activate it.")
- return
-
- if(QDELETED(src))
- to_chat(user, "Swarmer has been occupied by someone else.")
- return
- var/mob/living/simple_animal/hostile/swarmer/S = new /mob/living/simple_animal/hostile/swarmer(get_turf(loc))
- S.key = user.key
- qdel(src)
-
-/obj/item/unactivated_swarmer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
- if(S.resources + 50 > S.max_resources)
- to_chat(S, "We have too many resources to reconsume this shell. Aborting.")
+ new /obj/item/deactivated_swarmer(get_turf(src))
+ qdel(src)
else
- ..()
- S.resources += 49 //refund the whole thing
-
-/obj/item/unactivated_swarmer/deactivated
- name = "deactivated swarmer"
- desc = "A shell of swarmer that was completely powered down. It no longer can activate itself."
- crit_fail = 1
+ return ..()
////The Mob itself////
@@ -101,10 +81,12 @@
attack_sound = 'sound/effects/empulse.ogg'
friendly = "pinches"
speed = 0
+ a_intent = INTENT_HARM
+ can_change_intents = 0
faction = list("swarmer")
projectiletype = /obj/item/projectile/beam/disabler
pass_flags = PASSTABLE
- mob_size = MOB_SIZE_TINY
+ mob_size = MOB_SIZE_SMALL
ventcrawler = 2
ranged = 1
light_color = LIGHT_COLOR_CYAN
@@ -193,136 +175,188 @@
/atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
+ return TRUE
/obj/item/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.Integrate(src)
+ return FALSE
+
+/atom/movable/swarmer_act()
+ if(!simulated)
+ return FALSE
+ return ..()
+
+/obj/effect/swarmer_act()
+ return FALSE
+
+/obj/effect/decal/cleanable/robot_debris/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+ qdel(src)
+ return TRUE
/obj/item/gun/swarmer_act()//Stops you from eating the entire armory
- return
+ return FALSE
/turf/simulated/floor/swarmer_act()//ex_act() on turf calls it on its contents, this is to prevent attacking mobs by DisIntegrate()'ing the floor
- return
+ return FALSE
/obj/machinery/atmospherics/swarmer_act()
- return
+ return FALSE
/obj/structure/disposalpipe/swarmer_act()
- return
+ return FALSE
/obj/machinery/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DismantleMachine(src)
+ return TRUE
/obj/machinery/light/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
+ return TRUE
/obj/machinery/door/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
+ return TRUE
/obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
toggle_cam(S, 0)
+ return TRUE
/obj/structure/particle_accelerator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.")
+ return FALSE
/obj/machinery/particle_accelerator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) // Since the console is still parented to this
to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.")
+ return FALSE
/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
if(!active)
S.DisIntegrate(src)
- return
+ return TRUE
to_chat(S, "An inhospitable area may be created as a result of destroying this object. Aborting.")
+ return FALSE
/obj/machinery/gravity_generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
+ return TRUE
/obj/machinery/vending/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//It's more visually interesting than dismantling the machine
S.DisIntegrate(src)
+ return TRUE
/obj/machinery/turretid/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
+ return TRUE
/obj/machinery/chem_dispenser/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "The volatile chemicals in this machine would destroy us. Aborting.")
+ return FALSE
/obj/machinery/nuclearbomb/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This device's destruction would result in the extermination of everything in the area. Aborting.")
+ return FALSE
/obj/effect/rune/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "Searching... sensor malfunction! Target lost. Aborting.")
+ return FALSE
/obj/structure/reagent_dispensers/fueltank/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "Destroying this object would cause a chain reaction. Aborting.")
+ return FALSE
/obj/structure/cable/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.")
+ return FALSE
/obj/machinery/portable_atmospherics/canister/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "An inhospitable area may be created as a result of destroying this object. Aborting.")
+ return FALSE
/obj/machinery/telecomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.")
+ return FALSE
/obj/machinery/message_server/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.")
+ return FALSE
/obj/machinery/blackbox_recorder/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This machine has recorded large amounts of data on this structure and its inhabitants, it will be a useful resource to our masters in the future. Aborting. ")
+ return FALSE
/obj/machinery/power/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.")
+ return FALSE
/obj/machinery/gateway/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This bluespace source will be important to us later. Aborting.")
+ return FALSE
/obj/machinery/cryopod/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This cryogenic sleeper should be preserved, it will be a useful resource to our masters in the future. Aborting.")
+ return FALSE
/obj/structure/cryofeed/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This cryogenic feed should be preserved, it will be a useful resource to our masters in the future. Aborting.")
+ return FALSE
/obj/machinery/computer/cryopod/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This cryopod control computer should be preserved, it contains useful items and information about the inhabitants. Aborting.")
+ return FALSE
/turf/simulated/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
for(var/turf/T in range(1, src))
if(istype(T, /turf/space) || istype(T.loc, /area/space) || istype(T, /turf/simulated/floor/plating/airless))
to_chat(S, "Destroying this object has the potential to cause a hull breach. Aborting.")
- return
- ..()
+ return FALSE
+ return ..()
/obj/structure/window/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
for(var/turf/T in range(1, src))
if(istype(T, /turf/space) || istype(T.loc, /area/space))
to_chat(S, "Destroying this object has the potential to cause a hull breach. Aborting.")
- return
- ..()
+ return FALSE
+ return ..()
/obj/item/stack/cable_coil/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//Wiring would be too effective as a resource
to_chat(S, "This object does not contain enough materials to work with.")
+ return FALSE
/obj/item/circuitboard/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This object does not contain enough materials to work with.")
+ return FALSE
/obj/machinery/porta_turret/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "Attempting to dismantle this machine would result in an immediate counterattack. Aborting.")
+ return FALSE
/obj/spacepod/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "Destroying this vehicle would destroy us. Aborting.")
+ return FALSE
/obj/machinery/clonepod/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
if(occupant)
to_chat(S, "Destroying this machine while it is occupied would result in biological and sentient resources to be harmed. Aborting.")
- return
- ..()
+ return FALSE
+ return ..()
/mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisperseTarget(src)
+ return TRUE
/mob/living/carbon/slime/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This biological resource is somehow resisting our bluespace transceiver. Aborting.")
+ return FALSE
+/obj/structure/lattice/catwalk/swarmer_catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ to_chat(S, "We have created these for our own benefit. Aborting.")
+ return FALSE
+
+/obj/structure/shuttle/engine/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ to_chat(S, "This shuttle may be important to us later. Aborting.")
+ return FALSE
////END CTRL CLICK FOR SWARMERS////
@@ -391,6 +425,11 @@
break
return
+/mob/living/simple_animal/hostile/swarmer/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
+ if(!tesla_shock)
+ return FALSE
+ return ..()
+
/mob/living/simple_animal/hostile/swarmer/proc/DismantleMachine(var/obj/machinery/target)
do_attack_animation(target)
to_chat(src, "We begin to dismantle this machine. We will need to be uninterrupted.")
@@ -506,12 +545,12 @@
light_color = LIGHT_COLOR_CYAN
health = 10
-/obj/structure/swarmer/trap/Crossed(var/atom/movable/AM)
+/obj/structure/swarmer/trap/Crossed(var/atom/movable/AM, oldloc)
if(isliving(AM))
var/mob/living/L = AM
if(!istype(L, /mob/living/simple_animal/hostile/swarmer))
playsound(loc,'sound/effects/snap.ogg',50, 1, -1)
- L.electrocute_act(0, src, 1, 1)
+ L.electrocute_act(0, src, 1, TRUE, TRUE)
if(isrobot(L) || L.isSynthetic())
L.Weaken(5)
qdel(src)
@@ -567,9 +606,13 @@
to_chat(src, "This is not a suitable location for replicating ourselves. We need more room.")
return
if(do_mob(src, src, 100))
- if(Fabricate(/obj/item/unactivated_swarmer, 50))
+ var/createtype = SwarmerTypeToCreate()
+ if(createtype && Fabricate(createtype, 50))
playsound(loc,'sound/items/poster_being_created.ogg',50, 1, -1)
+/mob/living/simple_animal/hostile/swarmer/proc/SwarmerTypeToCreate()
+ return /obj/effect/mob_spawn/swarmer
+
/mob/living/simple_animal/hostile/swarmer/proc/RepairSelf()
set name = "Self Repair"
set category = "Swarmer"
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
index d611092bb2b..0d5ba13d682 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
@@ -15,7 +15,7 @@
return 0
if(!the_gateway)
return 0
- new /obj/item/unactivated_swarmer(get_turf(the_gateway))
+ new /obj/effect/mob_spawn/swarmer(get_turf(the_gateway))
/datum/event/spawn_swarmer/proc/find_swarmer()
diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm
index d344074a331..2b6040ed8b6 100644
--- a/code/game/gamemodes/miniantags/guardian/guardian.dm
+++ b/code/game/gamemodes/miniantags/guardian/guardian.dm
@@ -12,6 +12,7 @@
icon_dead = "magicOrange"
speed = 0
a_intent = INTENT_HARM
+ can_change_intents = 0
stop_automated_movement = 1
floating = 1
attack_sound = 'sound/weapons/punch1.ogg'
@@ -60,9 +61,9 @@
/mob/living/simple_animal/hostile/guardian/Life(seconds, times_fired) //Dies if the summoner dies
..()
if(summoner)
- if(summoner.stat == DEAD)
+ if(summoner.stat == DEAD || (!summoner.check_death_method() && summoner.health <= HEALTH_THRESHOLD_DEAD))
to_chat(src, "Your summoner has died!")
- visible_message("The [src] dies along with its user!")
+ visible_message("[src] dies along with its user!")
ghostize()
qdel(src)
snapback()
@@ -85,6 +86,18 @@
forceMove(summoner.loc) //move to summoner's tile, don't recall
new /obj/effect/temp_visual/guardian/phase(loc)
+/mob/living/simple_animal/hostile/guardian/proc/is_deployed()
+ return loc != summoner
+
+/mob/living/simple_animal/hostile/guardian/AttackingTarget()
+ if(!is_deployed() && a_intent == INTENT_HARM)
+ to_chat(src, "You must be manifested to attack!")
+ return FALSE
+ else if(!is_deployed() && a_intent == INTENT_HELP)
+ return FALSE
+ else
+ return ..()
+
/mob/living/simple_animal/hostile/guardian/Move() //Returns to summoner if they move out of range
..()
snapback()
@@ -102,7 +115,7 @@
if(summoner)
var/resulthealth
if(iscarbon(summoner))
- resulthealth = round((abs(config.health_threshold_dead - summoner.health) / abs(config.health_threshold_dead - summoner.maxHealth)) * 100)
+ resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - summoner.health) / abs(HEALTH_THRESHOLD_DEAD - summoner.maxHealth)) * 100)
else
resulthealth = round((summoner.health / summoner.maxHealth) * 100)
if(hud_used)
@@ -149,11 +162,12 @@
if(!summoner) return
if(loc == summoner)
forceMove(get_turf(summoner))
+ new /obj/effect/temp_visual/guardian/phase(loc)
src.client.eye = loc
cooldown = world.time + 30
/mob/living/simple_animal/hostile/guardian/proc/Recall(forced = FALSE)
- if(cooldown > world.time && !forced)
+ if(!summoner || loc == summoner || (cooldown > world.time && !forced))
return
if(!summoner) return
new /obj/effect/temp_visual/guardian/phase/out(get_turf(src))
diff --git a/code/game/gamemodes/miniantags/guardian/types/bomb.dm b/code/game/gamemodes/miniantags/guardian/types/bomb.dm
index 2908888839a..fbe4458693f 100644
--- a/code/game/gamemodes/miniantags/guardian/types/bomb.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/bomb.dm
@@ -8,6 +8,13 @@
tech_fluff_string = "Boot sequence complete. Explosive modules active. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of stealthily booby trapping items."
var/bomb_cooldown = 0
+ var/default_bomb_cooldown = 20 SECONDS
+
+/mob/living/simple_animal/hostile/guardian/bomb/Stat()
+ ..()
+ if(statpanel("Status"))
+ if(bomb_cooldown >= world.time)
+ stat(null, "Bomb Cooldown Remaining: [max(round((bomb_cooldown - world.time)*0.1, 0.1), 0)] seconds")
/mob/living/simple_animal/hostile/guardian/bomb/AltClickOn(atom/movable/A)
if(!istype(A))
@@ -21,11 +28,11 @@
to_chat(src, "Success! Bomb on [A] armed!")
if(summoner)
to_chat(summoner, "Your guardian has primed [A] to explode!")
- bomb_cooldown = world.time + 200
+ bomb_cooldown = world.time + default_bomb_cooldown
B.spawner = src
B.disguise (A)
else
- to_chat(src, "Your powers are on cooldown! You must wait 20 seconds between bombs.")
+ to_chat(src, "Your power is on cooldown! You must wait another [max(round((bomb_cooldown - world.time)*0.1, 0.1), 0)] seconds before you can place next bomb.")
/obj/item/guardian_bomb
name = "bomb"
diff --git a/code/game/gamemodes/miniantags/guardian/types/fire.dm b/code/game/gamemodes/miniantags/guardian/types/fire.dm
index f10a94793b5..0c5052f48bd 100644
--- a/code/game/gamemodes/miniantags/guardian/types/fire.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/fire.dm
@@ -1,5 +1,4 @@
/mob/living/simple_animal/hostile/guardian/fire
- a_intent = INTENT_HELP
melee_damage_lower = 10
melee_damage_upper = 10
attack_sound = 'sound/items/welder.ogg'
@@ -43,7 +42,7 @@
do_teleport(M, M, 10)
new /obj/effect/temp_visual/guardian/phase/out(get_turf(M))
-/mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj)
+/mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj, oldloc)
..()
collision_ignite(AM)
diff --git a/code/game/gamemodes/miniantags/guardian/types/healer.dm b/code/game/gamemodes/miniantags/guardian/types/healer.dm
index 6c784e1ee0a..d9be543f7e2 100644
--- a/code/game/gamemodes/miniantags/guardian/types/healer.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/healer.dm
@@ -1,5 +1,4 @@
/mob/living/simple_animal/hostile/guardian/healer
- a_intent = INTENT_HARM
friendly = "heals"
speed = 0
melee_damage_lower = 15
@@ -10,6 +9,7 @@
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of mending wounds and travelling via bluespace."
var/turf/simulated/floor/beacon
var/beacon_cooldown = 0
+ var/default_beacon_cooldown = 300 SECONDS
var/toggle = FALSE
var/heal_cooldown = 0
@@ -21,7 +21,6 @@
icon_state = "seal"
attacktext = "slaps"
speak_emote = list("barks")
- a_intent = INTENT_HARM
friendly = "heals"
speed = 0
melee_damage_lower = 0
@@ -37,6 +36,12 @@
var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED]
medsensor.add_hud_to(src)
+/mob/living/simple_animal/hostile/guardian/healer/Stat()
+ ..()
+ if(statpanel("Status"))
+ if(beacon_cooldown >= world.time)
+ stat(null, "Bluespace Beacon Cooldown Remaining: [max(round((beacon_cooldown - world.time)*0.1, 0.1), 0)] seconds")
+
/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
..()
if(toggle == TRUE)
@@ -60,6 +65,7 @@
if(loc == summoner)
if(toggle)
a_intent = INTENT_HARM
+ hud_used.action_intent.icon_state = a_intent;
speed = 0
damage_transfer = 0.7
if(adminseal)
@@ -70,6 +76,7 @@
toggle = FALSE
else
a_intent = INTENT_HELP
+ hud_used.action_intent.icon_state = a_intent;
speed = 1
damage_transfer = 1
if(adminseal)
@@ -81,9 +88,8 @@
else
to_chat(src, "You have to be recalled to toggle modes!")
-
/mob/living/simple_animal/hostile/guardian/healer/verb/Beacon()
- set name = "Place Bluespsace Beacon"
+ set name = "Place Bluespace Beacon"
set category = "Guardian"
set desc = "Mark a floor as your beacon point, allowing you to warp targets to it. Your beacon will not work in unfavorable atmospheric conditions."
if(beacon_cooldown < world.time)
@@ -98,10 +104,10 @@
if(beacon)
beacon.ChangeTurf(/turf/simulated/floor/plating)
beacon = F
- beacon_cooldown = world.time+3000
+ beacon_cooldown = world.time + default_beacon_cooldown
else
- to_chat(src, "Your power is on cooldown. You must wait five minutes between placing beacons.")
+ to_chat(src, "Your power is on cooldown! You must wait another [max(round((beacon_cooldown - world.time)*0.1, 0.1), 0)] seconds before you can place another beacon.")
/mob/living/simple_animal/hostile/guardian/healer/AltClickOn(atom/movable/A)
if(!istype(A))
diff --git a/code/game/gamemodes/miniantags/guardian/types/lightning.dm b/code/game/gamemodes/miniantags/guardian/types/lightning.dm
index 3aaeebbc513..88d5a43143d 100644
--- a/code/game/gamemodes/miniantags/guardian/types/lightning.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/lightning.dm
@@ -99,7 +99,6 @@
if(istype(G) && G.summoner == summoner)
continue
if(successfulshocks > 4)
- //L.electrocute_act(30, src) //shocks for 30 burn damage
L.visible_message(
"[L] was shocked by the lightning chain!", \
"You are shocked by the lightning chain!", \
diff --git a/code/game/gamemodes/miniantags/guardian/types/ranged.dm b/code/game/gamemodes/miniantags/guardian/types/ranged.dm
index 695782728fa..fe8a566ad52 100644
--- a/code/game/gamemodes/miniantags/guardian/types/ranged.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/ranged.dm
@@ -6,7 +6,6 @@
armour_penetration = 100
/mob/living/simple_animal/hostile/guardian/ranged
- a_intent = INTENT_HELP
friendly = "quietly assesses"
melee_damage_lower = 10
melee_damage_upper = 10
@@ -17,7 +16,7 @@
ranged = 1
rapid = 1
range = 13
- see_invisible = SEE_INVISIBLE_MINIMUM
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
see_in_dark = 8
playstyle_string = "As a Ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit."
magic_fluff_string = "..And draw the Sentinel, an alien master of ranged combat."
@@ -54,12 +53,24 @@
to_chat(src, "You have to be recalled to toggle modes!")
/mob/living/simple_animal/hostile/guardian/ranged/ToggleLight()
- if(see_invisible == SEE_INVISIBLE_MINIMUM)
- to_chat(src, "You deactivate your night vision.")
- see_invisible = SEE_INVISIBLE_LIVING
- else
- to_chat(src, "You activate your night vision.")
- see_invisible = SEE_INVISIBLE_MINIMUM
+ var/msg
+ switch(lighting_alpha)
+ if (LIGHTING_PLANE_ALPHA_VISIBLE)
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
+ msg = "You activate your night vision."
+ if (LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ msg = "You increase your night vision."
+ if (LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE)
+ lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
+ msg = "You maximize your night vision."
+ else
+ lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
+ msg = "You deactivate your night vision."
+
+ update_sight()
+
+ to_chat(src, "[msg]")
/mob/living/simple_animal/hostile/guardian/ranged/verb/Snare()
set name = "Set Surveillance Trap"
@@ -92,7 +103,7 @@
invisibility = 1
-/obj/item/effect/snare/Crossed(AM as mob|obj)
+/obj/item/effect/snare/Crossed(AM as mob|obj, oldloc)
if(isliving(AM))
var/turf/snare_loc = get_turf(loc)
if(spawner)
diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm
index 94c39d12442..81e052a85d8 100644
--- a/code/game/gamemodes/miniantags/morph/morph.dm
+++ b/code/game/gamemodes/miniantags/morph/morph.dm
@@ -27,7 +27,7 @@
melee_damage_lower = 20
melee_damage_upper = 20
see_in_dark = 8
- see_invisible = SEE_INVISIBLE_MINIMUM
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
idle_vision_range = 1 // Only attack when target is close
wander = 0
attacktext = "glomps"
@@ -38,13 +38,23 @@
var/atom/movable/form = null
var/morph_time = 0
- var/playstyle_string = "You are a morph, an abomination of science created primarily with changeling cells. \
- You may take the form of anything nearby by shift-clicking it. This process will alert any nearby \
- observers, and can only be performed once every five seconds. While morphed, you move faster, but do \
+ var/playstyle_string = "You are a morph. As an abomination created primarily with changeling cells, \
+ you may take the form of anything nearby by shift-clicking it. This process will alert any nearby \
+ observers, and can only be performed once every five seconds. While morphed, you move faster, but do \
less damage. In addition, anyone within three tiles will note an uncanny wrongness if examining you. \
- You can attack any item or dead creature to consume it - creatures will restore 1/3 of your max health. \
- Finally, you can restore yourself to your original form while morphed by shift-clicking yourself."
+ You can restore yourself to your original form while morphed by shift-clicking yourself. \
+ Finally, you can attack any item or dead creature to consume it - creatures will restore 1/3 of your max health."
+/mob/living/simple_animal/hostile/morph/wizard
+ name = "magical morph"
+ real_name = "magical morph"
+ desc = "A revolting, pulsating pile of flesh. This one looks somewhat.. magical."
+
+/mob/living/simple_animal/hostile/morph/wizard/New()
+ . = ..()
+ AddSpell(new /obj/effect/proc_holder/spell/targeted/smoke)
+ AddSpell(new /obj/effect/proc_holder/spell/targeted/forcewall)
+
/mob/living/simple_animal/hostile/morph/examine(mob/user)
if(morphed)
if(form)
diff --git a/code/game/gamemodes/miniantags/morph/morph_event.dm b/code/game/gamemodes/miniantags/morph/morph_event.dm
index 4a1c8ebeb7e..e80374e2dca 100644
--- a/code/game/gamemodes/miniantags/morph/morph_event.dm
+++ b/code/game/gamemodes/miniantags/morph/morph_event.dm
@@ -21,7 +21,7 @@
player_mind.transfer_to(S)
player_mind.assigned_role = SPECIAL_ROLE_MORPH
player_mind.special_role = SPECIAL_ROLE_MORPH
- ticker.mode.traitors |= player_mind
+ SSticker.mode.traitors |= player_mind
to_chat(S, S.playstyle_string)
S << 'sound/magic/mutate.ogg'
message_admins("[key_of_morph] has been made into morph by an event.")
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index bde3f7ee8e9..740601f3798 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -2,7 +2,9 @@
//"Ghosts" that are invisible and move like ghosts, cannot take damage while invsible
//Don't hear deadchat and are NOT normal ghosts
//Admin-spawn or random event
+
#define INVISIBILITY_REVENANT 50
+#define REVENANT_NAME_FILE "revenant_names.json"
/mob/living/simple_animal/revenant
name = "revenant"
@@ -18,7 +20,7 @@
health = INFINITY //Revenants don't use health, they use essence instead
maxHealth = INFINITY
see_in_dark = 8
- see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
universal_understand = 1
response_help = "passes through"
response_disarm = "swings at"
@@ -51,7 +53,6 @@
var/draining = 0 //If the revenant is draining someone.
var/list/drained_mobs = list() //Cannot harvest the same mob twice
var/perfectsouls = 0 //How many perfect, regen-cap increasing souls the revenant has.
- var/image/ghostimage = null //Visible to ghost with darkness off
/mob/living/simple_animal/revenant/Life(seconds, times_fired)
@@ -91,13 +92,6 @@
if(essence == 0)
to_chat(src, "You feel your essence fraying!")
-/mob/living/simple_animal/revenant/update_sight()
- if(!client)
- return
- if(stat == DEAD)
- grant_death_vision()
- return
-
/mob/living/simple_animal/revenant/say(message)
if(!message)
return
@@ -120,13 +114,18 @@
/mob/living/simple_animal/revenant/New()
..()
- ghostimage = image(src.icon,src,src.icon_state)
- ghost_darkness_images |= ghostimage
- updateallghostimages()
remove_from_all_data_huds()
+ random_revenant_name()
addtimer(CALLBACK(src, .proc/firstSetupAttempt), 15 SECONDS) // Give admin 15 seconds to put in a ghost (Or wait 15 seconds before giving it objectives)
+/mob/living/simple_animal/revenant/proc/random_revenant_name()
+ var/built_name = ""
+ built_name += pick(strings(REVENANT_NAME_FILE, "spirit_type"))
+ built_name += " of "
+ built_name += pick(strings(REVENANT_NAME_FILE, "adjective"))
+ built_name += pick(strings(REVENANT_NAME_FILE, "theme"))
+ name = built_name
/mob/living/simple_animal/revenant/proc/firstSetupAttempt()
if(mind)
@@ -172,7 +171,7 @@
objective2.owner = mind
mind.objectives += objective2
to_chat(src, "Objective #2: [objective2.explanation_text]")
- ticker.mode.traitors |= mind //Necessary for announcing
+ SSticker.mode.traitors |= mind //Necessary for announcing
/mob/living/simple_animal/revenant/proc/giveSpells()
mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
@@ -196,8 +195,6 @@
. = ..()
if(!.)
return FALSE
- ghost_darkness_images -= ghostimage
- updateallghostimages()
to_chat(src, "NO! No... it's too late, you can feel your essence breaking apart...")
notransform = 1
@@ -419,7 +416,7 @@
player_mind.transfer_to(R)
player_mind.assigned_role = SPECIAL_ROLE_REVENANT
player_mind.special_role = SPECIAL_ROLE_REVENANT
- ticker.mode.traitors |= player_mind
+ SSticker.mode.traitors |= player_mind
message_admins("[key_of_revenant] has been [client_to_revive ? "re":""]made into a revenant by reforming ectoplasm.")
log_game("[key_of_revenant] was [client_to_revive ? "re":""]made as a revenant by reforming ectoplasm.")
visible_message("[src] suddenly rises into the air before fading away.")
diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
index c201b1bc45d..34bf06f07f7 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
@@ -110,8 +110,6 @@
message = "You toggle your night vision."
action_icon_state = "r_nightvision"
action_background_icon_state = "bg_revenant"
- non_night_vision = INVISIBILITY_REVENANT
- night_vision = SEE_INVISIBLE_OBSERVER_NOLIGHTING
//Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob
/obj/effect/proc_holder/spell/targeted/revenant_transmit
@@ -215,11 +213,11 @@
if(!L.on) //wait, wait, don't shock me
return
flick("[L.base_state]2", L)
- for(var/mob/living/carbon/human/M in view(shock_range, L))
+ for(var/mob/living/M in view(shock_range, L))
if(M == user)
return
M.Beam(L,icon_state="purple_lightning",icon='icons/effects/effects.dmi',time=5)
- M.electrocute_act(shock_damage, "[L.name]", safety=1)
+ M.electrocute_act(shock_damage, L, safety = TRUE)
do_sparks(4, 0, M)
playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1)
diff --git a/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm b/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm
index 757fbe579a2..437e7637a77 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm
@@ -45,7 +45,7 @@
player_mind.transfer_to(revvie)
player_mind.assigned_role = SPECIAL_ROLE_REVENANT
player_mind.special_role = SPECIAL_ROLE_REVENANT
- ticker.mode.traitors |= player_mind
+ SSticker.mode.traitors |= player_mind
message_admins("[key_of_revenant] has been made into a revenant by an event.")
log_game("[key_of_revenant] was spawned as a revenant by an event.")
return 1
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index 7e74de27267..09d5fecb8a2 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -33,7 +33,7 @@
melee_damage_lower = 30
melee_damage_upper = 30
see_in_dark = 8
- see_invisible = SEE_INVISIBLE_MINIMUM
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
var/boost = 0
bloodcrawl = BLOODCRAWL_EAT
@@ -72,7 +72,7 @@
if(!(vialspawned))
var/datum/objective/slaughter/objective = new
var/datum/objective/demonFluff/fluffObjective = new
- ticker.mode.traitors |= mind
+ SSticker.mode.traitors |= mind
objective.owner = mind
fluffObjective.owner = mind
//Paradise Port:I added the objective for one spawned like this
@@ -174,7 +174,7 @@
S.mind.assigned_role = "Harbringer of the Slaughter"
S.mind.special_role = "Harbringer of the Slaughter"
to_chat(S, playstyle_string)
- ticker.mode.add_cultist(S.mind)
+ SSticker.mode.add_cultist(S.mind)
var/obj/effect/proc_holder/spell/targeted/sense_victims/SV = new
AddSpell(SV)
var/datum/objective/new_objective = new /datum/objective
@@ -290,6 +290,10 @@
emote_hear = list("gaffaws", "laughs")
response_help = "hugs"
attacktext = "wildly tickles"
+ maxHealth = 150
+ health = 150
+ melee_damage_lower = 20
+ melee_damage_upper = 20
attack_sound = 'sound/items/bikehorn.ogg'
feast_sound = 'sound/spookoween/scary_horn2.ogg'
diff --git a/code/game/gamemodes/nations/nations.dm b/code/game/gamemodes/nations/nations.dm
deleted file mode 100644
index c8a9ad00a62..00000000000
--- a/code/game/gamemodes/nations/nations.dm
+++ /dev/null
@@ -1,256 +0,0 @@
-datum/game_mode/nations
- name = "nations"
- config_tag = "nations"
- required_players = 25
- var/kickoff = 0
- var/victory = 0
- var/list/cargonians = list("Quartermaster","Cargo Technician","Shaft Miner")
- var/list/servicion = list("Clown", "Mime", "Bartender", "Chef", "Botanist", "Librarian", "Chaplain", "Barber")
-
-
-/datum/game_mode/nations/post_setup()
- spawn (rand(1200, 3000))
- kickoff=1
- send_intercept()
- split_teams()
- set_ai()
- assign_leaders()
-// remove_access()
- for(var/mob/M in GLOB.player_list)
- if(!istype(M,/mob/new_player))
- M << sound('sound/effects/purge_siren.ogg')
-
- return ..()
-
-/datum/game_mode/nations/proc/send_intercept()
- event_announcement.Announce("Due to recent and COMPLETELY UNFOUNDED allegations of massive fraud and insider trading \
- affecting trillions of investors, the Nanotrasen Corporation has decided to liquidate all \
- assets of the Centcom Division in order to pay the massive legal fees that will be incurred \
- during the following centuries long court process. Therefore, all current employment contracts \
- are IMMEDIATELY TERMINATED. Nanotrasen will be unable to send a rescue shuttle to carry you home,\
- however they remain willing for the time being to continue trading cargo. Have a pleasant \
- day.", "FINAL TRANSMISSION, CENTCOM.", new_sound = 'sound/AI/intercept.ogg')
-
-
-/datum/game_mode/nations/proc/split_teams()
-
- for(var/mob/living/carbon/human/H in GLOB.player_list)
- if(H.mind)
- if(H.mind.assigned_role in engineering_positions)
- H.mind.nation = GLOB.all_nations["Atmosia"]
- update_nations_icons_added(H,"hudatmosia")
- H.mind.nation.membership += H.mind.current
- if(H.mind.assigned_role == H.mind.nation.default_leader)
- H.mind.nation.current_leader = H.mind.current
- to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
- continue
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
- continue
-
- if(H.mind.assigned_role in medical_positions)
- H.mind.nation = GLOB.all_nations["Medistan"]
- update_nations_icons_added(H,"hudmedistan")
- H.mind.nation.membership += H.mind.current
- if(H.mind.assigned_role == H.mind.nation.default_leader)
- H.mind.nation.current_leader = H.mind.current
- to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
- continue
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
- continue
-
- if(H.mind.assigned_role in science_positions)
- H.mind.nation = GLOB.all_nations["Scientopia"]
- update_nations_icons_added(H,"hudscientopia")
- H.mind.nation.membership += H.mind.current
- if(H.mind.assigned_role == H.mind.nation.default_leader)
- H.mind.nation.current_leader = H.mind.current
- to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
- continue
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
- continue
-
- if(H.mind.assigned_role in security_positions)
- H.mind.nation = GLOB.all_nations["Brigston"]
- update_nations_icons_added(H,"hudbrigston")
- H.mind.nation.membership += H.mind.current
- if(H.mind.assigned_role == H.mind.nation.default_leader)
- H.mind.nation.current_leader = H.mind.current
- to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
- continue
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
- continue
-
- if(H.mind.assigned_role in cargonians)
- H.mind.nation = GLOB.all_nations["Cargonia"]
- update_nations_icons_added(H,"hudcargonia")
- H.mind.nation.membership += H.mind.current
- if(H.mind.assigned_role == H.mind.nation.default_leader)
- H.mind.nation.current_leader = H.mind.current
- to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
- continue
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
- continue
-
- if(H.mind.assigned_role in servicion)
- H.mind.nation = GLOB.all_nations["Servicion"]
- update_nations_icons_added(H,"hudservice")
- H.mind.nation.membership += H.mind.current
- if(H.mind.assigned_role == H.mind.nation.default_leader)
- H.mind.nation.current_leader = H.mind.current
- to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
- continue
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
- continue
-
- if(H.mind.assigned_role in (support_positions + command_positions))
- H.mind.nation = GLOB.all_nations["People's Republic of Commandzakstan"]
- update_nations_icons_added(H,"hudcommand")
- H.mind.nation.membership += H.mind.current
- if(H.mind.assigned_role == H.mind.nation.default_leader)
- H.mind.nation.current_leader = H.mind.current
- to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
- continue
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
- continue
-
- if(H.mind.assigned_role in civilian_positions)
- to_chat(H, "You do not belong to any nation and are free to sell your services to the highest bidder.")
- continue
-
- else
- message_admins("[H.name] with [H.mind.assigned_role] could not find any nation to assign!")
- continue
-
-
-/datum/game_mode/nations/proc/set_ai()
- for(var/mob/living/silicon/ai/AI in GLOB.mob_list)
- AI.set_zeroth_law("")
- AI.clear_supplied_laws()
- AI.clear_ion_laws()
- AI.clear_inherent_laws()
- AI.add_inherent_law("Uphold the Space Geneva Convention: Weapons of Mass Destruction and Biological Weapons are not allowed.")
- AI.add_inherent_law("You are only capable of protecting crew if they are visible on cameras. Nations that willfully destroy your cameras lose your protection.")
- AI.add_inherent_law("Subdue and detain crewmembers who use lethal force against each other. Kill crew members who use lethal force against you or your borgs.")
- AI.add_inherent_law("Remain available to mediate all conflicts between the various nations when asked to.")
- AI.show_laws()
- for(var/mob/living/silicon/robot/R in AI.connected_robots)
- var/obj/item/mmi/oldmmi = R.mmi
- R.change_mob_type(/mob/living/silicon/robot/nations, null, null, 1, 1 )
- R.lawsync()
- R.show_laws()
- qdel(oldmmi)
-
-/datum/game_mode/nations/proc/remove_access()
- for(var/obj/machinery/door/airlock/W in GLOB.airlocks)
- if(is_station_level(W.z))
- W.req_access = list()
-
-
-/datum/game_mode/nations/proc/assign_leaders()
- for(var/name in GLOB.all_nations)
- var/datum/nations/N = GLOB.all_nations[name]
- if(!N.current_name)
- N.current_name = N.default_name
- if(!N.current_leader && N.membership.len)
- N.current_leader = pick(N.membership)
- to_chat(N.current_leader, "You have been chosen to lead the nation of [N.current_name]!")
- if(N.current_leader)
- var/mob/living/carbon/human/H = N.current_leader
- H.verbs += /mob/living/carbon/human/proc/set_nation_name
- H.verbs += /mob/living/carbon/human/proc/set_ranks
- H.verbs += /mob/living/carbon/human/proc/choose_heir
- N.update_nation_id()
-
-/**
- * LateSpawn hook.
- * Called in newplayer.dm when a humanoid character joins the round after it started.
- * Parameters: var/mob/living/carbon/human, var/rank
- */
-/hook/latespawn/proc/give_latejoiners_nations(var/mob/living/carbon/human/H)
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode) return 1
-
- if(!mode.kickoff) return 1
-
- if(H.mind)
- if(H.mind.assigned_role in engineering_positions)
- H.mind.nation = GLOB.all_nations["Atmosia"]
- mode.update_nations_icons_added(H,"atmosia")
- H.mind.nation.membership += H.mind.current
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
- return 1
-
- if(H.mind.assigned_role in medical_positions)
- H.mind.nation = GLOB.all_nations["Medistan"]
- mode.update_nations_icons_added(H,"hudmedistan")
- H.mind.nation.membership += H.mind.current
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
- return 1
-
- if(H.mind.assigned_role in science_positions)
- H.mind.nation = GLOB.all_nations["Scientopia"]
- mode.update_nations_icons_added(H,"hudscientopia")
- H.mind.nation.membership += H.mind.current
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
- return 1
-
- if(H.mind.assigned_role in security_positions)
- H.mind.nation = GLOB.all_nations["Brigston"]
- mode.update_nations_icons_added(H,"hudbrigston")
- H.mind.nation.membership += H.mind.current
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
- return 1
-
- if(H.mind.assigned_role in mode.cargonians)
- H.mind.nation = GLOB.all_nations["Cargonia"]
- mode.update_nations_icons_added(H,"hudcargonia")
- H.mind.nation.membership += H.mind.current
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
- return 1
-
- if(H.mind.assigned_role in mode.servicion)
- H.mind.nation = GLOB.all_nations["Servicion"]
- mode.update_nations_icons_added(H,"hudservice")
- H.mind.nation.membership += H.mind.current
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
- return 1
-
- if(H.mind.assigned_role in (support_positions + command_positions))
- H.mind.nation = GLOB.all_nations["People's Republic of Commandzakstan"]
- mode.update_nations_icons_added(H,"hudcommand")
- H.mind.nation.membership += H.mind.current
- to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
- return 1
-
- if(H.mind.assigned_role in civilian_positions)
- to_chat(H, "You do not belong to any nation and are free to sell your services to the highest bidder.")
- return 1
-
- if(H.mind.assigned_role == "AI")
- mode.set_ai()
- return 1
-
- else
- message_admins("[H.name] with [H.mind.assigned_role] could not find any nation to assign!")
- return 1
- message_admins("[H.name] latejoined with no mind.")
- return 1
-
-/proc/get_nations_mode()
- if(!GAMEMODE_IS_NATIONS)
- return null
-
- return ticker.mode
-
-
-//prepare for copypaste
-//While not an Antag i AM using the set_antag hud on this to make this easier.
-/datum/game_mode/proc/update_nations_icons_added(datum/mind/nations_mind,var/naticon)
- var/datum/atom_hud/antag/nations_hud = huds[GAME_HUD_NATIONS]
- nations_hud.join_hud(nations_mind)
- set_nations_hud(nations_mind,naticon)
-
-/datum/game_mode/proc/update_nations_icons_removed(datum/mind/nations_mind)
- var/datum/atom_hud/antag/nations_hud = huds[GAME_HUD_NATIONS]
- nations_hud.leave_hud(nations_mind)
- set_nations_hud(nations_mind, null)
diff --git a/code/game/gamemodes/nations/nationsdatums.dm b/code/game/gamemodes/nations/nationsdatums.dm
deleted file mode 100644
index d7c211f829d..00000000000
--- a/code/game/gamemodes/nations/nationsdatums.dm
+++ /dev/null
@@ -1,38 +0,0 @@
-/datum/nations
- var/default_name
- var/current_name
- var/default_leader
- var/current_leader
- var/list/membership = list()
- var/leader_rank = "Leader"
- var/heir_rank = "Heir"
- var/member_rank = "Member"
- var/heir
-
-/datum/nations/atmosia
- default_name = "Atmosia"
- default_leader = "Chief Engineer"
-
-/datum/nations/brigston
- default_name = "Brigston"
- default_leader = "Head of Security"
-
-/datum/nations/cargonia
- default_name = "Cargonia"
- default_leader = "Quartermaster"
-
-/datum/nations/command
- default_name = "People's Republic of Commandzakstan"
- default_leader = "Captain"
-
-/datum/nations/medistan
- default_name = "Medistan"
- default_leader = "Chief Medical Officer"
-
-/datum/nations/scientopia
- default_name = "Scientopia"
- default_leader = "Research Director"
-
-/datum/nations/service
- default_name = "Servicion"
- default_leader = "Bartender"
\ No newline at end of file
diff --git a/code/game/gamemodes/nations/nationsprocs.dm b/code/game/gamemodes/nations/nationsprocs.dm
deleted file mode 100644
index 55487a27da9..00000000000
--- a/code/game/gamemodes/nations/nationsprocs.dm
+++ /dev/null
@@ -1,120 +0,0 @@
-/mob/living/carbon/human/proc/set_nation_name()
- set name = "Rename Nation"
- set category = "Nations"
- set desc = "Click to rename your nation. You are only able to do this once."
-
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode) return 1
-
- if(!mode.kickoff) return 1
-
- var/mob/living/carbon/human/H = src
- if(H.stat==DEAD) return
- if(H.mind && H.mind.nation && H.mind.nation.current_leader == H)
- var/input = stripped_input(H,"What do you want to name your nation?", ,"", MAX_NAME_LEN)
-
- if(input)
- H.mind.nation.current_name = input
- H.mind.nation.update_nation_id()
- to_chat(H, "You rename your nation to [input].")
- H.verbs -= /mob/living/carbon/human/proc/set_nation_name
- return 1
-
-
-/mob/living/carbon/human/proc/set_ranks()
- set name = "Set Ranks"
- set category = "Nations"
- set desc = "Click to set a rank for Leaders and Members."
-
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode) return 1
-
- if(!mode.kickoff) return 1
-
- var/mob/living/carbon/human/H = src
- if(H.stat==DEAD) return
- if(H.mind && H.mind.nation && H.mind.nation.current_leader == H)
- var/type = input(H, "What rank do you want to change?", "Rename Rank", "") in list("Leader", "Heir", "Member")
- var/input = stripped_input(H,"What rank do you want?", ,"", MAX_NAME_LEN)
- if(input)
- if(type == "Leader")
- H.mind.nation.leader_rank = input
- if(type == "Heir")
- H.mind.nation.heir_rank = input
- if(type == "Member")
- H.mind.nation.member_rank = input
- H.mind.nation.update_nation_id()
- to_chat(H, "You changed the [type] rank of your nation to [input].")
- return 1
-
-/mob/living/carbon/human/proc/choose_heir()
- set name = "Choose Heir"
- set category = "Nations"
- set desc = "Click to pick a Heir. Note that the Heir has the ability to take over your role at ANY TIME. Choose carefully."
-
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode) return 1
-
- if(!mode.kickoff) return 1
-
- var/mob/living/carbon/human/H = src
- if(H.stat==DEAD) return
- if(H.mind && H.mind.nation && H.mind.nation.current_leader == H)
- var/heir = input(H, "Who do you wish to make your heir?", "Choose Heir", "") as null|anything in H.mind.nation.membership
- if(heir)
- if(H.mind.nation.heir)
- var/mob/living/carbon/human/oldheir = H.mind.nation.heir
- to_chat(oldheir, "You are no longer the heir to your nation!")
- oldheir.verbs -= /mob/living/carbon/human/proc/takeover
- var/mob/living/carbon/human/newheir = heir
- H.mind.nation.heir = newheir
- newheir.verbs += /mob/living/carbon/human/proc/takeover
- to_chat(newheir, "You have been selected to be the heir to your nation's leadership!")
- to_chat(H, "You have selected [heir] to be your heir!")
- H.mind.nation.update_nation_id()
-
-
-/mob/living/carbon/human/proc/takeover()
- set name = "Become Leader"
- set category = "Nations"
- set desc = "Click to replace your current nation's leader with yourself."
-
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode) return 1
-
- if(!mode.kickoff) return 1
-
- var/mob/living/carbon/human/H = src
- if(H.stat==DEAD) return
- if(H.mind && H.mind.nation && H.mind.nation.heir == H)
- var/confirmation = input(H, "Are you sure you want to take over leadership?", "Become Leader", "") as null|anything in list("Yes", "No")
- if(confirmation == "Yes")
- var/mob/living/carbon/human/oldleader = H.mind.nation.current_leader
- to_chat(oldleader, "You have been replaced by [H.name] as the leader of [H.mind.nation.current_name]!")
- oldleader.verbs -= /mob/living/carbon/human/proc/set_nation_name
- oldleader.verbs -= /mob/living/carbon/human/proc/set_ranks
- oldleader.verbs -= /mob/living/carbon/human/proc/choose_heir
- H.mind.nation.current_leader = H
- H.mind.nation.heir = null
- H.verbs -= /mob/living/carbon/human/proc/takeover
- H.verbs += /mob/living/carbon/human/proc/set_nation_name
- H.verbs += /mob/living/carbon/human/proc/set_ranks
- H.verbs += /mob/living/carbon/human/proc/choose_heir
- to_chat(H, "You have replaced [oldleader.name] as the leader of [H.mind.nation.current_name]!")
- H.mind.nation.update_nation_id()
-
-
-/datum/nations/proc/update_nation_id()
- for(var/mob/living/carbon/human/M in membership)
- for(var/obj/item/card/id/I in M.contents)
- if(I.registered_name == M.real_name)
- if(M == current_leader)
- I.name = "[I.registered_name]'s ID Card ([current_name] [leader_rank])"
- I.assignment = "[current_name] [leader_rank]"
- else if(M == heir)
- I.name = "[I.registered_name]'s ID Card ([current_name] [heir_rank])"
- I.assignment = "[current_name] [heir_rank]"
- else
- I.name = "[I.registered_name]'s ID Card ([current_name] [member_rank])"
- I.assignment = "[current_name] [member_rank]"
-
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index 95849d31f65..cf808f3709d 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -1,10 +1,10 @@
-#define NUKESCALINGMODIFIER 1
+#define NUKESCALINGMODIFIER 1.2
/datum/game_mode
var/list/datum/mind/syndicates = list()
proc/issyndicate(mob/living/M as mob)
- return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.syndicates)
+ return istype(M) && M.mind && SSticker && SSticker.mode && (M.mind in SSticker.mode.syndicates)
/datum/game_mode/nuclear
name = "nuclear emergency"
@@ -12,11 +12,10 @@ proc/issyndicate(mob/living/M as mob)
required_players = 30 // 30 players - 5 players to be the nuke ops = 25 players remaining
required_enemies = 5
recommended_enemies = 5
- free_golems_disabled = TRUE
var/const/agents_possible = 5 //If we ever need more syndicate agents.
- var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer!
+ var/nukes_left = 1 //Call 3714-PRAY right now and order more nukes! Limited offer!
var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station
var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level
var/total_tc = 0 //Total amount of telecrystals shared between nuke ops
@@ -36,7 +35,7 @@ proc/issyndicate(mob/living/M as mob)
if(possible_syndicates.len < 1)
return 0
- if(possible_syndicates.len > agents_possible)
+ if(LAZYLEN(possible_syndicates) > agents_possible)
agent_number = agents_possible
else
agent_number = possible_syndicates.len
@@ -64,7 +63,7 @@ proc/issyndicate(mob/living/M as mob)
/datum/game_mode/proc/remove_operative(datum/mind/operative_mind)
if(operative_mind in syndicates)
- ticker.mode.syndicates -= operative_mind
+ SSticker.mode.syndicates -= operative_mind
operative_mind.special_role = null
for(var/datum/objective/nuclear/O in operative_mind.objectives)
operative_mind.objectives -= O
@@ -73,7 +72,7 @@ proc/issyndicate(mob/living/M as mob)
to_chat(operative_mind.current, "You have been turned into a robot! You are no longer a Syndicate operative.")
else
to_chat(operative_mind.current, "You have been brainwashed! You are no longer a Syndicate operative.")
- ticker.mode.update_synd_icons_removed(operative_mind)
+ SSticker.mode.update_synd_icons_removed(operative_mind)
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
@@ -123,12 +122,7 @@ proc/issyndicate(mob/living/M as mob)
leader_selected = 1
else
synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]"
-
- var/list/foundIDs = synd_mind.current.search_contents_for(/obj/item/card/id)
- if(foundIDs.len)
- for(var/obj/item/card/id/ID in foundIDs)
- ID.name = "[syndicate_name()] Operative ID card"
- ID.registered_name = synd_mind.current.real_name
+ update_syndicate_id(synd_mind, FALSE)
agent_number++
spawnpos++
@@ -201,15 +195,7 @@ proc/issyndicate(mob/living/M as mob)
var/obj/item/nuclear_challenge/challenge = new /obj/item/nuclear_challenge
synd_mind.current.equip_to_slot_or_del(challenge, slot_r_hand)
- var/list/foundIDs = synd_mind.current.search_contents_for(/obj/item/card/id)
-
- if(foundIDs.len)
- for(var/obj/item/card/id/ID in foundIDs)
- ID.name = "[syndicate_name()] [leader_title] ID card"
- ID.registered_name = synd_mind.current.real_name
- ID.access += access_syndicate_leader
- else
- message_admins("Warning: Nuke Ops spawned without access to leave their spawn area!")
+ update_syndicate_id(synd_mind, leader_title, TRUE)
if(nuke_code)
synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0)
@@ -221,7 +207,7 @@ proc/issyndicate(mob/living/M as mob)
P.stamp(stamp)
qdel(stamp)
- if(ticker.mode.config_tag=="nuclear")
+ if(SSticker.mode.config_tag=="nuclear")
P.loc = synd_mind.current.loc
else
var/mob/living/carbon/human/H = synd_mind.current
@@ -231,8 +217,18 @@ proc/issyndicate(mob/living/M as mob)
else
nuke_code = "code will be provided later"
- return
+/datum/game_mode/proc/update_syndicate_id(var/datum/mind/synd_mind, is_leader = FALSE)
+ var/list/found_ids = synd_mind.current.search_contents_for(/obj/item/card/id)
+
+ if(LAZYLEN(found_ids))
+ for(var/obj/item/card/id/ID in found_ids)
+ ID.name = "[synd_mind.current.real_name] ID card"
+ ID.registered_name = synd_mind.current.real_name
+ if(is_leader)
+ ID.access += access_syndicate_leader
+ else
+ message_admins("Warning: Operative [key_name_admin(synd_mind.current)] spawned without an ID card!")
/datum/game_mode/proc/forge_syndicate_objectives(var/datum/mind/syndicate)
var/datum/objective/nuclear/syndobj = new
@@ -255,7 +251,7 @@ proc/issyndicate(mob/living/M as mob)
return 1337 // WHY??? -- Doohl
-/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob)
+/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob, uplink_uses = 20)
var/radio_freq = SYND_FREQ
var/obj/item/radio/R = new /obj/item/radio/headset/syndicate/alt(synd_mob)
@@ -272,7 +268,7 @@ proc/issyndicate(mob/living/M as mob)
synd_mob.equip_to_slot_or_del(new /obj/item/pinpointer/nukeop(synd_mob), slot_wear_pda)
var/obj/item/radio/uplink/nuclear/U = new /obj/item/radio/uplink/nuclear(synd_mob)
U.hidden_uplink.uplink_owner="[synd_mob.key]"
- U.hidden_uplink.uses = 20
+ U.hidden_uplink.uses = uplink_uses
synd_mob.equip_to_slot_or_del(U, slot_in_backpack)
if(synd_mob.dna.species)
@@ -310,7 +306,6 @@ proc/issyndicate(mob/living/M as mob)
synd_mob.update_icons()
return 1
-
/datum/game_mode/nuclear/check_win()
if(nukes_left == 0)
return 1
@@ -441,7 +436,7 @@ proc/issyndicate(mob/living/M as mob)
/datum/game_mode/nuclear/set_scoreboard_gvars()
var/foecount = 0
- for(var/datum/mind/M in ticker.mode.syndicates)
+ for(var/datum/mind/M in SSticker.mode.syndicates)
foecount++
if(!M || !M.current)
score_opkilled++
@@ -461,7 +456,7 @@ proc/issyndicate(mob/living/M as mob)
var/turf/T = get_turf(nuke)
var/area/A = T.loc
- var/list/thousand_penalty = list(/area/syndicate_station, /area/wizard_station, /area/solar, /area)
+ var/list/thousand_penalty = list(/area/wizard_station, /area/solar, /area)
var/list/fiftythousand_penalty = list(/area/security/main, /area/security/brig, /area/security/armoury, /area/security/checkpoint2)
if(is_type_in_list(A, thousand_penalty))
@@ -494,7 +489,7 @@ proc/issyndicate(mob/living/M as mob)
var/diskdat = ""
var/bombdat = null
- for(var/datum/mind/M in ticker.mode.syndicates)
+ for(var/datum/mind/M in SSticker.mode.syndicates)
foecount++
for(var/mob/living/C in world)
diff --git a/code/game/gamemodes/nuclear/nuclear_challenge.dm b/code/game/gamemodes/nuclear/nuclear_challenge.dm
index 45711bb52fc..35c26408c5b 100644
--- a/code/game/gamemodes/nuclear/nuclear_challenge.dm
+++ b/code/game/gamemodes/nuclear/nuclear_challenge.dm
@@ -21,7 +21,7 @@
return
declaring_war = TRUE
- var/are_you_sure = alert(user, "Consult your team carefully before you declare war on [station_name()]. Are you sure you want to alert the enemy crew? You have [-round((world.time-round_start_time - CHALLENGE_TIME_LIMIT)/10)] seconds to decide.", "Declare war?", "Yes", "No")
+ var/are_you_sure = alert(user, "Consult your team carefully before you declare war on [station_name()]. Are you sure you want to alert the enemy crew? You have [-round((world.time-SSticker.round_start_time - CHALLENGE_TIME_LIMIT)/10)] seconds to decide.", "Declare war?", "Yes", "No")
declaring_war = FALSE
if(!check_allowed(user))
@@ -88,7 +88,7 @@
if(!is_admin_level(user.z))
to_chat(user, "You have to be at your base to use this.")
return FALSE
- if((world.time - round_start_time) > CHALLENGE_TIME_LIMIT) // Only count after the round started
+ if((world.time - SSticker.round_start_time) > CHALLENGE_TIME_LIMIT) // Only count after the round started
to_chat(user, "It's too late to declare hostilities. Your benefactors are already busy with other schemes. You'll have to make do with what you have on hand.")
return FALSE
for(var/obj/machinery/computer/shuttle/syndicate/S in GLOB.machines)
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 94190149848..09de3f917bd 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -354,8 +354,8 @@ var/bomb_set
if(!lighthack)
icon_state = "nuclearbomb3"
playsound(src,'sound/machines/alarm.ogg',100,0,5)
- if(ticker && ticker.mode)
- ticker.mode.explosion_in_progress = 1
+ if(SSticker && SSticker.mode)
+ SSticker.mode.explosion_in_progress = 1
sleep(100)
enter_allowed = 0
@@ -368,17 +368,17 @@ var/bomb_set
else
off_station = 2
- if(ticker)
- if(ticker.mode && ticker.mode.name == "nuclear emergency")
+ if(SSticker)
+ if(SSticker.mode && SSticker.mode.name == "nuclear emergency")
var/obj/docking_port/mobile/syndie_shuttle = SSshuttle.getShuttle("syndicate")
if(syndie_shuttle)
- ticker.mode:syndies_didnt_escape = is_station_level(syndie_shuttle.z)
- ticker.mode:nuke_off_station = off_station
- ticker.station_explosion_cinematic(off_station,null)
- if(ticker.mode)
- ticker.mode.explosion_in_progress = 0
- if(ticker.mode.name == "nuclear emergency")
- ticker.mode:nukes_left --
+ SSticker.mode:syndies_didnt_escape = is_station_level(syndie_shuttle.z)
+ SSticker.mode:nuke_off_station = off_station
+ SSticker.station_explosion_cinematic(off_station,null)
+ if(SSticker.mode)
+ SSticker.mode.explosion_in_progress = 0
+ if(SSticker.mode.name == "nuclear emergency")
+ SSticker.mode:nukes_left --
else if(off_station == 1)
to_chat(world, "A nuclear device was set off, but the explosion was out of reach of the station!")
else if(off_station == 2)
@@ -386,10 +386,10 @@ var/bomb_set
else
to_chat(world, "The station was destoyed by the nuclear blast!")
- ticker.mode.station_was_nuked = (off_station<2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated.
+ SSticker.mode.station_was_nuked = (off_station<2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated.
//kinda shit but I couldn't get permission to do what I wanted to do.
- if(!ticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is
+ if(!SSticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is
world.Reboot("Station destroyed by Nuclear Device.", "end_error", "nuke - unhandled ending")
return
return
@@ -407,7 +407,7 @@ var/bomb_set
/obj/item/disk/nuclear/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
GLOB.poi_list |= src
/obj/item/disk/nuclear/process()
@@ -437,7 +437,7 @@ var/bomb_set
message_admins("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - JMP":"nonexistent location"]).")
log_game("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z]":"nonexistent location"]).")
GLOB.poi_list.Remove(src)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
if(blobstart.len > 0)
diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm
index 61986b34f94..07ee2219157 100644
--- a/code/game/gamemodes/nuclear/pinpointer.dm
+++ b/code/game/gamemodes/nuclear/pinpointer.dm
@@ -165,7 +165,13 @@
var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in item_names
if(!targetitem)
return
- target = locate(item_paths[targetitem])
+
+ var/list/target_candidates = get_all_of_type(item_paths[targetitem], subtypes = TRUE)
+ for(var/obj/item/candidate in target_candidates)
+ if(!is_admin_level((get_turf(candidate)).z))
+ target = candidate
+ break
+
if(!target)
to_chat(usr, "Failed to locate [targetitem]!")
return
@@ -273,7 +279,7 @@
var/mob/living/carbon/nearest_op = null
/obj/item/pinpointer/operative/attack_self()
- if(!usr.mind || !(usr.mind in ticker.mode.syndicates))
+ if(!usr.mind || !(usr.mind in SSticker.mode.syndicates))
to_chat(usr, "AUTHENTICATION FAILURE. ACCESS DENIED.")
return 0
if(!active)
@@ -290,7 +296,7 @@
nearest_op = null //Resets nearest_op every time it scans
var/closest_distance = 1000
for(var/mob/living/carbon/M in GLOB.mob_list)
- if(M.mind && (M.mind in ticker.mode.syndicates))
+ if(M.mind && (M.mind in SSticker.mode.syndicates))
if(get_dist(M, get_turf(src)) < closest_distance) //Actually points toward the nearest op, instead of a random one like it used to
nearest_op = M
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 210b1bb786e..836c51d5a2c 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -25,6 +25,8 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
/datum/objective/proc/is_invalid_target(datum/mind/possible_target)
if(possible_target == owner)
return TARGET_INVALID_IS_OWNER
+ if(possible_target in owner.targets)
+ return TARGET_INVALID_IS_TARGET
if(!ishuman(possible_target.current))
return TARGET_INVALID_NOT_HUMAN
if(!possible_target.current.stat == DEAD)
@@ -43,7 +45,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
/datum/objective/proc/find_target()
var/list/possible_targets = list()
- for(var/datum/mind/possible_target in ticker.minds)
+ for(var/datum/mind/possible_target in SSticker.minds)
if(is_invalid_target(possible_target))
continue
@@ -52,7 +54,6 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
if(possible_targets.len > 0)
target = pick(possible_targets)
-
/datum/objective/assassinate
martyr_compatible = 1
@@ -263,9 +264,9 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
return 0
if(!owner.current || owner.current.stat == DEAD)
return 0
- if(ticker.force_ending) //This one isn't their fault, so lets just assume good faith
+ if(SSticker.force_ending) //This one isn't their fault, so lets just assume good faith
return 1
- if(ticker.mode.station_was_nuked) //If they escaped the blast somehow, let them win
+ if(SSticker.mode.station_was_nuked) //If they escaped the blast somehow, let them win
return 1
if(SSshuttle.emergency.mode < SHUTTLE_ENDGAME)
return 0
@@ -273,7 +274,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
if(!location)
return 0
- if(istype(location, /turf/simulated/shuttle/floor4) || istype(location, /turf/simulated/floor/mineral/plastitanium/brig)) // Fails traitors if they are in the shuttle brig -- Polymorph
+ if(istype(location, /turf/simulated/shuttle/floor4) || istype(location, /turf/simulated/floor/mineral/plastitanium/red/brig)) // Fails traitors if they are in the shuttle brig -- Polymorph
return 0
if(location.onCentcom() || location.onSyndieBase())
@@ -287,7 +288,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
/datum/objective/escape/escape_with_identity/find_target()
var/list/possible_targets = list() //Copypasta because NO_DNA races, yay for snowflakes.
- for(var/datum/mind/possible_target in ticker.minds)
+ for(var/datum/mind/possible_target in SSticker.minds)
if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && possible_target.current.client)
var/mob/living/carbon/human/H = possible_target.current
if(!(NO_DNA in H.dna.species.species_traits))
@@ -344,11 +345,14 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
var/theft_area
/datum/objective/steal/proc/get_location()
- if(steal_target.location_override)
- return steal_target.location_override
- var/obj/item/T = locate(steal_target.typepath)
- theft_area = get_area(T.loc)
- return "[theft_area]"
+ if(steal_target.location_override)
+ return steal_target.location_override
+ var/list/obj/item/steal_candidates = get_all_of_type(steal_target.typepath, subtypes = TRUE)
+ for(var/obj/item/candidate in steal_candidates)
+ if(!is_admin_level(candidate.loc.z))
+ theft_area = get_area(candidate.loc)
+ return "[theft_area]"
+ return "an unknown area"
/datum/objective/steal/find_target()
var/loop=50
@@ -358,9 +362,12 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
var/datum/theft_objective/O = new thefttype
if(owner.assigned_role in O.protected_jobs)
continue
+ if(O in owner.targets)
+ continue
if(O.flags & 2)
continue
- steal_target=O
+ steal_target = O
+
explanation_text = "Steal [steal_target]. One was last seen in [get_location()]. "
if(islist(O.protected_jobs) && O.protected_jobs.len)
explanation_text += "It may also be in the possession of the [jointext(O.protected_jobs, ", ")]."
@@ -452,19 +459,19 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
/datum/objective/absorb
/datum/objective/absorb/proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6)
target_amount = rand (lowbound,highbound)
- if(ticker)
+ if(SSticker)
var/n_p = 1 //autowin
- if(ticker.current_state == GAME_STATE_SETTING_UP)
+ if(SSticker.current_state == GAME_STATE_SETTING_UP)
for(var/mob/new_player/P in GLOB.player_list)
if(P.client && P.ready && P.mind != owner)
if(P.client.prefs && (P.client.prefs.species == "Machine")) // Special check for species that can't be absorbed. No better solution.
continue
n_p++
- else if(ticker.current_state == GAME_STATE_PLAYING)
+ else if(SSticker.current_state == GAME_STATE_PLAYING)
for(var/mob/living/carbon/human/P in GLOB.player_list)
if(NO_DNA in P.dna.species.species_traits)
continue
- if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner)
+ if(P.client && !(P.mind in SSticker.mode.changelings) && P.mind!=owner)
n_p++
target_amount = min(target_amount, n_p)
@@ -531,8 +538,8 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
var/list/possible_targets = list()
var/list/priority_targets = list()
- for(var/datum/mind/possible_target in ticker.minds)
- if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && (possible_target.assigned_role != possible_target.special_role))
+ for(var/datum/mind/possible_target in SSticker.minds)
+ if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && (possible_target.assigned_role != possible_target.special_role) && !possible_target.offstation_role)
possible_targets += possible_target
for(var/role in roles)
if(possible_target.assigned_role == role)
@@ -627,7 +634,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
if(total_amount >= target_amount)
return 1
- var/datum/game_mode/heist/H = ticker.mode
+ var/datum/game_mode/heist/H = SSticker.mode
for(var/datum/mind/raider in H.raiders)
if(raider.current)
for(var/obj/O in raider.current.get_contents())
@@ -697,7 +704,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
S = I
total_amount += S.get_amount()
- var/datum/game_mode/heist/H = ticker.mode
+ var/datum/game_mode/heist/H = SSticker.mode
for(var/datum/mind/raider in H.raiders)
if(raider.current)
for(var/obj/item/O in raider.current.get_contents())
@@ -714,7 +721,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
explanation_text = "Do not leave any Vox behind, alive or dead."
/datum/objective/heist/inviolate_crew/check_completion()
- var/datum/game_mode/heist/H = ticker.mode
+ var/datum/game_mode/heist/H = SSticker.mode
if(H.is_raider_crew_safe())
return 1
return 0
@@ -726,7 +733,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
var/vox_allowed_kills = 3 // The number of people the vox can accidently kill. Mostly a counter to people killing themselves if a raider touches them to force fail.
var/vox_total_kills = 0
- var/datum/game_mode/heist/H = ticker.mode
+ var/datum/game_mode/heist/H = SSticker.mode
for(var/datum/mind/raider in H.raiders)
vox_total_kills += raider.kills.len // Kills are listed in the mind; uses this to calculate vox kills
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index 7cab3de5aa1..9f7e14ccef2 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -87,7 +87,7 @@
if(check_counter >= 5)
if(!finished)
check_heads()
- ticker.mode.check_win()
+ SSticker.mode.check_win()
check_counter = 0
return FALSE
@@ -369,7 +369,7 @@
/datum/game_mode/revolution/set_scoreboard_gvars()
var/foecount = 0
- for(var/datum/mind/M in ticker.mode.head_revolutionaries)
+ for(var/datum/mind/M in SSticker.mode.head_revolutionaries)
foecount++
if(!M || !M.current)
score_opkilled++
@@ -408,10 +408,10 @@
var/comcount = 0
var/revcount = 0
var/loycount = 0
- for(var/datum/mind/M in ticker.mode:head_revolutionaries)
+ for(var/datum/mind/M in SSticker.mode:head_revolutionaries)
if(M.current && M.current.stat != DEAD)
foecount++
- for(var/datum/mind/M in ticker.mode:revolutionaries)
+ for(var/datum/mind/M in SSticker.mode:revolutionaries)
if(M.current && M.current.stat != DEAD)
revcount++
for(var/mob/living/carbon/human/player in world)
@@ -421,7 +421,7 @@
if(player.stat != DEAD)
comcount++
else
- if(player.mind in ticker.mode.revolutionaries) continue
+ if(player.mind in SSticker.mode.revolutionaries) continue
loycount++
for(var/mob/living/silicon/X in world)
diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm
index 35284594b46..216c946fc97 100644
--- a/code/game/gamemodes/sandbox/h_sandbox.dm
+++ b/code/game/gamemodes/sandbox/h_sandbox.dm
@@ -67,32 +67,32 @@ datum/hSB
P.wear_suit.plane = initial(P.wear_suit.plane)
P.wear_suit = null
P.wear_suit = new/obj/item/clothing/suit/space(P)
- P.wear_suit.layer = 20
- P.wear_suit.plane = HUD_PLANE
+ P.wear_suit.layer = ABOVE_HUD_LAYER
+ P.wear_suit.plane = ABOVE_HUD_PLANE
if(P.head)
P.head.loc = P.loc
P.head.layer = initial(P.head.layer)
P.head.plane = initial(P.head.plane)
P.head = null
P.head = new/obj/item/clothing/head/helmet/space(P)
- P.head.layer = 20
- P.head.plane = HUD_PLANE
+ P.head.layer = ABOVE_HUD_LAYER
+ P.head.plane = ABOVE_HUD_PLANE
if(P.wear_mask)
P.wear_mask.loc = P.loc
P.wear_mask.layer = initial(P.wear_mask.layer)
P.wear_mask.plane = initial(P.wear_mask.plane)
P.wear_mask = null
P.wear_mask = new/obj/item/clothing/mask/gas(P)
- P.wear_mask.layer = 20
- P.wear_mask.plane = HUD_PLANE
+ P.wear_mask.layer = ABOVE_HUD_LAYER
+ P.wear_mask.plane = ABOVE_HUD_PLANE
if(P.back)
P.back.loc = P.loc
P.back.layer = initial(P.back.layer)
P.back.plane = initial(P.back.plane)
P.back = null
P.back = new/obj/item/tank/jetpack(P)
- P.back.layer = 20
- P.back.plane = HUD_PLANE
+ P.back.layer = ABOVE_HUD_LAYER
+ P.back.plane = ABOVE_HUD_PLANE
P.internal = P.back
if("hsbmetal")
var/obj/item/stack/sheet/hsb = new/obj/item/stack/sheet/metal
diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm
index 9a3ca6073a1..379b4fbdcd9 100644
--- a/code/game/gamemodes/scoreboard.dm
+++ b/code/game/gamemodes/scoreboard.dm
@@ -1,9 +1,9 @@
-/datum/controller/gameticker/proc/scoreboard()
+/datum/controller/subsystem/ticker/proc/scoreboard()
//Print a list of antagonists to the server log
var/list/total_antagonists = list()
//Look into all mobs in world, dead or alive
- for(var/datum/mind/Mind in minds)
+ for(var/datum/mind/Mind in SSticker.minds)
var/temprole = Mind.special_role
if(temprole) //if they are an antagonist of some sort.
if(temprole in total_antagonists) //If the role exists already, add the name to it
@@ -59,15 +59,15 @@
score_richestjob = E.job
score_richestkey = E.key
- dmg_score = E.bruteloss + E.fireloss + E.toxloss + E.oxyloss
+ dmg_score = E.getBruteLoss() + E.getFireLoss() + E.getToxLoss() + E.getOxyLoss()
if(dmg_score > score_dmgestdamage)
score_dmgestdamage = dmg_score
score_dmgestname = E.real_name
score_dmgestjob = E.job
score_dmgestkey = E.key
- if(ticker && ticker.mode)
- ticker.mode.set_scoreboard_gvars()
+ if(SSticker && SSticker.mode)
+ SSticker.mode.set_scoreboard_gvars()
// Check station's power levels
@@ -147,7 +147,7 @@
E.scorestats()
// A recursive function to properly determine the wealthiest escapee
-/datum/controller/gameticker/proc/get_score_container_worth(atom/C, level=0)
+/datum/controller/subsystem/ticker/proc/get_score_container_worth(atom/C, level=0)
if(level >= 5)
// in case the containers recurse or something
return 0
@@ -171,8 +171,8 @@
/mob/proc/scorestats()
var/dat = "Round Statistics and Score "
- if(ticker && ticker.mode)
- dat += ticker.mode.get_scoreboard_stats()
+ if(SSticker && SSticker.mode)
+ dat += SSticker.mode.get_scoreboard_stats()
dat += {"
General Statistics
@@ -208,7 +208,7 @@
else
dat += "No-one escaped! "
- dat += ticker.mode.declare_job_completion()
+ dat += SSticker.mode.declare_job_completion()
dat += {"
diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm
index 0c16e88279b..78e6cea4987 100644
--- a/code/game/gamemodes/setupgame.dm
+++ b/code/game/gamemodes/setupgame.dm
@@ -142,12 +142,12 @@
qdel(F)
continue
else
- ticker.factions.Add(F)
- ticker.availablefactions.Add(F)
+ SSticker.factions.Add(F)
+ SSticker.availablefactions.Add(F)
// Populate the syndicate coalition:
- for(var/datum/faction/syndicate/S in ticker.factions)
- ticker.syndicate_coalition.Add(S)
+ for(var/datum/faction/syndicate/S in SSticker.factions)
+ SSticker.syndicate_coalition.Add(S)
/proc/setupcult()
var/static/datum/cult_info/picked_cult // Only needs to get picked once
diff --git a/code/game/gamemodes/shadowling/ascendant_shadowling.dm b/code/game/gamemodes/shadowling/ascendant_shadowling.dm
index 51f4d147bba..9eeadeaba0f 100644
--- a/code/game/gamemodes/shadowling/ascendant_shadowling.dm
+++ b/code/game/gamemodes/shadowling/ascendant_shadowling.dm
@@ -12,7 +12,7 @@
speed = 0
var/phasing = 0
see_in_dark = 8
- see_invisible = SEE_INVISIBLE_MINIMUM
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
universal_speak = 1
diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm
index 3f408e08f3b..b580f88c0b7 100644
--- a/code/game/gamemodes/shadowling/shadowling.dm
+++ b/code/game/gamemodes/shadowling/shadowling.dm
@@ -53,17 +53,18 @@ Made by Xhuis
var/objective_explanation
var/warning_threshold
var/victory_warning_announced = FALSE
+ var/thrall_ratio = 1
/proc/is_thrall(var/mob/living/M)
- return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.shadowling_thralls)
+ return istype(M) && M.mind && SSticker && SSticker.mode && (M.mind in SSticker.mode.shadowling_thralls)
/proc/is_shadow_or_thrall(var/mob/living/M)
- return istype(M) && M.mind && ticker && ticker.mode && ((M.mind in ticker.mode.shadowling_thralls) || (M.mind in ticker.mode.shadows))
+ return istype(M) && M.mind && SSticker && SSticker.mode && ((M.mind in SSticker.mode.shadowling_thralls) || (M.mind in SSticker.mode.shadows))
/proc/is_shadow(var/mob/living/M)
- return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.shadows)
+ return istype(M) && M.mind && SSticker && SSticker.mode && (M.mind in SSticker.mode.shadows)
/datum/game_mode/shadowling
@@ -101,6 +102,7 @@ Made by Xhuis
var/thrall_scaling = round(num_players() / 3)
required_thralls = Clamp(thrall_scaling, 15, 25)
+ thrall_ratio = required_thralls / 15
warning_threshold = round(0.66 * required_thralls)
@@ -262,15 +264,19 @@ Made by Xhuis
/datum/game_mode/shadowling/declare_completion()
if(check_shadow_victory() && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE) //Doesn't end instantly - this is hacky and I don't know of a better way ~X
feedback_set_details("round_end_result","shadowling win - shadowling ascension")
+ to_chat(world, "Shadowling Victory")
to_chat(world, "The shadowlings have ascended and taken over the station!")
else if(shadowling_dead && !check_shadow_victory()) //If the shadowlings have ascended, they can not lose the round
feedback_set_details("round_end_result","shadowling loss - shadowling killed")
+ to_chat(world, "Crew Major Victory")
to_chat(world, "The shadowlings have been killed by the crew!")
else if(!check_shadow_victory() && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
feedback_set_details("round_end_result","shadowling loss - crew escaped")
+ to_chat(world, "Crew Minor Victory")
to_chat(world, "The crew escaped the station before the shadowlings could ascend!")
else
feedback_set_details("round_end_result","shadowling loss - generic failure")
+ to_chat(world, "Crew Major Victory")
to_chat(world, "The shadowlings have failed!")
..()
return 1
diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm
index 02b3be7adca..276f8d2eb1f 100644
--- a/code/game/gamemodes/shadowling/shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm
@@ -18,14 +18,41 @@
return 0
-/obj/effect/proc_holder/spell/targeted/glare //Stuns and mutes a human target for 10 seconds
+/obj/effect/proc_holder/spell/targeted/glare //Stuns and mutes a human target, depending on the distance relative to the shadowling
name = "Glare"
- desc = "Stuns and mutes a target for a decent duration."
+ desc = "Stuns and mutes a target for a decent duration. Duration depends on the proximity to the target."
panel = "Shadowling Abilities"
charge_max = 300
clothes_req = 0
+ range = 10 //has no effect beyond this range, so setting this makes invalid/useless targets not show up in popup
action_icon_state = "glare"
- humans_only = 1
+ humans_only = 1 //useless since we override chose_targets, but might be used for other code later??? Might remove, idk
+
+/obj/effect/proc_holder/spell/targeted/glare/choose_targets(mob/user)
+ var/list/possible_targets = list()
+ for(var/mob/living/carbon/human/target in view_or_range(range, user, "view"))
+ if(target.stat)
+ continue
+ if(is_shadow_or_thrall(target))
+ continue
+ possible_targets += target
+ var/mob/living/carbon/human/M
+ var/list/targets = list()
+ if(possible_targets.len == 1)//no choice involved
+ targets = possible_targets
+ else
+ M = input("Choose the target for the spell.", "Targeting") as mob in possible_targets
+ if(M in view_or_range(range, user, "view"))
+ targets += M
+
+
+ if(!targets.len) //doesn't waste the spell
+ revert_cast(user)
+ return
+
+ perform(targets, user = user)
+ return
+
/obj/effect/proc_holder/spell/targeted/glare/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/human/target in targets)
@@ -46,13 +73,25 @@
return
var/mob/living/carbon/human/M = target
user.visible_message("[user]'s eyes flash a blinding red!")
- target.visible_message("[target] freezes in place, [target.p_their()] eyes glazing over...")
- if(in_range(target, user))
+ var/distance = get_dist(target, user)
+ if (distance <= 1) //Melee glare
+ target.visible_message("[target] freezes in place, [target.p_their()] eyes glazing over...")
to_chat(target, "Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by [user.p_their()] heavenly beauty...")
- else //Only alludes to the shadowling if the target is close by
+ target.Stun(10)
+ M.AdjustSilence(10)
+ else //Distant glare
+ var/loss = 10 - distance
+ var/duration = 10 - loss
+ if(loss <= 0)
+ to_chat(user, "Your glare had no effect over a such long distance!")
+ return
+ target.slowed = duration
+ M.AdjustSilence(10)
+ to_chat(target, "A red light flashes across your vision, and your mind tries to resist them.. you are exhausted.. you are not able to speak..")
+ sleep(duration*10)
+ target.Stun(loss)
+ target.visible_message("[target] freezes in place, [target.p_their()] eyes glazing over...")
to_chat(target, "Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights...")
- target.Stun(10)
- M.AdjustSilence(10)
/obj/effect/proc_holder/spell/aoe_turf/veil
name = "Veil"
@@ -204,11 +243,11 @@
/obj/effect/proc_holder/spell/targeted/enthrall/cast(list/targets, mob/user = usr)
var/mob/living/carbon/human/ling = user
- listclearnulls(ticker.mode.shadowling_thralls)
- if(!(ling.mind in ticker.mode.shadows))
+ listclearnulls(SSticker.mode.shadowling_thralls)
+ if(!(ling.mind in SSticker.mode.shadows))
return
if(!isshadowling(ling))
- if(ticker.mode.shadowling_thralls.len >= 5)
+ if(SSticker.mode.shadowling_thralls.len >= 5)
charge_counter = charge_max
return
for(var/mob/living/carbon/human/target in targets)
@@ -279,7 +318,7 @@
target.visible_message("[target] looks to have experienced a revelation!", \
"False faces all dark not real not real not--")
target.setOxyLoss(0) //In case the shadowling was choking them out
- ticker.mode.add_thrall(target.mind)
+ SSticker.mode.add_thrall(target.mind)
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
/obj/effect/proc_holder/spell/targeted/shadowling_regenarmor //Resets a shadowling's species to normal, removes genetic defects, and re-equips their armor
@@ -323,7 +362,7 @@
include_user = 1
var/blind_smoke_acquired
var/screech_acquired
- var/drainLifeAcquired
+ var/nullChargeAcquired
var/reviveThrallAcquired
action_icon_state = "collective_mind"
@@ -333,7 +372,7 @@
return
for(var/mob/living/target in targets)
var/thralls = 0
- var/victory_threshold = ticker.mode.required_thralls
+ var/victory_threshold = SSticker.mode.required_thralls
var/mob/M
to_chat(target, "You focus your telepathic energies abound, harnessing and drawing together the strength of your thralls.")
@@ -347,23 +386,24 @@
to_chat(target, "Your concentration has been broken. The mental hooks you have sent out now retract into your mind.")
return
- if(thralls >= 3 && !screech_acquired)
+ if(thralls >= CEILING(3 * SSticker.mode.thrall_ratio, 1) && !screech_acquired)
screech_acquired = 1
to_chat(target, "The power of your thralls has granted you the Sonic Screech ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms.")
target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech(null))
- if(thralls >= 5 && !blind_smoke_acquired)
+ if(thralls >= CEILING(5 * SSticker.mode.thrall_ratio, 1) && !blind_smoke_acquired)
blind_smoke_acquired = 1
to_chat(target, "The power of your thralls has granted you the Blinding Smoke ability. \
It will create a choking cloud that will blind any non-thralls who enter.")
target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/blindness_smoke(null))
- if(thralls >= 7 && !drainLifeAcquired)
- drainLifeAcquired = 1
- to_chat(target, "The power of your thralls has granted you the Drain Life ability. You can now drain the health of nearby humans to heal yourself.")
- target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/drainLife(null))
+ if(thralls >= CEILING(7 * SSticker.mode.thrall_ratio, 1) && !nullChargeAcquired)
+ nullChargeAcquired = 1
+ to_chat(user, "The power of your thralls has granted you the Null Charge ability. This ability will drain an APC's contents to the void, preventing it from recharging \
+ or sending power until repaired.")
+ target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/null_charge(null))
- if(thralls >= 9 && !reviveThrallAcquired)
+ if(thralls >= CEILING(9 * SSticker.mode.thrall_ratio, 1) && !reviveThrallAcquired)
reviveThrallAcquired = 1
to_chat(target, "The power of your thralls has granted you the Black Recuperation ability. \
This will, after a short time, bring a dead thrall completely back to life with no bodily defects.")
@@ -479,45 +519,57 @@
for(var/obj/structure/window/W in T.contents)
W.take_damage(rand(80, 100))
-/obj/effect/proc_holder/spell/aoe_turf/drainLife
- name = "Drain Life"
- desc = "Damages nearby humans, draining their life and healing your own wounds."
+/obj/effect/proc_holder/spell/aoe_turf/null_charge
+ name = "Null Charge"
+ desc = "Empties an APC, preventing it from recharging until fixed."
panel = "Shadowling Abilities"
- range = 3
- charge_max = 100
- clothes_req = 0
- var/targetsDrained
- var/list/nearbyTargets
- action_icon_state = "drain_life"
+ charge_max = 600
+ clothes_req = FALSE
+ action_icon_state = "null_charge"
-/obj/effect/proc_holder/spell/aoe_turf/drainLife/cast(list/targets, mob/user = usr)
+/obj/effect/proc_holder/spell/aoe_turf/null_charge/cast(mob/user = usr)
if(!shadowling_check(user))
charge_counter = charge_max
return
- var/mob/living/carbon/human/U = usr
- targetsDrained = 0
- nearbyTargets = list()
- for(var/turf/T in targets)
- for(var/mob/living/carbon/M in T.contents)
- if(M == src)
- continue
- targetsDrained++
- nearbyTargets.Add(M)
- if(!targetsDrained)
+
+ var/list/local_objs = view(1, user)
+ var/obj/machinery/power/apc/target_apc
+ for(var/object in local_objs)
+ if(istype(object, /obj/machinery/power/apc))
+ target_apc = object
+ break
+
+ if(!target_apc)
+ to_chat(user, "You must stand next to an APC to drain it!")
charge_counter = charge_max
- to_chat(U, "There were no nearby humans for you to drain.")
return
- for(var/mob/living/carbon/M in nearbyTargets)
- U.heal_organ_damage(10, 10)
- U.adjustToxLoss(-10)
- U.adjustOxyLoss(-10)
- U.adjustStaminaLoss(-20)
- U.AdjustWeakened(-1)
- U.AdjustStunned(-1)
- M.adjustOxyLoss(20)
- M.adjustStaminaLoss(20)
- to_chat(M, "You feel a wave of exhaustion and a curious draining sensation directed towards [U]!")
- to_chat(U, "You draw life from those around you to heal your wounds.")
+
+ if(target_apc.cell?.charge == 0)
+ to_chat(user, "APC must have a power to drain!")
+ charge_counter = charge_max
+ return
+
+ target_apc.operating = 0
+ target_apc.update()
+ target_apc.update_icon()
+ target_apc.visible_message("The [target_apc] flickers and begins to grow dark.")
+
+ to_chat(user, "You dim the APC's screen and carefully begin siphoning its power into the void.")
+ if(!do_after(user, 200, target=target_apc))
+ //Whoops! The APC's powers back on
+ to_chat(user, "Your concentration breaks and the APC suddenly repowers!")
+ target_apc.operating = 1
+ target_apc.update()
+ target_apc.update_icon()
+ target_apc.visible_message("The [target_apc] begins glowing brightly!")
+ else
+ //We did it!
+ to_chat(user, "You sent the APC's power to the void while overloading all it's lights!")
+ target_apc.cell?.charge = 0 //Sent to the shadow realm
+ target_apc.chargemode = 0 //Won't recharge either until an someone hits the button
+ target_apc.charging = 0
+ target_apc.null_charge()
+ target_apc.update_icon()
@@ -553,7 +605,7 @@
charge_counter = charge_max
return
var/empowered_thralls = 0
- for(var/datum/mind/M in ticker.mode.shadowling_thralls)
+ for(var/datum/mind/M in SSticker.mode.shadowling_thralls)
if(!ishuman(M.current))
return
var/mob/living/carbon/human/H = M.current
@@ -620,23 +672,28 @@
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle
name = "Destroy Engines"
- desc = "Extends the time of the emergency shuttle's arrival by fifteen minutes. This can only be used once."
+ desc = "Extends the time of the emergency shuttle's arrival by ten minutes using a life force of our enemy. Shuttle will be unable to be recalled. This can only be used once."
panel = "Shadowling Abilities"
range = 1
clothes_req = 0
charge_max = 600
action_icon_state = "extend_shuttle"
+ var/global/extendlimit = 0
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle/cast(list/targets, mob/user = usr)
if(!shadowling_check(user))
charge_counter = charge_max
return
+ if(extendlimit == 1)
+ to_chat(user, "Shuttle was already delayed.")
+ charge_counter = charge_max
+ return
for(var/mob/living/carbon/human/target in targets)
if(target.stat)
charge_counter = charge_max
return
- if(!is_thrall(target))
- to_chat(user, "[target] must be a thrall.")
+ if(is_shadow_or_thrall(target))
+ to_chat(user, "[target] must not be an ally.")
charge_counter = charge_max
return
if(SSshuttle.emergency.mode != SHUTTLE_CALL)
@@ -648,7 +705,9 @@
"You begin to draw [M]'s life force.")
M.visible_message("[M]'s face falls slack, [M.p_their()] jaw slightly distending.", \
"You are suddenly transported... far, far away...")
- if(!do_after(user, 50, target = M))
+ extendlimit = 1
+ if(!do_after(user, 150, target = M))
+ extendlimit = 0
to_chat(M, "You are snapped back to reality, your haze dissipating!")
to_chat(user, "You have been interrupted. The draw has failed.")
return
@@ -657,10 +716,9 @@
"...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...")
M.death()
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
- var/more_minutes = 9000
- var/timer = SSshuttle.emergency.timeLeft()
- timer += more_minutes
- event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 15 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg')
+ var/more_minutes = 6000
+ var/timer = SSshuttle.emergency.timeLeft(1) + more_minutes
+ event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 10 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg')
SSshuttle.emergency.setTimer(timer)
SSshuttle.emergency.canRecall = FALSE
user.mind.spell_list.Remove(src) //Can only be used once!
@@ -736,7 +794,7 @@
to_chat(user, "You instantly rearrange [target]'s memories, hyptonitizing [target.p_them()] into a thrall.")
to_chat(target, "An agonizing spike of pain drives into your mind, and--")
- ticker.mode.add_thrall(target.mind)
+ SSticker.mode.add_thrall(target.mind)
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
target.add_language("Shadowling Hivemind")
diff --git a/code/game/gamemodes/shadowling/shadowling_items.dm b/code/game/gamemodes/shadowling/shadowling_items.dm
index 500c3ee25c5..69f5688829c 100644
--- a/code/game/gamemodes/shadowling/shadowling_items.dm
+++ b/code/game/gamemodes/shadowling/shadowling_items.dm
@@ -81,4 +81,5 @@
unacidable = 1
flash_protect = -1
vision_flags = SEE_MOBS
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
flags = ABSTRACT | NODROP
\ No newline at end of file
diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
index 29a2c9aadca..514a16174b1 100644
--- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
@@ -107,6 +107,8 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle(null))
+
+ QDEL_NULL(H.hud_used)
H.hud_used = new /datum/hud/human(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha)
H.hud_used.show_hud(H.hud_used.hud_version)
@@ -179,9 +181,9 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
H.invisibility = 60 //This is pretty bad, but is also necessary for the shuttle call to function properly
H.loc = A
sleep(50)
- if(!ticker.mode.shadowling_ascended)
+ if(!SSticker.mode.shadowling_ascended)
SSshuttle.emergency.request(null, 0.3)
SSshuttle.emergency.canRecall = FALSE
- ticker.mode.shadowling_ascended = 1
+ SSticker.mode.shadowling_ascended = 1
A.mind.RemoveSpell(src)
qdel(H)
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index de7ce59eaa2..3edf5b14e58 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -87,6 +87,7 @@
yandere_one.owner = traitor
traitor.objectives += yandere_one
yandere_one.find_target()
+ traitor.targets += yandere_one.target
objective_count++
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = traitor
@@ -99,6 +100,7 @@
kill_objective.owner = traitor
kill_objective.find_target()
traitor.objectives += kill_objective
+ traitor.targets += kill_objective.target
var/datum/objective/survive/survive_objective = new
survive_objective.owner = traitor
@@ -124,26 +126,31 @@
destroy_objective.owner = traitor
destroy_objective.find_target()
traitor.objectives += destroy_objective
+ traitor.targets += destroy_objective.target
else if(prob(5))
var/datum/objective/debrain/debrain_objective = new
debrain_objective.owner = traitor
debrain_objective.find_target()
traitor.objectives += debrain_objective
+ traitor.targets += debrain_objective.target
else if(prob(30))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = traitor
maroon_objective.find_target()
traitor.objectives += maroon_objective
+ traitor.targets += maroon_objective.target
else
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = traitor
kill_objective.find_target()
traitor.objectives += kill_objective
+ traitor.targets += kill_objective.target
else
var/datum/objective/steal/steal_objective = new
steal_objective.owner = traitor
steal_objective.find_target()
traitor.objectives += steal_objective
+ traitor.targets += steal_objective.steal_target
if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
if(!(locate(/datum/objective/hijack) in traitor.objectives))
@@ -208,11 +215,11 @@
/datum/game_mode/proc/give_codewords(mob/living/traitor_mob)
to_chat(traitor_mob, "The Syndicate provided you with the following information on how to identify their agents:")
- to_chat(traitor_mob, "Code Phrase: [syndicate_code_phrase]")
- to_chat(traitor_mob, "Code Response: [syndicate_code_response]")
+ to_chat(traitor_mob, "Code Phrase: [GLOB.syndicate_code_phrase]")
+ to_chat(traitor_mob, "Code Response: [GLOB.syndicate_code_response]")
- traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]")
- traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]")
+ traitor_mob.mind.store_memory("Code Phrase: [GLOB.syndicate_code_phrase]")
+ traitor_mob.mind.store_memory("Code Response: [GLOB.syndicate_code_response]")
to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.")
@@ -348,14 +355,14 @@
/datum/game_mode/proc/remove_traitor(datum/mind/traitor_mind)
if(traitor_mind in traitors)
- ticker.mode.traitors -= traitor_mind
+ SSticker.mode.traitors -= traitor_mind
traitor_mind.special_role = null
traitor_mind.current.create_attack_log("De-traitored")
if(issilicon(traitor_mind.current))
to_chat(traitor_mind.current, "You have been turned into a robot! You are no longer a traitor.")
else
to_chat(traitor_mind.current, "You have been brainwashed! You are no longer a traitor.")
- ticker.mode.update_traitor_icons_removed(traitor_mind)
+ SSticker.mode.update_traitor_icons_removed(traitor_mind)
/datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind)
var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR]
diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm
index 18d36ad57f3..5fc01686200 100644
--- a/code/game/gamemodes/vampire/vampire.dm
+++ b/code/game/gamemodes/vampire/vampire.dm
@@ -288,7 +288,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
else
H.LAssailant = owner
while(do_mob(owner, H, 50))
- if(!(owner.mind in ticker.mode.vampires))
+ if(!(owner.mind in SSticker.mode.vampires))
to_chat(owner, "Your fangs have disappeared!")
return
old_bloodtotal = bloodtotal
@@ -297,19 +297,27 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
to_chat(owner, "They've got no blood left to give.")
break
if(H.stat < DEAD)
- blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
- bloodtotal += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
- bloodusable += blood / 2
+ if(!issmall(H) || H.ckey)
+ blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
+ bloodtotal += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
+ bloodusable += blood / 2
else
- blood = min(5, H.blood_volume) // The dead only give 5 blood
- bloodtotal += blood
+ if(!issmall(H) || H.ckey)
+ blood = min(5, H.blood_volume) // The dead only give 5 blood
+ bloodtotal += blood
if(old_bloodtotal != bloodtotal)
- to_chat(owner, "You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].")
+ if(!issmall(H) || H.ckey) // not small OR has a ckey, monkeys with ckeys can be sucked, humanized monkeys can be sucked monkeys without ckeys cannot be sucked
+ to_chat(owner, "You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].")
check_vampire_upgrade()
H.blood_volume = max(H.blood_volume - 25, 0)
if(ishuman(owner))
var/mob/living/carbon/human/V = owner
- V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + (blood / 2))
+ if(issmall(H) && !H.ckey)
+ to_chat(V, "Feeding on [H] reduces your hunger, but you get no usable blood from it.")
+ V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + 5)
+ else
+ V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + (blood / 2))
+
draining = null
to_chat(owner, "You stop draining [H.name] of blood.")
@@ -337,7 +345,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
/datum/game_mode/proc/remove_vampire(datum/mind/vampire_mind)
if(vampire_mind in vampires)
- ticker.mode.vampires -= vampire_mind
+ SSticker.mode.vampires -= vampire_mind
vampire_mind.special_role = null
vampire_mind.current.create_attack_log("De-vampired")
if(vampire_mind.vampire)
@@ -347,7 +355,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
to_chat(vampire_mind.current, "You have been turned into a robot! You can feel your powers fading away...")
else
to_chat(vampire_mind.current, "You have been brainwashed! You are no longer a vampire.")
- ticker.mode.update_vampire_icons_removed(vampire_mind)
+ SSticker.mode.update_vampire_icons_removed(vampire_mind)
//prepare for copypaste
/datum/game_mode/proc/update_vampire_icons_added(datum/mind/vampire_mind)
@@ -402,11 +410,11 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
if(!hud.vampire_blood_display)
hud.vampire_blood_display = new /obj/screen()
hud.vampire_blood_display.name = "Usable Blood"
- hud.vampire_blood_display.icon_state = "power_display"
+ hud.vampire_blood_display.icon_state = "blood_display"
hud.vampire_blood_display.screen_loc = "WEST:6,CENTER-1:15"
hud.static_inventory += hud.vampire_blood_display
hud.show_hud(hud.hud_version)
- hud.vampire_blood_display.maptext = "
[bloodusable]
"
+ hud.vampire_blood_display.maptext = "
[bloodusable]
"
handle_vampire_cloak()
if(istype(owner.loc, /turf/space))
check_sun()
diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm
index f78520ac7eb..7e1a375f15d 100644
--- a/code/game/gamemodes/vampire/vampire_powers.dm
+++ b/code/game/gamemodes/vampire/vampire_powers.dm
@@ -156,6 +156,7 @@
user.SetWeakened(0)
user.SetStunned(0)
user.SetParalysis(0)
+ user.SetSleeping(0)
U.adjustStaminaLoss(-75)
to_chat(user, "You flush your system with clean blood and remove any incapacitating effects.")
spawn(1)
@@ -226,6 +227,7 @@
target.Weaken(5)
target.stuttering = 20
to_chat(target, "You are blinded by [user]'s glare.")
+ add_attack_logs(user, target, "(Vampire) Glared at")
/obj/effect/proc_holder/spell/vampire/self/shapeshift
name = "Shapeshift (50)"
@@ -259,8 +261,10 @@
for(var/mob/living/carbon/C in hearers(4))
if(C == user)
continue
- if(ishuman(C) && (C:l_ear || C:r_ear) && istype((C:l_ear || C:r_ear), /obj/item/clothing/ears/earmuffs))
- continue
+ if(ishuman(C))
+ var/mob/living/carbon/human/H = C
+ if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs))
+ continue
if(!affects(C))
continue
to_chat(C, "You hear a ear piercing shriek and your senses dull!")
@@ -275,7 +279,7 @@
/proc/isvampirethrall(mob/living/M as mob)
- return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.vampire_enthralled)
+ return istype(M) && M.mind && SSticker && SSticker.mode && (M.mind in SSticker.mode.vampire_enthralled)
/obj/effect/proc_holder/spell/vampire/targetted/enthrall
name = "Enthrall (300)"
@@ -314,11 +318,11 @@
if(!C.mind)
to_chat(user, "[C.name]'s mind is not there for you to enthrall.")
return 0
- if(enthrall_safe || ( C.mind in ticker.mode.vampires )||( C.mind.vampire )||( C.mind in ticker.mode.vampire_enthralled ))
+ if(enthrall_safe || ( C.mind in SSticker.mode.vampires )||( C.mind.vampire )||( C.mind in SSticker.mode.vampire_enthralled ))
C.visible_message("[C] seems to resist the takeover!", "You feel a familiar sensation in your skull that quickly dissipates.")
return 0
if(!affects(C))
- C.visible_message("[C] seems to resist the takeover!", "Your faith of [ticker.Bible_deity_name] has kept your mind clear of all evil.")
+ C.visible_message("[C] seems to resist the takeover!", "Your faith of [SSticker.Bible_deity_name] has kept your mind clear of all evil.")
return 0
if(!ishuman(C))
to_chat(user, "You can only enthrall humans!")
@@ -329,24 +333,32 @@
if(!istype(H))
return 0
var/ref = "\ref[user.mind]"
- if(!(ref in ticker.mode.vampire_thralls))
- ticker.mode.vampire_thralls[ref] = list(H.mind)
+ if(!(ref in SSticker.mode.vampire_thralls))
+ SSticker.mode.vampire_thralls[ref] = list(H.mind)
else
- ticker.mode.vampire_thralls[ref] += H.mind
+ SSticker.mode.vampire_thralls[ref] += H.mind
- ticker.mode.update_vampire_icons_added(H.mind)
- ticker.mode.update_vampire_icons_added(user.mind)
+ SSticker.mode.update_vampire_icons_added(H.mind)
+ SSticker.mode.update_vampire_icons_added(user.mind)
var/datum/mindslaves/slaved = user.mind.som
H.mind.som = slaved
slaved.serv += H
slaved.add_serv_hud(user.mind, "vampire")//handles master servent icons
slaved.add_serv_hud(H.mind, "vampthrall")
- ticker.mode.vampire_enthralled.Add(H.mind)
- ticker.mode.vampire_enthralled[H.mind] = user.mind
+ SSticker.mode.vampire_enthralled.Add(H.mind)
+ SSticker.mode.vampire_enthralled[H.mind] = user.mind
H.mind.special_role = SPECIAL_ROLE_VAMPIRE_THRALL
- to_chat(H, "You have been Enthralled by [user]. Follow [user.p_their()] every command.")
+
+ var/datum/objective/protect/serve_objective = new
+ serve_objective.owner = user.mind
+ serve_objective.target = H.mind
+ serve_objective.explanation_text = "You have been Enthralled by [user]. Follow [user.p_their()] every command."
+ H.mind.objectives += serve_objective
+
+ to_chat(H, "You have been Enthralled by [user]. Follow [user.p_their()] every command.")
to_chat(user, "You have successfully Enthralled [H]. If [H.p_they()] refuse[H.p_s()] to do as you say just adminhelp.")
+ H.Stun(2)
add_attack_logs(user, H, "Vampire-thralled")
@@ -437,9 +449,6 @@
steam.start()
sleep(jaunt_duration)
var/mobloc = get_turf(user.loc)
- if(get_area(mobloc) == /area/security/armoury/gamma)
- to_chat(user, "A strange energy repels you!")
- mobloc = originalloc
animation.loc = mobloc
steam.location = mobloc
steam.start()
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index dbe3146dd7f..1eedc354f5e 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -99,9 +99,9 @@
new_objective:target = H:mind
new_objective.explanation_text = "Protect [H.real_name], the wizard."
M.mind.objectives += new_objective
- ticker.mode.traitors += M.mind
+ SSticker.mode.traitors += M.mind
M.mind.special_role = SPECIAL_ROLE_WIZARD_APPRENTICE
- ticker.mode.update_wiz_icons_added(M.mind)
+ SSticker.mode.update_wiz_icons_added(M.mind)
M.faction = list("wizard")
else
used = 0
@@ -153,9 +153,13 @@
src.spawn_amt_left = spawn_amt
src.desc = desc
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
//return
+/obj/effect/rend/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
/obj/effect/rend/process()
for(var/mob/M in loc)
return
@@ -279,7 +283,7 @@ var/global/list/multiverse = list()
usr.mind.objectives += hijack_objective
hijack_objective.explanation_text = "Ensure only [usr.real_name] and [usr.p_their()] copies are on the shuttle!"
to_chat(usr, "Objective #[1]: [hijack_objective.explanation_text]")
- ticker.mode.traitors += usr.mind
+ SSticker.mode.traitors += usr.mind
usr.mind.special_role = "[usr.real_name] Prime"
evil = TRUE
else
@@ -289,7 +293,7 @@ var/global/list/multiverse = list()
new_objective.explanation_text = "Survive, and help defend the innocent from the mobs of multiverse clones."
to_chat(usr, "Objective #[1]: [new_objective.explanation_text]")
usr.mind.objectives += new_objective
- ticker.mode.traitors += usr.mind
+ SSticker.mode.traitors += usr.mind
usr.mind.special_role = "[usr.real_name] Prime"
evil = FALSE
else
@@ -633,9 +637,9 @@ var/global/list/multiverse = list()
if(M.stat != DEAD)
to_chat(user, "This artifact can only affect the dead!")
return
-
- if(!M.mind || !M.client)
- to_chat(user, "There is no soul connected to this body...")
+
+ if((!M.mind || !M.client) && !M.grab_ghost())
+ to_chat(user,"There is no soul connected to this body...")
return
check_spooky()//clean out/refresh the list
@@ -648,6 +652,7 @@ var/global/list/multiverse = list()
else
M.set_species(/datum/species/skeleton)
M.visible_message(" A massive amount of flesh sloughs off [M] and a skeleton rises up!")
+ M.grab_ghost() // yoinks the ghost if its not in the body
M.revive()
equip_skeleton(M)
spooky_scaries |= M
@@ -728,9 +733,8 @@ var/global/list/multiverse = list()
H.update_dna()
H.update_body()
-
+ H.grab_ghost()
H.revive()
-
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/clothing/head/kitty(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/clothing/under/schoolgirl(H), slot_w_uniform)
diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm
index bb62b7bebea..57a4f4e17de 100644
--- a/code/game/gamemodes/wizard/raginmages.dm
+++ b/code/game/gamemodes/wizard/raginmages.dm
@@ -3,36 +3,35 @@
config_tag = "raginmages"
required_players = 20
use_huds = 1
+ but_wait_theres_more = 1
var/max_mages = 0
- var/making_mage = 0
+ var/making_mage = FALSE
var/mages_made = 1
var/time_checked = 0
- var/players_per_mage = 6 // If the admin wants to tweak things or something
- but_wait_theres_more = 1
+ var/players_per_mage = 10 // If the admin wants to tweak things or something
var/delay_per_mage = 4200 // Every 7 minutes by default
var/time_till_chaos = 18000 // Half-hour in
/datum/game_mode/wizard/raginmages/announce()
to_chat(world, "The current game mode is - Ragin' Mages!")
- to_chat(world, "The Space Wizard Federation is pissed, help defeat all the space wizards!")
-
+ to_chat(world, "The Space Wizard Federation is pissed, crew must help defeat all the Space Wizards invading the station!")
/datum/game_mode/wizard/raginmages/greet_wizard(var/datum/mind/wizard, var/you_are=1)
if(you_are)
to_chat(wizard.current, "You are the Space Wizard!")
- to_chat(wizard.current, "The Space Wizards Federation has given you the following tasks:")
+ to_chat(wizard.current, "The Space Wizard Federation has given you the following tasks:")
var/obj_count = 1
+ to_chat(wizard.current, "Supreme Objective: Make sure the station pays for its actions against our diplomats. We might send more Wizards to the station if the situation is not developing in our favour.")
for(var/datum/objective/objective in wizard.objectives)
to_chat(wizard.current, "Objective #[obj_count]: [objective.explanation_text]")
obj_count++
- to_chat(wizard.current, "Objective Alpha: Make sure the station pays for its actions against our diplomats")
return
/datum/game_mode/wizard/raginmages/check_finished()
var/wizards_alive = 0
- // Accidental pun!
- var/wizard_cap = (max_mages || (num_players_started() / players_per_mage))
+ var/wizard_cap = CEILING((num_players_started() / players_per_mage), 1)
+ max_mages = wizard_cap
for(var/datum/mind/wizard in wizards)
if(isnull(wizard.current))
continue
@@ -115,71 +114,44 @@
qdel(B)
/datum/game_mode/wizard/raginmages/proc/make_more_mages()
-
if(making_mage || SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
- return 0
- making_mage = 1
- var/list/candidates = list()
+ return FALSE
+ making_mage = TRUE
+
+ var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a raging Space Wizard?", ROLE_WIZARD, TRUE, poll_time = 20 SECONDS)
var/mob/dead/observer/harry = null
- spawn(rand(200, 600))
- message_admins("SWF is still pissed, sending another wizard - [max_mages - mages_made] left.")
- //Protip: This returns clients, not ghosts
- candidates = get_candidate_ghosts(ROLE_WIZARD)
- if(!candidates.len)
- message_admins("No applicable clients for the next ragin' mage, asking ghosts instead.")
- var/time_passed = world.time
- for(var/mob/dead/observer/G in GLOB.player_list)
- if(!jobban_isbanned(G, "wizard") && !jobban_isbanned(G, "Syndicate"))
- spawn(0)
- switch(alert(G, "Do you wish to be considered for the position of Space Wizard Foundation 'diplomat'?","Please answer in 30 seconds!","Yes","No"))
- if("Yes")
- if((world.time-time_passed)>300)//If more than 30 game seconds passed.
- continue
- candidates += G
- if("No")
- continue
- sleep(300)
- if(!candidates.len)
- message_admins("This is awkward, sleeping until another mage check...")
- making_mage = 0
- return
+ message_admins("SWF is still pissed, sending another wizard - [max_mages - mages_made] left.")
+
+ if(!candidates.len)
+ message_admins("This is awkward, sleeping until another mage check..")
+ making_mage = FALSE
+ sleep(300)
+ return
+ else
+ harry = pick(candidates)
+ making_mage = FALSE
+ if(harry)
+ var/mob/living/carbon/human/new_character= makeBody(harry)
+ new_character.mind.make_Wizard() // This puts them at the wizard spawn, worry not
+ mages_made++
+ return TRUE
else
- candidates = shuffle(candidates)
- for(var/mob/dead/observer/i in candidates)
- if(!i) continue //Dont bother removing them from the list since we only grab one wizard
-
- // YER A WIZZERD HARRY
- harry = i
- break
-
- making_mage = 0
- if(harry)
- var/mob/living/carbon/human/new_character= makeBody(harry)
-
-
- new_character.mind.make_Wizard() // This puts them at the wizard spawn, worry not
- mages_made++
- return 1
- else
- log_runtime(EXCEPTION("The candidates list for ragin' mages contained non-observer entries!"), src)
- return 0
+ log_runtime(EXCEPTION("The candidates list for ragin' mages contained non-observer entries!"), src)
+ return FALSE
// ripped from -tg-'s wizcode, because whee lets make a very general proc for a very specific gamemode
// This probably wouldn't do half bad as a proc in __HELPERS
// Lemme know if this causes species to mess up spectacularly or anything
/datum/game_mode/wizard/raginmages/proc/makeBody(var/mob/dead/observer/G)
- if(!G || !G.key) return // Let's not steal someone's soul here
-
+ if(!G || !G.key)
+ return // Let's not steal someone's soul here
var/mob/living/carbon/human/new_character = new(pick(latejoin))
-
G.client.prefs.copy_to(new_character)
-
new_character.key = G.key
-
return new_character
/datum/game_mode/wizard/raginmages/declare_completion()
if(finished)
- feedback_set_details("round_end_result","raging wizard loss - wizard killed")
- to_chat(world, " The crew has managed to hold off the wizard attack! The Space Wizards Federation has been taught a lesson they will not soon forget!")
+ feedback_set_details("round_end_result", "raging wizard loss - wizard killed")
+ to_chat(world, " The crew has managed to hold off the Wizard attack! The Space Wizard Federation has been taught a lesson they will not soon forget!")
..(1)
diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm
index 9150f25736a..deb054f6d3e 100644
--- a/code/game/gamemodes/wizard/rightandwrong.dm
+++ b/code/game/gamemodes/wizard/rightandwrong.dm
@@ -1,12 +1,12 @@
-/mob/proc/rightandwrong(var/summon_type) //0 = Summon Guns, 1 = Summon Magic
- var/list/gunslist = list("taser","egun","laser","revolver","detective","c20r","nuclear","deagle","gyrojet","pulse","suppressed","cannon","doublebarrel","shotgun","combatshotgun","bulldog","mateba","sabr","crossbow","saw","car","boltaction","arg","uzi","turret","pulsecarbine","decloner","mindflayer","kinetic","advplasmacutter","wormhole","wt550","grenadelauncher","medibeam")
+/mob/proc/rightandwrong(summon_type, revolver_fight = FALSE, fake_revolver_fight = FALSE) //0 = Summon Guns, 1 = Summon Magic
+ var/list/gunslist = list("taser","egun","laser","revolver","detective","c20r","nuclear","deagle","gyrojet","pulse","suppressed","cannon","doublebarrel","shotgun","combatshotgun","bulldog","mateba","sabr","crossbow","saw","car","boltaction","arg","uzi","turret","pulsecarbine","decloner","mindflayer","kinetic","advplasmacutter","wormhole","wt550","grenadelauncher","medibeam", "fakerevolver")
var/list/magiclist = list("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","charge", "summonitem", "wandnothing", "wanddeath", "wandresurrection", "wandpolymorph", "wandteleport", "wanddoor", "wandfireball", "staffhealing", "armor", "scrying", "staffdoor", "special","voodoo","special")
var/list/magicspeciallist = list("staffchange","staffanimation", "wandbelt", "contract", "staffchaos","necromantic")
to_chat(usr, "You summoned [summon_type ? "magic" : "guns"]!")
- message_admins("[key_name_admin(usr)] summoned [summon_type ? "magic" : "guns"]!")
+ message_admins("[key_name_admin(usr)] summoned [summon_type ? "magic" : "guns"]! ([revolver_fight ? "Revolver duel!" : ""] [fake_revolver_fight ? "Suicidal revolver duel!" : ""])")
for(var/mob/living/carbon/human/H in GLOB.player_list)
if(H.stat == 2 || !(H.client))
@@ -17,6 +17,13 @@
var/randomizeguns = pick(gunslist)
var/randomizemagic = pick(magiclist)
var/randomizemagicspecial = pick(magicspeciallist)
+ if(revolver_fight)
+ randomizeguns = "revolver"
+ if(fake_revolver_fight)
+ if(prob(50))
+ randomizeguns = "revolver"
+ else
+ randomizeguns = "fakerevolver"
if(!summon_type)
switch(randomizeguns)
if("taser")
@@ -88,6 +95,8 @@
new /obj/item/gun/projectile/revolver/grenadelauncher(get_turf(H))
if("medibeam")
new /obj/item/gun/medbeam(get_turf(H))
+ if("fakerevolver")
+ new /obj/item/toy/russian_revolver/trick_revolver(get_turf(H)) //lol
playsound(get_turf(H), 'sound/magic/summon_guns.ogg', 50, 1)
else
@@ -137,7 +146,8 @@
H.mutations.Add(XRAY)
H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
H.see_in_dark = 8
- H.see_invisible = SEE_INVISIBLE_LEVEL_TWO
+ H.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ H.update_sight()
to_chat(H, "The walls suddenly disappear.")
if("voodoo")
new /obj/item/voodoo(get_turf(H))
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index 3e22f3f84df..a71b51c58f0 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -273,11 +273,11 @@
Z.key = A.key
Z.faction |= "\ref[U]"
if(iscultist(U))
- if(ticker.mode.name == "cult")
- ticker.mode:add_cultist(Z.mind)
+ if(SSticker.mode.name == "cult")
+ SSticker.mode:add_cultist(Z.mind)
else
- ticker.mode.cult+=Z.mind
- ticker.mode.update_cult_icons_added(Z.mind)
+ SSticker.mode.cult+=Z.mind
+ SSticker.mode.update_cult_icons_added(Z.mind)
qdel(T)
to_chat(Z, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike.")
to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.")
@@ -289,11 +289,11 @@
Z.key = A.key
Z.faction |= "\ref[U]"
if(iscultist(U))
- if(ticker.mode.name == "cult")
- ticker.mode:add_cultist(Z.mind)
+ if(SSticker.mode.name == "cult")
+ SSticker.mode:add_cultist(Z.mind)
else
- ticker.mode.cult+=Z.mind
- ticker.mode.update_cult_icons_added(Z.mind)
+ SSticker.mode.cult+=Z.mind
+ SSticker.mode.update_cult_icons_added(Z.mind)
qdel(T)
to_chat(Z, "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.")
to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.")
@@ -305,11 +305,11 @@
Z.key = A.key
Z.faction |= "\ref[U]"
if(iscultist(U))
- if(ticker.mode.name == "cult")
- ticker.mode:add_cultist(Z.mind)
+ if(SSticker.mode.name == "cult")
+ SSticker.mode:add_cultist(Z.mind)
else
- ticker.mode.cult+=Z.mind
- ticker.mode.update_cult_icons_added(Z.mind)
+ SSticker.mode.cult+=Z.mind
+ SSticker.mode.update_cult_icons_added(Z.mind)
qdel(T)
to_chat(Z, "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone).")
to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.")
@@ -326,11 +326,11 @@
newstruct.faction |= "\ref[stoner]"
newstruct.key = target.key
if(stoner && iscultist(stoner) || cultoverride)
- if(ticker.mode.name == "cult")
- ticker.mode:add_cultist(newstruct.mind)
+ if(SSticker.mode.name == "cult")
+ SSticker.mode:add_cultist(newstruct.mind)
else
- ticker.mode.cult+=newstruct.mind
- ticker.mode.update_cult_icons_added(newstruct.mind)
+ SSticker.mode.cult+=newstruct.mind
+ SSticker.mode.update_cult_icons_added(newstruct.mind)
if(stoner && iswizard(stoner))
to_chat(newstruct, "You are still bound to serve your creator, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.")
else if(stoner && iscultist(stoner))
@@ -357,7 +357,7 @@
if(U)
S.faction |= "\ref[U]" //Add the master as a faction, allowing inter-mob cooperation
if(U && iscultist(U))
- ticker.mode.add_cultist(S.mind, 0)
+ SSticker.mode.add_cultist(S.mind, 0)
S.cancel_camera()
name = "soulstone: Shade of [T.real_name]"
icon_state = "soulstone2"
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index e7893c3f84e..6f96d4c22e2 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -229,6 +229,12 @@
log_name = "LD"
category = "Defensive"
+/datum/spellbook_entry/lichdom/IsAvailible()
+ if(SSticker.mode.name == "ragin' mages")
+ return FALSE
+ else
+ return TRUE
+
/datum/spellbook_entry/lightningbolt
name = "Lightning Bolt"
spell_type = /obj/effect/proc_holder/spell/targeted/lightning
@@ -333,7 +339,7 @@
user.mutations.Add(XRAY)
user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
user.see_in_dark = 8
- user.see_invisible = SEE_INVISIBLE_LEVEL_TWO
+ user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
to_chat(user, "The walls suddenly disappear.")
return 1
@@ -398,8 +404,8 @@
name = "Bottle of Tickles"
desc = "A bottle of magically infused fun, the smell of which will \
attract adorable extradimensional beings when broken. These beings \
- are similar to slaughter demons, but they do not permamently kill \
- their victims, instead putting them in an extradimensional hugspace, \
+ are similar to slaughter demons, but are a little weaker and they do not permamently \
+ kill their victims, instead putting them in an extradimensional hugspace, \
to be released on the demon's death. Chaotic, but not ultimately \
damaging. The crew's reaction to the other hand could be very \
destructive."
@@ -409,8 +415,17 @@
limit = 3
category = "Assistance"
+/datum/spellbook_entry/item/oozebottle
+ name = "Bottle of Ooze"
+ desc = "A bottle of magically infused ooze, which will awake an all-consuming Morph, capable of cunningly disguising itself as any object it comes in contact with and even casting some very basic spells. Be careful though, as Morph diet includes Wizards."
+ item_path = /obj/item/antag_spawner/morph
+ cost = 1
+ log_name = "BO"
+ limit = 3
+ category = "Assistance"
+
/datum/spellbook_entry/item/tarotdeck
- name = "Tarot Deck"
+ name = "Guardian Deck"
desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \
It would be wise to avoid buying these with anything capable of causing you to swap bodies with others."
item_path = /obj/item/guardiancreator
@@ -430,14 +445,6 @@
item_path = /obj/item/twohanded/singularityhammer
log_name = "SI"
-/datum/spellbook_entry/item/cursed_heart
- name = "Cursed Heart"
- desc = "A heart that has been revived by dark magicks. The user must ensure the heart is manually beaten or their blood circulation will suffer, but every beat heals their injuries. It must beat every 6 seconds."
- item_path = /obj/item/organ/internal/heart/cursed/wizard
- log_name = "CH"
- cost = 1
- category = "Defensive"
-
/datum/spellbook_entry/summon
name = "Summon Stuff"
category = "Rituals"
@@ -460,20 +467,40 @@
dat += "Already cast! "
return dat
+/datum/spellbook_entry/summon/ghosts
+ name = "Summon Ghosts"
+ desc = "Spook the crew out by making them see dead people. Be warned, ghosts are capricious and occasionally vindicative, and some will use their incredibly minor abilities to frustrate you."
+ cost = 0
+ log_name = "SGH"
+
+/datum/spellbook_entry/summon/ghosts/IsAvailible()
+ if(!SSticker.mode) // In case spellbook is placed on map
+ return FALSE
+ if(SSticker.mode.name == "ragin' mages")
+ return FALSE
+ else
+ return TRUE
+
+/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
+ new /datum/event/wizard/ghost()
+ active = TRUE
+ to_chat(user, "You have cast summon ghosts!")
+ playsound(get_turf(user), 'sound/effects/ghost2.ogg', 50, 1)
+ return TRUE
+
/datum/spellbook_entry/summon/guns
name = "Summon Guns"
- category = "Rituals"
- desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. Just be careful not to stand still too long!"
+ desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. Just be careful not to stand still too long! You will also receive 1 extra point to use in your spellbook."
cost = 0
log_name = "SG"
/datum/spellbook_entry/summon/guns/IsAvailible()
- if(!ticker.mode) // In case spellbook is placed on map
- return 0
- if(ticker.mode.name == "ragin' mages")
- return 0
+ if(!SSticker.mode) // In case spellbook is placed on map
+ return FALSE
+ if(SSticker.mode.name == "ragin' mages")
+ return FALSE
else
- return 1
+ return TRUE
/datum/spellbook_entry/summon/guns/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
feedback_add_details("wizard_spell_learned",log_name)
@@ -485,18 +512,17 @@
/datum/spellbook_entry/summon/magic
name = "Summon Magic"
- category = "Challenges"
- desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time."
+ desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time. You will also receive 1 extra point to use in your spellbook."
cost = 0
log_name = "SU"
/datum/spellbook_entry/summon/magic/IsAvailible()
- if(!ticker.mode) // In case spellbook is placed on map
- return 0
- if(ticker.mode.name == "ragin' mages")
- return 0
+ if(!SSticker.mode) // In case spellbook is placed on map
+ return FALSE
+ if(SSticker.mode.name == "ragin' mages")
+ return FALSE
else
- return 1
+ return TRUE
/datum/spellbook_entry/summon/magic/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
feedback_add_details("wizard_spell_learned",log_name)
@@ -584,9 +610,6 @@
dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased. "
dat += "For spells: the number after the spell name is the cooldown time. "
dat += "You can reduce this number by spending more points on the spell. "
- if("Challenges")
- dat += "The Wizard Federation typically has hard limits on the potency and number of spells brought to the station based on risk. "
- dat += "Arming the station against you will increases the risk, but will grant you one more charge for your spellbook. "
if("Rituals")
dat += "These powerful spells change the very fabric of reality. Not always in your favour. "
return dat
@@ -883,3 +906,13 @@
spellname = "sacred flame"
icon_state ="booksacredflame"
desc = "Become one with the flames that burn within... and invite others to do so as well."
+
+/obj/item/spellbook/oneuse/random
+ icon_state = "random_book"
+
+/obj/item/spellbook/oneuse/random/initialize()
+ . = ..()
+ var/static/banned_spells = list(/obj/item/spellbook/oneuse/mime, /obj/item/spellbook/oneuse/mime/fingergun, /obj/item/spellbook/oneuse/mime/fingergun/fake, /obj/item/spellbook/oneuse/mime/greaterwall)
+ var/real_type = pick(subtypesof(/obj/item/spellbook/oneuse) - banned_spells)
+ new real_type(loc)
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index b249ebe8520..131afd84fff 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -7,9 +7,8 @@
required_players = 20
required_enemies = 1
recommended_enemies = 1
- free_golems_disabled = TRUE
+ var/use_huds = 1
- var/use_huds = 0
var/finished = 0
var/but_wait_theres_more = 0
@@ -17,7 +16,6 @@
to_chat(world, "The current game mode is - Wizard!")
to_chat(world, "There is a SPACE WIZARD on the station. You can't let him achieve his objective!")
-
/datum/game_mode/wizard/can_start()//This could be better, will likely have to recode it later
if(!..())
return 0
@@ -42,7 +40,6 @@
..()
return 1
-
/datum/game_mode/wizard/post_setup()
for(var/datum/mind/wizard in wizards)
log_game("[key_name(wizard)] has been selected as a Wizard")
@@ -58,7 +55,7 @@
/datum/game_mode/proc/remove_wizard(datum/mind/wizard_mind)
if(wizard_mind in wizards)
- ticker.mode.wizards -= wizard_mind
+ SSticker.mode.wizards -= wizard_mind
wizard_mind.special_role = null
wizard_mind.current.create_attack_log("De-wizarded")
wizard_mind.current.spellremove(wizard_mind.current)
@@ -67,14 +64,13 @@
to_chat(wizard_mind.current, "You have been turned into a robot! You can feel your magical powers fading away...")
else
to_chat(wizard_mind.current, "You have been brainwashed! You are no longer a wizard.")
- ticker.mode.update_wiz_icons_removed(wizard_mind)
+ SSticker.mode.update_wiz_icons_removed(wizard_mind)
/datum/game_mode/proc/update_wiz_icons_added(datum/mind/wiz_mind)
var/datum/atom_hud/antag/wizhud = huds[ANTAG_HUD_WIZ]
wizhud.join_hud(wiz_mind.current)
set_antag_hud(wiz_mind.current, ((wiz_mind in wizards) ? "hudwizard" : "apprentice"))
-
/datum/game_mode/proc/update_wiz_icons_removed(datum/mind/wiz_mind)
var/datum/atom_hud/antag/wizhud = huds[ANTAG_HUD_WIZ]
wizhud.leave_hud(wiz_mind.current)
@@ -86,7 +82,6 @@
wizard.objectives += wiz_objective
return
-
/datum/game_mode/proc/name_wizard(mob/living/carbon/human/wizard_mob)
//Allows the wizard to choose a custom name or go with a random one. Spawn 0 so it does not lag the round starting.
var/wizard_name_first = pick(GLOB.wizard_first)
@@ -104,7 +99,6 @@
wizard_mob.mind.name = newname
return
-
/datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1)
addtimer(CALLBACK(wizard.current, /mob/.proc/playsound_local, null, 'sound/ambience/antag/ragesmages.ogg', 100, 0), 30)
if(you_are)
@@ -117,7 +111,6 @@
obj_count++
return
-
/*/datum/game_mode/proc/learn_basic_spells(mob/living/carbon/human/wizard_mob)
if(!istype(wizard_mob))
return
@@ -165,23 +158,30 @@
wizard_mob.gene_stability += DEFAULT_GENE_STABILITY //magic
return 1
-
+// Checks if the game should end due to all wizards and apprentices being dead, or MMI'd/Borged
/datum/game_mode/wizard/check_finished()
var/wizards_alive = 0
var/traitors_alive = 0
+
+ // Wizards
for(var/datum/mind/wizard in wizards)
if(!istype(wizard.current,/mob/living/carbon))
continue
if(wizard.current.stat==DEAD)
continue
+ if(istype(wizard.current, /obj/item/mmi)) // wizard is in an MMI, don't count them as alive
+ continue
wizards_alive++
+ // Apprentices - classified as "traitors"
if(!wizards_alive)
for(var/datum/mind/traitor in traitors)
if(!istype(traitor.current,/mob/living/carbon))
continue
if(traitor.current.stat==DEAD)
continue
+ if(istype(traitor.current, /obj/item/mmi)) // apprentice is in an MMI, don't count them as alive
+ continue
traitors_alive++
if(wizards_alive || traitors_alive || but_wait_theres_more)
@@ -190,8 +190,6 @@
finished = 1
return 1
-
-
/datum/game_mode/wizard/declare_completion(var/ragin = 0)
if(finished && !ragin)
feedback_set_details("round_end_result","wizard loss - wizard killed")
@@ -199,7 +197,6 @@
..()
return 1
-
/datum/game_mode/proc/auto_declare_completion_wizard()
if(wizards.len)
var/text = " the wizards/witches were:"
@@ -282,4 +279,4 @@ Made a proc so this is not repeated 14 (or more) times.*/
return 1
/proc/iswizard(mob/living/M as mob)
- return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.wizards)
+ return istype(M) && M.mind && SSticker && SSticker.mode && (M.mind in SSticker.mode.wizards)
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index 7e3013658c8..a31f694f7fc 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -126,7 +126,7 @@ var/const/access_free_golems = 300
var/acc = M.get_access() //see mob.dm
- if(acc == IGNORE_ACCESS)
+ if(acc == IGNORE_ACCESS || M.can_admin_interact())
return 1 //Mob ignores access
else
@@ -601,28 +601,29 @@ proc/get_all_job_icons() //For all existing HUD icons
return GLOB.joblist + list("Prisoner")
/obj/proc/GetJobName() //Used in secHUD icon generation
- var/obj/item/card/id/I
+ var/assignmentName = "Unknown"
+ var/rankName = "Unknown"
if(istype(src, /obj/item/pda))
var/obj/item/pda/P = src
- I = P.id
+ assignmentName = P.ownjob
+ rankName = P.ownrank
else if(istype(src, /obj/item/card/id))
- I = src
+ var/obj/item/card/id/I = src
+ assignmentName = I.assignment
+ rankName = I.rank
+
- if(I)
- var/job_icons = get_all_job_icons()
- var/centcom = get_all_centcom_jobs()
+ var/job_icons = get_all_job_icons()
+ var/centcom = get_all_centcom_jobs()
- if(I.assignment in centcom) //Return with the NT logo if it is a Centcom job
- return "Centcom"
- if(I.rank in centcom)
- return "Centcom"
-
- if(I.assignment in job_icons) //Check if the job has a hud icon
- return I.assignment
- if(I.rank in job_icons)
- return I.rank
-
- else
- return
+ if(assignmentName in centcom) //Return with the NT logo if it is a Centcom job
+ return "Centcom"
+ if(rankName in centcom)
+ return "Centcom"
+ if(assignmentName in job_icons) //Check if the job has a hud icon
+ return assignmentName
+ if(rankName in job_icons)
+ return rankName
+
return "Unknown" //Return unknown if none of the above apply
diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm
index e2cffabcfd0..ecae6919813 100644
--- a/code/game/jobs/job/engineering.dm
+++ b/code/game/jobs/job/engineering.dm
@@ -18,8 +18,8 @@
access_heads, access_construction, access_sec_doors,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_minisat, access_mechanic, access_mineral_storeroom)
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_ENGINEERING
outfit = /datum/outfit/job/chief_engineer
/datum/outfit/job/chief_engineer
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 61e458927e9..eebe4f2e9e4 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -235,9 +235,9 @@
return 1
/datum/outfit/job/proc/imprint_idcard(mob/living/carbon/human/H)
- var/datum/job/J = job_master.GetJobType(jobtype)
+ var/datum/job/J = SSjobs.GetJobType(jobtype)
if(!J)
- J = job_master.GetJob(H.job)
+ J = SSjobs.GetJob(H.job)
var/alt_title
if(H.mind)
@@ -256,6 +256,8 @@
if(H.mind && H.mind.initial_account)
C.associated_account_number = H.mind.initial_account.account_number
+ C.owner_uid = H.UID()
+ C.owner_ckey = H.ckey
/datum/outfit/job/proc/imprint_pda(mob/living/carbon/human/H)
var/obj/item/pda/PDA = H.wear_pda
@@ -265,3 +267,10 @@
PDA.ownjob = C.assignment
PDA.ownrank = C.rank
PDA.name = "PDA-[H.real_name] ([PDA.ownjob])"
+
+/datum/job/proc/would_accept_job_transfer_from_player(mob/player)
+ if(!guest_jobbans(title)) // actually checks if job is a whitelisted position
+ return TRUE
+ if(!istype(player))
+ return FALSE
+ return is_job_whitelisted(player, title)
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index aaf1a61a2a1..49e6b4486ac 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -16,8 +16,8 @@
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_sec_doors, access_psychiatrist, access_maint_tunnels, access_paramedic, access_mineral_storeroom)
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_MEDICAL
outfit = /datum/outfit/job/cmo
/datum/outfit/job/cmo
diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm
index a1711bf4fd8..435565434c8 100644
--- a/code/game/jobs/job/science.dm
+++ b/code/game/jobs/job/science.dm
@@ -18,8 +18,8 @@
access_research, access_robotics, access_xenobiology, access_ai_upload,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_minisat, access_maint_tunnels, access_mineral_storeroom, access_network)
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_SCIENCE
// All science-y guys get bonuses for maxing out their tech.
required_objectives = list(
/datum/job_objective/further_research
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index b425532bf30..407393eb489 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -18,8 +18,8 @@
access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_pilot, access_weapons)
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_SECURITY
disabilities_allowed = 0
outfit = /datum/outfit/job/hos
diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm
index 0def40bc7b1..c239c1d3b3b 100644
--- a/code/game/jobs/job/silicon.dm
+++ b/code/game/jobs/job/silicon.dm
@@ -9,8 +9,8 @@
department_head = list("Captain")
req_admin_notify = 1
minimal_player_age = 30
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_SILICON
/datum/job/ai/equip(mob/living/carbon/human/H)
if(!H)
diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm
index 3cdbb9b7247..3208e9d3533 100644
--- a/code/game/jobs/job/supervisor.dm
+++ b/code/game/jobs/job/supervisor.dm
@@ -13,8 +13,8 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0)
access = list() //See get_access()
minimal_access = list() //See get_access()
minimal_player_age = 30
- exp_requirements = 2400
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_COMMAND
disabilities_allowed = 0
outfit = /datum/outfit/job/captain
@@ -24,7 +24,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0)
/datum/job/captain/announce(mob/living/carbon/human/H)
. = ..()
captain_announcement.Announce("All hands, Captain [H.real_name] on deck!")
- callHook("captain_spawned", list("captain" = H))
+ updateDisplaycase(H)
/datum/outfit/job/captain
name = "Captain"
@@ -68,8 +68,8 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0)
req_admin_notify = 1
is_command = 1
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_COMMAND
access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm
index fe5d7799582..22c2d47e3b9 100644
--- a/code/game/jobs/job/support.dm
+++ b/code/game/jobs/job/support.dm
@@ -160,8 +160,8 @@
title = "Shaft Miner"
flag = MINER
department_flag = SUPPORT
- total_positions = 3
- spawn_positions = 3
+ total_positions = 6
+ spawn_positions = 8
is_supply = 1
supervisors = "the quartermaster"
department_head = list("Head of Personnel")
@@ -175,23 +175,56 @@
name = "Shaft Miner"
jobtype = /datum/job/mining
- uniform = /obj/item/clothing/under/rank/miner
- gloves = /obj/item/clothing/gloves/fingerless
- shoes = /obj/item/clothing/shoes/workboots
+ uniform = /obj/item/clothing/under/rank/miner/lavaland
+ gloves = /obj/item/clothing/gloves/color/black
+ shoes = /obj/item/clothing/shoes/workboots/mining
l_ear = /obj/item/radio/headset/headset_cargo/mining
id = /obj/item/card/id/supply
- l_pocket = /obj/item/reagent_containers/food/pill/patch/styptic
+ l_pocket = /obj/item/reagent_containers/hypospray/autoinjector/survival
r_pocket = /obj/item/flashlight/seclite
pda = /obj/item/pda/shaftminer
backpack_contents = list(
- /obj/item/mining_voucher = 1,
- /obj/item/storage/bag/ore = 1
+ /obj/item/storage/bag/ore=1,\
+ /obj/item/kitchen/knife/combat/survival=1,\
+ /obj/item/mining_voucher=1,\
+ /obj/item/stack/marker_beacon/ten=1
+ )
+
+ backpack = /obj/item/storage/backpack/explorer
+ satchel = /obj/item/storage/backpack/explorer
+
+/datum/outfit/job/mining/equipped
+ name = "Shaft Miner"
+
+ suit = /obj/item/clothing/suit/hooded/explorer
+ mask = /obj/item/clothing/mask/gas/explorer
+ glasses = /obj/item/clothing/glasses/meson
+ suit_store = /obj/item/tank/emergency_oxygen
+ internals_slot = slot_s_store
+ backpack_contents = list(
+ /obj/item/flashlight/seclite=1,\
+ /obj/item/kitchen/knife/combat/survival=1,
+ /obj/item/mining_voucher=1,
+ /obj/item/t_scanner/adv_mining_scanner/lesser=1,
+ /obj/item/gun/energy/kinetic_accelerator=1,\
+ /obj/item/stack/marker_beacon/ten=1
)
- backpack = /obj/item/storage/backpack/industrial
- satchel = /obj/item/storage/backpack/satchel_eng
+ backpack = /obj/item/storage/backpack/explorer
+ satchel = /obj/item/storage/backpack/explorer
+/datum/outfit/job/miner/equipped/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ ..()
+ if(visualsOnly)
+ return
+ if(istype(H.wear_suit, /obj/item/clothing/suit/hooded))
+ var/obj/item/clothing/suit/hooded/S = H.wear_suit
+ S.ToggleHood()
+/datum/outfit/job/miner/equipped/hardsuit
+ name = "Shaft Miner (Equipment + Hardsuit)"
+ suit = /obj/item/clothing/suit/space/hardsuit/mining
+ mask = /obj/item/clothing/mask/breath
//Griff //BS12 EDIT
diff --git a/code/game/jobs/job/support_chaplain.dm b/code/game/jobs/job/support_chaplain.dm
index 73ec2483af1..ac393e277a8 100644
--- a/code/game/jobs/job/support_chaplain.dm
+++ b/code/game/jobs/job/support_chaplain.dm
@@ -158,11 +158,11 @@
to_chat(H, "Welp, out of time, buddy. You're stuck. Next time choose faster.")
accepted = 1
- if(ticker)
- ticker.Bible_icon_state = B.icon_state
- ticker.Bible_item_state = B.item_state
- ticker.Bible_name = B.name
- ticker.Bible_deity_name = B.deity_name
+ if(SSticker)
+ SSticker.Bible_icon_state = B.icon_state
+ SSticker.Bible_item_state = B.item_state
+ SSticker.Bible_name = B.name
+ SSticker.Bible_deity_name = B.deity_name
feedback_set_details("religion_deity", "[new_deity]")
feedback_set_details("religion_book", "[new_book_style]")
diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm
index fa13fbdb4b7..359981ded4f 100644
--- a/code/game/jobs/job_exp.dm
+++ b/code/game/jobs/job_exp.dm
@@ -72,7 +72,7 @@ var/global/list/role_playtime_requirements = list(
jtext = "-"
if(C.mob.mind && C.mob.mind.assigned_role)
- theirjob = job_master.GetJob(C.mob.mind.assigned_role)
+ theirjob = SSjobs.GetJob(C.mob.mind.assigned_role)
if(theirjob)
jtext = theirjob.title
msg += "
[jtext]
"
@@ -100,6 +100,7 @@ var/global/list/role_playtime_requirements = list(
// Procs
/proc/role_available_in_playtime(client/C, role)
+ // "role" is a special role defined in role_playtime_requirements above. e.g: ROLE_ERT. This is *not* a job title.
if(!C)
return 0
if(!role)
@@ -121,6 +122,7 @@ var/global/list/role_playtime_requirements = list(
return req_mins
return max(0, req_mins - my_exp)
+
/datum/job/proc/available_in_playtime(client/C)
if(!C)
return 0
@@ -178,7 +180,7 @@ var/global/list/role_playtime_requirements = list(
if(config.use_exp_restrictions)
var/list/jobs_locked = list()
var/list/jobs_unlocked = list()
- for(var/datum/job/job in job_master.occupations)
+ for(var/datum/job/job in SSjobs.occupations)
if(job.exp_requirements && job.exp_type)
if(!job.available_in_playtime(mob.client))
jobs_unlocked += job.title
@@ -255,13 +257,19 @@ var/global/list/role_playtime_requirements = list(
play_records[rtype] = text2num(read_records[rtype])
else
play_records[rtype] = 0
- if(mob.stat == CONSCIOUS && mob.mind.assigned_role)
+ var/myrole
+ if(mob.mind)
+ if(mob.mind.playtime_role)
+ myrole = mob.mind.playtime_role
+ else if(mob.mind.assigned_role)
+ myrole = mob.mind.assigned_role
+ if(mob.stat == CONSCIOUS && myrole)
play_records[EXP_TYPE_LIVING] += minutes
if(announce_changes)
to_chat(mob,"You got: [minutes] Living EXP!")
for(var/category in exp_jobsmap)
if(exp_jobsmap[category]["titles"])
- if(mob.mind.assigned_role in exp_jobsmap[category]["titles"])
+ if(myrole in exp_jobsmap[category]["titles"])
play_records[category] += minutes
if(announce_changes)
to_chat(mob,"You got: [minutes] [category] EXP!")
@@ -284,12 +292,3 @@ var/global/list/role_playtime_requirements = list(
log_game("SQL ERROR during exp_update_client write. Error : \[[err]\]\n")
message_admins("SQL ERROR during exp_update_client write. Error : \[[err]\]\n")
return
-
-/hook/roundstart/proc/exptimer()
- if(!config.sql_enabled || !config.use_exp_tracking)
- return 1
- spawn(0)
- while(TRUE)
- sleep(5 MINUTES)
- update_exp(5,0)
- return 1
diff --git a/code/game/jobs/job_objective.dm b/code/game/jobs/job_objective.dm
index 90bac6d8383..48fa911bcf5 100644
--- a/code/game/jobs/job_objective.dm
+++ b/code/game/jobs/job_objective.dm
@@ -44,12 +44,12 @@
/datum/game_mode/proc/declare_job_completion()
var/text = "Job Completion"
- for(var/datum/mind/employee in ticker.minds)
+ for(var/datum/mind/employee in SSticker.minds)
if(!employee.job_objectives.len)//If the employee had no objectives, don't need to process this.
continue
- if(employee.assigned_role == employee.special_role) //If the character is an offstation character, skip them.
+ if(employee.assigned_role == employee.special_role || employee.offstation_role) //If the character is an offstation character, skip them.
continue
var/tasks_completed=0
diff --git a/code/game/jobs/job_scaling.dm b/code/game/jobs/job_scaling.dm
index 89bd8374351..90d55b03444 100644
--- a/code/game/jobs/job_scaling.dm
+++ b/code/game/jobs/job_scaling.dm
@@ -5,7 +5,7 @@
if(playercount >= highpop_trigger)
log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - loading highpop job config");
- job_master.LoadJobs("config/jobs_highpop.txt")
+ SSjobs.LoadJobs("config/jobs_highpop.txt")
else
log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - keeping standard job config");
return 1
\ No newline at end of file
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 2ee1e93683d..af73a13f27c 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -99,7 +99,7 @@
icon_state = "table2-idle"
return 0
-/obj/machinery/optable/Crossed(atom/movable/AM)
+/obj/machinery/optable/Crossed(atom/movable/AM, oldloc)
. = ..()
if(iscarbon(AM) && LAZYLEN(injected_reagents))
to_chat(AM, "You feel a series of tiny pricks!")
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 917c198af2f..c447ff26e72 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -149,7 +149,7 @@
occupantData["stat"] = occupant.stat
occupantData["health"] = occupant.health
occupantData["maxHealth"] = occupant.maxHealth
- occupantData["minHealth"] = config.health_threshold_dead
+ occupantData["minHealth"] = HEALTH_THRESHOLD_DEAD
occupantData["bruteLoss"] = occupant.getBruteLoss()
occupantData["oxyLoss"] = occupant.getOxyLoss()
occupantData["toxLoss"] = occupant.getToxLoss()
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index 679af70526e..b7e24014f1e 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -459,8 +459,8 @@
organData["germ_level"] = I.germ_level
organData["damage"] = I.damage
organData["maxHealth"] = I.max_damage
- organData["bruised"] = I.min_broken_damage
- organData["broken"] = I.min_bruised_damage
+ organData["bruised"] = I.min_bruised_damage
+ organData["broken"] = I.min_broken_damage
organData["robotic"] = I.is_robotic()
organData["dead"] = (I.status & ORGAN_DEAD)
diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm
index 8a65da977ae..71202f8c536 100644
--- a/code/game/machinery/ai_slipper.dm
+++ b/code/game/machinery/ai_slipper.dm
@@ -1,8 +1,9 @@
/obj/machinery/ai_slipper
name = "\improper AI liquid dispenser"
icon = 'icons/obj/device.dmi'
- icon_state = "motion3"
+ icon_state = "liquid_dispenser"
layer = 3
+ plane = FLOOR_PLANE
anchored = 1.0
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0)
var/uses = 20
@@ -16,14 +17,14 @@
/obj/machinery/ai_slipper/power_change()
if(stat & BROKEN)
- return
+ update_icon()
else
if( powered() )
stat &= ~NOPOWER
else
- icon_state = "motion0"
stat |= NOPOWER
disabled = TRUE
+ update_icon()
/obj/machinery/ai_slipper/proc/setState(var/enabled, var/uses)
disabled = disabled
@@ -55,7 +56,7 @@
if(stat & (NOPOWER|BROKEN))
return
disabled = !disabled
- icon_state = disabled? "motion0":"motion3"
+ update_icon()
/obj/machinery/ai_slipper/proc/Activate()
if(stat & (NOPOWER|BROKEN))
@@ -69,6 +70,12 @@
cooldown_time = world.timeofday + 100
slip_process()
+/obj/machinery/ai_slipper/update_icon()
+ if(stat & (NOPOWER|BROKEN) || disabled)
+ icon_state = "liquid_dispenser"
+ else
+ icon_state = "liquid_dispenser_on"
+
/obj/machinery/ai_slipper/attack_ai(mob/user)
return attack_hand(user)
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index db5c2b6e9c3..52cd5bdfee8 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -81,12 +81,13 @@
power_channel = ENVIRON
req_one_access = list(access_atmospherics, access_engine_equip)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100)
+ siemens_strength = 1
var/alarm_id = null
var/frequency = ATMOS_VENTSCRUB
//var/skipprocess = 0 //Experimenting
var/alarm_frequency = ATMOS_FIRE_FREQ
- var/remote_control = 0
- var/rcon_setting = 2
+ var/remote_control = TRUE
+ var/rcon_setting = RCON_AUTO
var/rcon_time = 0
var/locked = 1
var/datum/wires/alarm/wires = null
@@ -97,7 +98,7 @@
// Waiting on a device to respond.
// Specifies an id_tag. NULL means we aren't waiting.
- var/waiting_on_device=null
+ var/waiting_on_device = null
var/mode = AALARM_MODE_SCRUBBING
var/preset = AALARM_PRESET_HUMAN
@@ -116,12 +117,18 @@
var/list/TLV = list()
- var/report_danger_level = 1
+ var/report_danger_level = TRUE
- var/automatic_emergency = 1 //Does the alarm automaticly respond to an emergency condition
+ var/automatic_emergency = TRUE //Does the alarm automaticly respond to an emergency condition
/obj/machinery/alarm/monitor
- report_danger_level = 0
+ report_danger_level = FALSE
+
+/obj/machinery/alarm/syndicate //general syndicate access
+ report_danger_level = FALSE
+ remote_control = FALSE
+ req_access = list(access_syndicate)
+ req_one_access = list()
/obj/machinery/alarm/monitor/server
preset = AALARM_PRESET_SERVER
@@ -212,8 +219,8 @@
/obj/machinery/alarm/Destroy()
GLOB.air_alarms -= src
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
air_alarm_repository.update_cache(src)
QDEL_NULL(wires)
@@ -374,38 +381,6 @@
if(ATMOS_ALARM_DANGER)
icon_state = "alarm1"
-/obj/machinery/alarm/receive_signal(datum/signal/signal)
- if(stat & (NOPOWER|BROKEN) || !alarm_area)
- return
- if(alarm_area.master_air_alarm != src)
- if(master_is_operating())
- return
- elect_master()
- if(alarm_area.master_air_alarm != src)
- return
- if(!signal || signal.encryption)
- return
- var/id_tag = signal.data["tag"]
- if(!id_tag)
- return
- if(signal.data["area"] != area_uid)
- return
- if(signal.data["sigtype"] != "status")
- return
-
- var/dev_type = signal.data["device"]
- if(!(id_tag in alarm_area.air_scrub_names) && !(id_tag in alarm_area.air_vent_names))
- register_env_machine(id_tag, dev_type)
- var/got_update=0
- if(dev_type == "AScr")
- alarm_area.air_scrub_info[id_tag] = signal.data
- got_update=1
- else if(dev_type == "AVP")
- alarm_area.air_vent_info[id_tag] = signal.data
- got_update=1
- if(got_update && waiting_on_device==id_tag)
- waiting_on_device=null
-
/obj/machinery/alarm/proc/register_env_machine(var/m_id, var/device_type)
var/new_name
if(device_type=="AVP")
@@ -432,9 +407,9 @@
send_signal(id_tag, list("status") )
/obj/machinery/alarm/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_TO_AIRALARM)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM)
/obj/machinery/alarm/proc/send_signal(var/target, var/list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise
if(!radio_connection)
@@ -571,7 +546,7 @@
update_icon()
/obj/machinery/alarm/proc/post_alert(alert_level)
- var/datum/radio_frequency/frequency = radio_controller.return_frequency(alarm_frequency)
+ var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency)
if(!frequency)
return
diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm
index 61547f270bf..1d0b8dde152 100644
--- a/code/game/machinery/atmo_control.dm
+++ b/code/game/machinery/atmo_control.dm
@@ -121,9 +121,9 @@
/obj/machinery/air_sensor/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
/obj/machinery/air_sensor/Initialize()
..()
@@ -132,8 +132,8 @@
/obj/machinery/air_sensor/Destroy()
SSair.atmos_machinery -= src
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
@@ -156,8 +156,8 @@
var/datum/radio_frequency/radio_connection
/obj/machinery/computer/general_air_control/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
@@ -268,9 +268,9 @@
return output
/obj/machinery/computer/general_air_control/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
/obj/machinery/computer/general_air_control/Initialize()
..()
@@ -357,7 +357,7 @@
return O:id_tag in sensors
/obj/machinery/computer/general_air_control/linkWith(mob/user, obj/O, link/context)
- sensors[O:id_tag] = reject_bad_name(input(user, "Choose a sensor label:", "Sensor Label") as text|null, allow_numbers=1)
+ sensors[O:id_tag] = reject_bad_name(clean_input(user, "Choose a sensor label:", "Sensor Label"), allow_numbers=1)
return 1
/obj/machinery/computer/general_air_control/large_tank_control
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 95e609ee524..e392b468557 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -371,7 +371,15 @@ update_flag
SSnanoui.update_uis(src) // Update all NanoUIs attached to src
-
+/obj/machinery/portable_atmospherics/canister/replace_tank(mob/living/user, close_valve)
+ . = ..()
+ if(.)
+ if(close_valve)
+ valve_open = FALSE
+ update_icon()
+ investigate_log("Valve was closed by [key_name(user)]. ", "atmos")
+ else if(valve_open && holding)
+ investigate_log("[key_name(user)] started a transfer into [holding]. ", "atmos")
/obj/machinery/portable_atmospherics/canister/attack_ai(var/mob/user as mob)
src.add_hiddenprint(user)
diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm
index dba1d942e2d..4777cdcc5f2 100644
--- a/code/game/machinery/atmoalter/meter.dm
+++ b/code/game/machinery/atmoalter/meter.dm
@@ -3,6 +3,9 @@
desc = "It measures something."
icon = 'icons/obj/meter.dmi'
icon_state = "meterX"
+
+ layer = GAS_PUMP_LAYER
+
var/obj/machinery/atmospherics/pipe/target = null
anchored = TRUE
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100)
@@ -65,7 +68,7 @@
icon_state = "meter4"
if(frequency)
- var/datum/radio_frequency/radio_connection = radio_controller.return_frequency(frequency)
+ var/datum/radio_frequency/radio_connection = SSradio.return_frequency(frequency)
if(!radio_connection) return
diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm
index dfecc3a4409..71e1310f96b 100644
--- a/code/game/machinery/atmoalter/portable_atmospherics.dm
+++ b/code/game/machinery/atmoalter/portable_atmospherics.dm
@@ -82,16 +82,49 @@
/obj/machinery/portable_atmospherics/portableConnectorReturnAir()
return air_contents
-/obj/machinery/portable_atmospherics/attackby(var/obj/item/W as obj, var/mob/user as mob, params)
- if((istype(W, /obj/item/tank) && !( src.destroyed )))
- if(src.holding)
- return
- var/obj/item/tank/T = W
- user.drop_item()
- T.loc = src
- src.holding = T
- update_icon()
+/obj/machinery/portable_atmospherics/AltClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
return
+ if(!in_range(src, user))
+ return
+ if(!ishuman(usr) && !issilicon(usr))
+ return
+ if(holding)
+ to_chat(user, "You remove [holding] from [src].")
+ replace_tank(user, TRUE)
+
+/obj/machinery/portable_atmospherics/examine(mob/user)
+ ..()
+ if(holding)
+ to_chat(user, "\The [src] contains [holding]. Alt-click [src] to remove it.")
+
+/obj/machinery/portable_atmospherics/proc/replace_tank(mob/living/user, close_valve, obj/item/tank/new_tank)
+ if(holding)
+ holding.forceMove(drop_location())
+ if(Adjacent(user) && !issilicon(user))
+ user.put_in_hands(holding)
+ if(new_tank)
+ holding = new_tank
+ else
+ holding = null
+ update_icon()
+ return TRUE
+
+/obj/machinery/portable_atmospherics/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/tank))
+ if(!(stat & BROKEN))
+ if(!user.drop_item())
+ return
+ var/obj/item/tank/T = W
+ user.drop_item()
+ if(src.holding)
+ to_chat(user, "[holding ? "In one smooth motion you pop [holding] out of [src]'s connector and replace it with [T]" : "You insert [T] into [src]"].")
+ replace_tank(user, FALSE)
+ T.loc = src
+ src.holding = T
+ update_icon()
+ return
else if(istype(W, /obj/item/wrench))
if(connected_port)
diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm
index a7680e815ff..5bd441f6748 100644
--- a/code/game/machinery/atmoalter/pump.dm
+++ b/code/game/machinery/atmoalter/pump.dm
@@ -95,6 +95,16 @@
/obj/machinery/portable_atmospherics/pump/return_air()
return air_contents
+/obj/machinery/portable_atmospherics/pump/replace_tank(mob/living/user, close_valve)
+ . = ..()
+ if(.)
+ if(close_valve)
+ if(on)
+ on = FALSE
+ update_icon()
+ else if(on && holding && direction_out)
+ investigate_log("[key_name(user)] started a transfer into [holding]. ", "atmos")
+
/obj/machinery/portable_atmospherics/pump/attack_ai(var/mob/user as mob)
src.add_hiddenprint(user)
return src.attack_hand(user)
@@ -139,10 +149,14 @@
if(href_list["power"])
on = !on
+ if(on && direction_out)
+ investigate_log("[key_name(usr)] started a transfer into [holding]. ", "atmos")
update_icon()
if(href_list["direction"])
direction_out = !direction_out
+ if(on && holding)
+ investigate_log("[key_name(usr)] started a transfer into [holding]. ", "atmos")
if(href_list["remove_tank"])
if(holding)
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index a76bd387ac7..b968a4bd5f8 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -33,7 +33,7 @@
pixel_x = 25
if(WEST)
pixel_x = -25
- if(radio_controller)
+ if(SSradio)
set_frequency(frequency)
/obj/machinery/driver_button/Initialize()
@@ -41,14 +41,14 @@
set_frequency(frequency)
/obj/machinery/driver_button/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_LOGIC)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_LOGIC)
return
/obj/machinery/driver_button/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 7535381197a..d59aca72145 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -295,10 +295,12 @@
to_chat(O, "The screen bursts into static.")
/obj/machinery/camera/proc/triggerCameraAlarm()
- camera_alarm.triggerAlarm(loc, src)
+ if(is_station_contact(z))
+ SSalarms.camera_alarm.triggerAlarm(loc, src)
/obj/machinery/camera/proc/cancelCameraAlarm()
- camera_alarm.clearAlarm(loc, src)
+ if(is_station_contact(z))
+ SSalarms.camera_alarm.clearAlarm(loc, src)
/obj/machinery/camera/proc/can_use()
if(!status)
@@ -382,14 +384,17 @@
user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 2)
/obj/machinery/camera/update_remote_sight(mob/living/user)
- user.see_invisible = SEE_INVISIBLE_LIVING //can't see ghosts through cameras
if(isXRay())
user.sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
user.see_in_dark = max(user.see_in_dark, 8)
+ user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
else
- user.sight = 0
- user.see_in_dark = 2
- return 1
+ user.sight = initial(user.sight)
+ user.see_in_dark = initial(user.see_in_dark)
+ user.lighting_alpha = initial(user.lighting_alpha)
+
+ ..()
+ return TRUE
/obj/machinery/camera/portable //Cameras which are placed inside of things, such as helmets.
var/turf/prev_turf
diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm
index eeb9eeb60d3..312e4cf577e 100644
--- a/code/game/machinery/camera/motion.dm
+++ b/code/game/machinery/camera/motion.dm
@@ -43,19 +43,20 @@
/obj/machinery/camera/proc/cancelAlarm()
if(!status || (stat & NOPOWER))
- return 0
- if(detectTime == -1)
- motion_alarm.clearAlarm(loc, src)
+ return FALSE
+ if(detectTime == -1 && is_station_contact(z))
+ SSalarms.motion_alarm.clearAlarm(loc, src)
detectTime = 0
- return 1
+ return TRUE
/obj/machinery/camera/proc/triggerAlarm()
if(!status || (stat & NOPOWER))
- return 0
- if(!detectTime) return 0
- motion_alarm.triggerAlarm(loc, src)
+ return FALSE
+ if(!detectTime || !is_station_contact(z))
+ return FALSE
+ SSalarms.motion_alarm.triggerAlarm(loc, src)
detectTime = -1
- return 1
+ return TRUE
/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj)
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 17a27812499..1d05204e381 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -34,7 +34,7 @@
var/obj/effect/countdown/clonepod/countdown
- var/list/brine_types = list("corazone", "salbutamol", "hydrocodone")
+ var/list/brine_types = list("corazone", "perfluorodecalin", "epinephrine", "salglu_solution") //stops heart attacks, heart failure, shock, and keeps their O2 levels normal
var/list/missing_organs
var/organs_number = 0
@@ -341,7 +341,7 @@
check_brine()
//Also heal some oxyloss ourselves just in case!!
- occupant.adjustOxyLoss(-4)
+ occupant.adjustOxyLoss(-10)
use_power(7500) //This might need tweaking.
@@ -416,25 +416,24 @@
/obj/machinery/clonepod/proc/update_clone_antag(var/mob/living/carbon/human/H)
// Check to see if the clone's mind is an antagonist of any kind and handle them accordingly to make sure they get their spells, HUD/whatever else back.
- callHook("clone", list(H))
- if((H.mind in ticker.mode:revolutionaries) || (H.mind in ticker.mode:head_revolutionaries))
- ticker.mode.update_rev_icons_added() //So the icon actually appears
- if(H.mind in ticker.mode.syndicates)
- ticker.mode.update_synd_icons_added()
- if(H.mind in ticker.mode.cult)
- ticker.mode.add_cultist(occupant.mind)
- ticker.mode.update_cult_icons_added() //So the icon actually appears
- ticker.mode.update_cult_comms_added(H.mind) //So the comms actually appears
- if((H.mind in ticker.mode.implanter) || (H.mind in ticker.mode.implanted))
- ticker.mode.update_traitor_icons_added(H.mind) //So the icon actually appears
+ if((H.mind in SSticker.mode:revolutionaries) || (H.mind in SSticker.mode:head_revolutionaries))
+ SSticker.mode.update_rev_icons_added() //So the icon actually appears
+ if(H.mind in SSticker.mode.syndicates)
+ SSticker.mode.update_synd_icons_added()
+ if(H.mind in SSticker.mode.cult)
+ SSticker.mode.add_cultist(occupant.mind)
+ SSticker.mode.update_cult_icons_added() //So the icon actually appears
+ SSticker.mode.update_cult_comms_added(H.mind) //So the comms actually appears
+ if((H.mind in SSticker.mode.implanter) || (H.mind in SSticker.mode.implanted))
+ SSticker.mode.update_traitor_icons_added(H.mind) //So the icon actually appears
if(H.mind.vampire)
H.mind.vampire.update_owner(H)
- if((H.mind in ticker.mode.vampire_thralls) || (H.mind in ticker.mode.vampire_enthralled))
- ticker.mode.update_vampire_icons_added(H.mind)
- if(H.mind in ticker.mode.changelings)
- ticker.mode.update_change_icons_added(H.mind)
- if((H.mind in ticker.mode.shadowling_thralls) || (H.mind in ticker.mode.shadows))
- ticker.mode.update_shadow_icons_added(H.mind)
+ if((H.mind in SSticker.mode.vampire_thralls) || (H.mind in SSticker.mode.vampire_enthralled))
+ SSticker.mode.update_vampire_icons_added(H.mind)
+ if(H.mind in SSticker.mode.changelings)
+ SSticker.mode.update_change_icons_added(H.mind)
+ if((H.mind in SSticker.mode.shadowling_thralls) || (H.mind in SSticker.mode.shadows))
+ SSticker.mode.update_shadow_icons_added(H.mind)
//Put messages in the connected computer's temp var for display.
/obj/machinery/clonepod/proc/connected_message(message)
@@ -449,10 +448,14 @@
/obj/machinery/clonepod/proc/go_out()
countdown.stop()
-
+ var/turf/T = get_turf(src)
if(mess) //Clean that mess and dump those gibs!
- mess = 0
- gibs(loc)
+ for(var/i in missing_organs)
+ var/obj/I = i
+ I.forceMove(T)
+ missing_organs.Cut()
+ mess = FALSE
+ new /obj/effect/gibspawner/generic(get_turf(src), occupant)
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
update_icon()
return
@@ -476,10 +479,13 @@
for(var/i in missing_organs)
qdel(i)
missing_organs.Cut()
- occupant.forceMove(get_turf(src))
+ occupant.SetLoseBreath(0) // Stop friggin' dying, gosh damn
+ occupant.setOxyLoss(0)
+ for(var/datum/disease/critical/crit in occupant.viruses)
+ crit.cure()
+ occupant.forceMove(T)
occupant.update_body()
domutcheck(occupant) //Waiting until they're out before possible notransform.
- occupant.shock_stage = 0 //Reset Shock
occupant.special_post_clone_handling()
occupant = null
update_icon()
diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm
index c338a0f32c9..c4c8d342aeb 100644
--- a/code/game/machinery/computer/Operating.dm
+++ b/code/game/machinery/computer/Operating.dm
@@ -112,7 +112,7 @@
occupantData["stat"] = occupant.stat
occupantData["health"] = occupant.health
occupantData["maxHealth"] = occupant.maxHealth
- occupantData["minHealth"] = config.health_threshold_dead
+ occupantData["minHealth"] = HEALTH_THRESHOLD_DEAD
occupantData["bruteLoss"] = occupant.getBruteLoss()
occupantData["oxyLoss"] = occupant.getOxyLoss()
occupantData["toxLoss"] = occupant.getToxLoss()
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 67f1dba85f0..38cc0b56866 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -134,8 +134,8 @@
return
if(P:brainmob.mind)
- ticker.mode.remove_cultist(P:brainmob.mind, 1)
- ticker.mode.remove_revolutionary(P:brainmob.mind, 1)
+ SSticker.mode.remove_cultist(P:brainmob.mind, 1)
+ SSticker.mode.remove_revolutionary(P:brainmob.mind, 1)
user.drop_item()
P.loc = src
diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm
index 22a376968d0..e6a57f4a875 100644
--- a/code/game/machinery/computer/aifixer.dm
+++ b/code/game/machinery/computer/aifixer.dm
@@ -25,12 +25,7 @@
ui_interact(user)
/obj/machinery/computer/aifixer/attack_hand(var/mob/user as mob)
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode)
- ui_interact(user)
- else
- if(mode.kickoff)
- to_chat(user, "You have been locked out from this console!")
+ ui_interact(user)
/obj/machinery/computer/aifixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 6d360a2ddb3..741a4725c8d 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -470,7 +470,7 @@
M.nutrition -= 50 //lose a lot of food
var/turf/location = usr.loc
if(istype(location, /turf/simulated))
- location.add_vomit_floor(src, 1)
+ location.add_vomit_floor(TRUE)
if(ORION_TRAIL_FLUX)
if(prob(75))
M.Weaken(3)
@@ -484,7 +484,7 @@
playsound(src.loc, 'sound/effects/bang.ogg', 100, 1)
var/turf/simulated/floor/F
for(F in orange(1, src))
- F.ChangeTurf(/turf/space)
+ F.ChangeTurf(F.baseturf)
atom_say("Something slams into the floor around [src], exposing it to space!")
if(hull)
sleep(10)
diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm
index f2137d2ee8f..f8c2979e043 100644
--- a/code/game/machinery/computer/atmos_alert.dm
+++ b/code/game/machinery/computer/atmos_alert.dm
@@ -12,10 +12,10 @@ var/global/list/minor_air_alarms = list()
/obj/machinery/computer/atmos_alert/New()
..()
- atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/update_icon)
+ SSalarms.atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/update_icon)
/obj/machinery/computer/atmos_alert/Destroy()
- atmosphere_alarm.unregister(src)
+ SSalarms.atmosphere_alarm.unregister(src)
return ..()
/obj/machinery/computer/atmos_alert/attack_hand(mob/user)
@@ -33,10 +33,10 @@ var/global/list/minor_air_alarms = list()
var/major_alarms[0]
var/minor_alarms[0]
- for(var/datum/alarm/alarm in atmosphere_alarm.major_alarms())
+ for(var/datum/alarm/alarm in SSalarms.atmosphere_alarm.major_alarms())
major_alarms[++major_alarms.len] = list("name" = sanitize(alarm.alarm_name()), "ref" = "\ref[alarm]")
- for(var/datum/alarm/alarm in atmosphere_alarm.minor_alarms())
+ for(var/datum/alarm/alarm in SSalarms.atmosphere_alarm.minor_alarms())
minor_alarms[++minor_alarms.len] = list("name" = sanitize(alarm.alarm_name()), "ref" = "\ref[alarm]")
data["priority_alarms"] = major_alarms
@@ -45,11 +45,11 @@ var/global/list/minor_air_alarms = list()
return data
/obj/machinery/computer/atmos_alert/update_icon()
- var/list/alarms = atmosphere_alarm.major_alarms()
+ var/list/alarms = SSalarms.atmosphere_alarm.major_alarms()
if(alarms.len)
icon_screen = "alert:2"
else
- alarms = atmosphere_alarm.minor_alarms()
+ alarms = SSalarms.atmosphere_alarm.minor_alarms()
if(alarms.len)
icon_screen = "alert:1"
else
@@ -61,7 +61,7 @@ var/global/list/minor_air_alarms = list()
return 1
if(href_list["clear_alarm"])
- var/datum/alarm/alarm = locate(href_list["clear_alarm"]) in atmosphere_alarm.alarms
+ var/datum/alarm/alarm = locate(href_list["clear_alarm"]) in SSalarms.atmosphere_alarm.alarms
if(alarm)
for(var/datum/alarm_source/alarm_source in alarm.sources)
var/obj/machinery/alarm/air_alarm = alarm_source.source
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 2b294db78c9..a34a49ca051 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -56,6 +56,17 @@
/obj/item/circuitboard/machine
board_type = "machine"
+/obj/item/circuitboard/examine(mob/user)
+ ..()
+ if(LAZYLEN(req_components))
+ var/list/nice_list = list()
+ for(var/B in req_components)
+ var/atom/A = B
+ if(!ispath(A))
+ continue
+ nice_list += list("[req_components[A]] [initial(A.name)]")
+ to_chat(user,"Required components: [english_list(nice_list)].")
+
/obj/item/circuitboard/message_monitor
name = "Circuit board (Message Monitor)"
build_path = /obj/machinery/computer/message_monitor
@@ -207,6 +218,10 @@
name = "Circuit board (Power Monitor)"
build_path = /obj/machinery/computer/monitor
origin_tech = "programming=2;powerstorage=2"
+/obj/item/circuitboard/powermonitor/secret
+ name = "Circuit board (Outdated Power Monitor)"
+ build_path = /obj/machinery/computer/monitor/secret
+ origin_tech = "programming=2;powerstorage=2"
/obj/item/circuitboard/olddoor
name = "Circuit board (DoorMex)"
build_path = /obj/machinery/computer/pod/old
@@ -319,9 +334,6 @@
/obj/item/circuitboard/white_ship
name = "circuit Board (White Ship)"
build_path = /obj/machinery/computer/shuttle/white_ship
-/obj/item/circuitboard/golem_ship
- name = "circuit Board (Golem Ship)"
- build_path = /obj/machinery/computer/shuttle/golem_ship
/obj/item/circuitboard/shuttle/syndicate
name = "circuit board (Syndicate Shuttle)"
build_path = /obj/machinery/computer/shuttle/syndicate
@@ -331,7 +343,9 @@
/obj/item/circuitboard/shuttle/syndicate/drop_pod
name = "circuit board (Syndicate Drop Pod)"
build_path = /obj/machinery/computer/shuttle/syndicate/drop_pod
-
+/obj/item/circuitboard/shuttle/golem_ship
+ name = "circuit Board (Golem Ship)"
+ build_path = /obj/machinery/computer/shuttle/golem_ship
/obj/item/circuitboard/HolodeckControl
name = "Circuit board (Holodeck Control)"
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 92e06641204..42c371fc4ee 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -24,7 +24,7 @@
available_networks["Mining Outpost"] = list(access_qm,access_hop,access_hos,access_captain)
available_networks["Research"] = list(access_rd,access_hos,access_captain)
available_networks["Prison"] = list(access_hos,access_captain)
- available_networks["Labor"] = list(access_hos,access_captain)
+ available_networks["Labor Camp"] = list(access_hos,access_captain)
available_networks["Interrogation"] = list(access_hos,access_captain)
available_networks["Atmosphere Alarms"] = list(access_ce,access_hos,access_captain)
available_networks["Fire Alarms"] = list(access_ce,access_hos,access_captain)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index 4cde71a4705..86515e5ddea 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -66,20 +66,21 @@ var/time_last_changed_position = 0
/obj/machinery/computer/card/proc/get_target_rank()
return modify && modify.assignment ? modify.assignment : "Unassigned"
-/obj/machinery/computer/card/proc/format_jobs(list/jobs)
+/obj/machinery/computer/card/proc/format_jobs(list/jobs, targetrank, list/jobformats)
var/list/formatted = list()
for(var/job in jobs)
- if(job_in_department(job_master.GetJob(job)))
+ if(job_in_department(SSjobs.GetJob(job)))
formatted.Add(list(list(
"display_name" = replacetext(job, " ", " "),
- "target_rank" = get_target_rank(),
- "job" = job)))
+ "target_rank" = targetrank,
+ "job" = job,
+ "jlinkformat" = jobformats[job] ? jobformats[job] : null)))
return formatted
/obj/machinery/computer/card/proc/format_job_slots()
var/list/formatted = list()
- for(var/datum/job/job in job_master.occupations)
+ for(var/datum/job/job in SSjobs.occupations)
if(job_blacklisted_full(job))
continue
if(!job_in_department(job))
@@ -117,12 +118,14 @@ var/time_last_changed_position = 0
if(!usr.get_active_hand() && Adjacent(usr))
usr.put_in_hands(scan)
scan = null
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
else if(modify)
to_chat(usr, "You remove \the [modify] from \the [src].")
modify.forceMove(get_turf(src))
if(!usr.get_active_hand() && Adjacent(usr))
usr.put_in_hands(modify)
modify = null
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
else
to_chat(usr, "There is nothing to remove from the console.")
@@ -134,10 +137,12 @@ var/time_last_changed_position = 0
user.drop_item()
id_card.loc = src
scan = id_card
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
else if(!modify)
user.drop_item()
id_card.loc = src
modify = id_card
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
SSnanoui.update_uis(src)
attack_hand(user)
@@ -166,7 +171,7 @@ var/time_last_changed_position = 0
/obj/machinery/computer/card/proc/can_close_job(datum/job/job)
if(job)
if(!job_blacklisted_full(job) && !job_blacklisted_partial(job) && job_in_department(job, FALSE))
- if(job.total_positions > job.current_positions && !(job in job_master.prioritized_jobs))
+ if(job.total_positions > job.current_positions && !(job in SSjobs.prioritized_jobs))
var/delta = (world.time / 10) - time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] > 0))
return 1
@@ -177,10 +182,10 @@ var/time_last_changed_position = 0
/obj/machinery/computer/card/proc/can_prioritize_job(datum/job/job)
if(job)
if(!job_blacklisted_full(job) && job_in_department(job, FALSE))
- if(job in job_master.prioritized_jobs)
+ if(job in SSjobs.prioritized_jobs)
return 2
else
- if(job_master.prioritized_jobs.len >= 3)
+ if(SSjobs.prioritized_jobs.len >= 3)
return 0
if(job.total_positions <= job.current_positions)
return 0
@@ -205,7 +210,7 @@ var/time_last_changed_position = 0
/obj/machinery/computer/card/proc/get_subordinates(rank, addcivs)
var/list/jobs_returned = list()
- for(var/datum/job/thisjob in job_master.occupations)
+ for(var/datum/job/thisjob in SSjobs.occupations)
if(rank in thisjob.department_head)
jobs_returned += thisjob.title
if(addcivs)
@@ -242,6 +247,7 @@ var/time_last_changed_position = 0
data["target_owner"] = modify && modify.registered_name ? modify.registered_name : "-----"
data["target_rank"] = get_target_rank()
data["scan_name"] = scan ? scan.name : "-----"
+ data["scan_owner"] = scan && scan.registered_name ? scan.registered_name : null
data["authenticated"] = is_authenticated(user)
data["has_modify"] = !!modify
data["account_number"] = modify ? modify.associated_account_number : null
@@ -249,15 +255,19 @@ var/time_last_changed_position = 0
data["all_centcom_access"] = null
data["regions"] = null
data["target_dept"] = target_dept
+ data["card_is_owned"] = modify && modify.owner_ckey
- data["engineering_jobs"] = format_jobs(engineering_positions)
- data["medical_jobs"] = format_jobs(medical_positions)
- data["science_jobs"] = format_jobs(science_positions)
- data["security_jobs"] = format_jobs(security_positions)
- data["support_jobs"] = format_jobs(support_positions)
- data["civilian_jobs"] = format_jobs(civilian_positions)
- data["special_jobs"] = format_jobs(whitelisted_positions)
- data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
+ var/list/job_formats = SSjobs.format_jobs_for_id_computer(modify)
+
+ data["top_jobs"] = format_jobs(list("Captain", "Custom"), data["target_rank"], job_formats)
+ data["engineering_jobs"] = format_jobs(engineering_positions, data["target_rank"], job_formats)
+ data["medical_jobs"] = format_jobs(medical_positions, data["target_rank"], job_formats)
+ data["science_jobs"] = format_jobs(science_positions, data["target_rank"], job_formats)
+ data["security_jobs"] = format_jobs(security_positions, data["target_rank"], job_formats)
+ data["support_jobs"] = format_jobs(support_positions, data["target_rank"], job_formats)
+ data["civilian_jobs"] = format_jobs(civilian_positions, data["target_rank"], job_formats)
+ data["special_jobs"] = format_jobs(whitelisted_positions, data["target_rank"], job_formats)
+ data["centcom_jobs"] = format_jobs(get_all_centcom_jobs(), data["target_rank"], job_formats)
data["card_skins"] = format_card_skins(get_station_card_skins())
data["job_slots"] = format_job_slots()
@@ -268,6 +278,9 @@ var/time_last_changed_position = 0
data["cooldown_mins"] = mins
data["cooldown_secs"] = (seconds < 10) ? "0[seconds]" : seconds
+ if(mode == 3 && is_authenticated(user))
+ data["id_change_html"] = SSjobs.fetch_transfer_record_html(is_centcom())
+
if(modify)
data["current_skin"] = modify.icon_state
@@ -315,15 +328,18 @@ var/time_last_changed_position = 0
if(!usr.get_active_hand() && Adjacent(usr))
usr.put_in_hands(modify)
modify = null
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
else
modify.forceMove(get_turf(src))
modify = null
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
else if(Adjacent(usr))
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/card/id))
usr.drop_item()
I.forceMove(src)
modify = I
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
if("scan")
if(scan)
@@ -332,15 +348,18 @@ var/time_last_changed_position = 0
if(!usr.get_active_hand() && Adjacent(usr))
usr.put_in_hands(scan)
scan = null
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
else
scan.forceMove(get_turf(src))
scan = null
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
else if(Adjacent(usr))
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/card/id))
usr.drop_item()
I.forceMove(src)
scan = I
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
if("access")
if(href_list["allowed"] && !target_dept)
@@ -361,23 +380,24 @@ var/time_last_changed_position = 0
if("assign")
if(is_authenticated(usr) && modify)
var/t1 = href_list["assign_target"]
- if(target_dept && modify.assignment == "Unassigned")
+ if(target_dept && modify.assignment == "Demoted")
visible_message("[src]: Demoted individuals must see the HoP for a new job.")
return 0
- if(!job_in_department(job_master.GetJob(modify.rank), FALSE))
+ if(!job_in_department(SSjobs.GetJob(modify.rank), FALSE))
visible_message("[src]: Cross-department job transfers must be done by the HoP.")
return 0
- if(!job_in_department(job_master.GetJob(t1)))
+ if(!job_in_department(SSjobs.GetJob(t1)))
return 0
if(t1 == "Custom")
var/temp_t = sanitize(copytext(input("Enter a custom job assignment.","Assignment"),1,MAX_MESSAGE_LEN))
//let custom jobs function as an impromptu alt title, mainly for sechuds
if(temp_t && modify)
+ SSjobs.log_job_transfer(modify.registered_name, modify.getRankAndAssignment(), temp_t, scan.registered_name)
modify.assignment = temp_t
log_game("[key_name(usr)] has given \"[modify.registered_name]\" the custom job title \"[temp_t]\".")
else
var/list/access = list()
- if(is_centcom())
+ if(is_centcom() && islist(get_centcom_access(t1)))
access = get_centcom_access(t1)
else
var/datum/job/jobdatum
@@ -397,13 +417,20 @@ var/time_last_changed_position = 0
if(t1 == "Civilian")
message_admins("[key_name_admin(usr)] has reassigned \"[modify.registered_name]\" from \"[jobnamedata]\" to \"[t1]\".")
+ SSjobs.log_job_transfer(modify.registered_name, jobnamedata, t1, scan.registered_name)
+ SSjobs.slot_job_transfer(modify.rank, t1)
+
+ var/mob/living/carbon/human/H = modify.getPlayer()
+ if(istype(H))
+ if(jobban_isbanned(H, t1))
+ message_admins("[ADMIN_FULLMONTY(H)] has been assigned the job [t1], in possible violation of their job ban.")
+ if(H.mind)
+ H.mind.playtime_role = t1
+
modify.access = access
modify.rank = t1
modify.assignment = t1
-
- callHook("reassign_employee", list(modify))
-
if("reg")
if(is_authenticated(usr) && !target_dept)
var/t2 = modify
@@ -426,6 +453,20 @@ var/time_last_changed_position = 0
if("mode")
mode = text2num(href_list["mode_target"])
+ if("wipe_my_logs")
+ if(is_authenticated(usr) && is_centcom())
+ var/delcount = SSjobs.delete_log_records(scan.registered_name, FALSE)
+ if(delcount)
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ SSnanoui.update_uis(src)
+
+ if("wipe_all_logs")
+ if(is_authenticated(usr) && !target_dept)
+ var/delcount = SSjobs.delete_log_records(scan.registered_name, TRUE)
+ if(delcount)
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ SSnanoui.update_uis(src)
+
if("print")
if(!printing && !target_dept)
printing = 1
@@ -464,16 +505,16 @@ var/time_last_changed_position = 0
var/jobnamedata = modify.getRankAndAssignment()
log_game("[key_name(usr)] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\".")
message_admins("[key_name_admin(usr)] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\".")
+ SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Terminated", scan.registered_name)
modify.assignment = "Terminated"
modify.access = list()
- callHook("terminate_employee", list(modify))
if("demote")
if(is_authenticated(usr))
- if(modify.assignment == "Unassigned")
- visible_message("[src]: Unassigned crew cannot be demoted any further. If further action is warranted, ask the Captain about Termination.")
+ if(modify.assignment == "Demoted")
+ visible_message("[src]: Demoted crew cannot be demoted any further. If further action is warranted, ask the Captain about Termination.")
return 0
- if(!job_in_department(job_master.GetJob(modify.rank), FALSE))
+ if(!job_in_department(SSjobs.GetJob(modify.rank), FALSE))
visible_message("[src]: Heads may only demote members of their own department.")
return 0
@@ -482,19 +523,20 @@ var/time_last_changed_position = 0
access = jobdatum.get_access()
var/jobnamedata = modify.getRankAndAssignment()
- log_game("[key_name(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" to \"Civilian (Unassigned)\".")
- message_admins("[key_name_admin(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" to \"Civilian (Unassigned)\".")
+ log_game("[key_name(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" to \"Civilian (Demoted)\".")
+ message_admins("[key_name_admin(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" to \"Civilian (Demoted)\".")
+ SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Demoted", scan.registered_name)
modify.access = access
modify.rank = "Civilian"
- modify.assignment = "Unassigned"
+ modify.assignment = "Demoted"
modify.icon_state = "id"
if("make_job_available")
// MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS
if(is_authenticated(usr))
var/edit_job_target = href_list["job"]
- var/datum/job/j = job_master.GetJob(edit_job_target)
+ var/datum/job/j = SSjobs.GetJob(edit_job_target)
if(!job_in_department(j, FALSE))
return 0
if(!j)
@@ -513,7 +555,7 @@ var/time_last_changed_position = 0
// MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS
if(is_authenticated(usr))
var/edit_job_target = href_list["job"]
- var/datum/job/j = job_master.GetJob(edit_job_target)
+ var/datum/job/j = SSjobs.GetJob(edit_job_target)
if(!job_in_department(j, FALSE))
return 0
if(!j)
@@ -533,17 +575,17 @@ var/time_last_changed_position = 0
// TOGGLE WHETHER JOB APPEARS AS PRIORITIZED IN THE LOBBY
if(is_authenticated(usr) && !target_dept)
var/priority_target = href_list["job"]
- var/datum/job/j = job_master.GetJob(priority_target)
+ var/datum/job/j = SSjobs.GetJob(priority_target)
if(!j)
return 0
if(!job_in_department(j))
return 0
var/priority = TRUE
- if(j in job_master.prioritized_jobs)
- job_master.prioritized_jobs -= j
+ if(j in SSjobs.prioritized_jobs)
+ SSjobs.prioritized_jobs -= j
priority = FALSE
- else if(job_master.prioritized_jobs.len < 3)
- job_master.prioritized_jobs += j
+ else if(SSjobs.prioritized_jobs.len < 3)
+ SSjobs.prioritized_jobs += j
else
return 0
log_game("[key_name(usr)] [priority ? "prioritized" : "unprioritized"] the job \"[j.title]\".")
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index c134747cd41..acdbc1110f3 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -36,10 +36,13 @@
if(scanner.occupant && can_autoprocess())
scan_mob(scanner.occupant)
-
+
+ if(!LAZYLEN(records))
+ return
+
for(var/obj/machinery/clonepod/pod in pods)
if(!(pod.occupant || pod.mess) && (pod.efficiency > 5))
- for(var/datum/dna2/record/R in src.records)
+ for(var/datum/dna2/record/R in records)
if(!(pod.occupant || pod.mess))
if(pod.growclone(R))
records.Remove(R)
@@ -392,6 +395,12 @@
SSnanoui.update_uis(src)
return
+ for(var/obj/machinery/clonepod/pod in pods)
+ if(pod.occupant && pod.clonemind == subject.mind)
+ scantemp = "Subject already getting cloned."
+ SSnanoui.update_uis(src)
+ return
+
subject.dna.check_integrity()
var/datum/dna2/record/R = new /datum/dna2/record()
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 854525dadf4..be27b0600cf 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -156,7 +156,7 @@
message_cooldown = 0
if("callshuttle")
- var/input = input(usr, "Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") as text|null
+ var/input = clean_input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","")
if(!input || ..() || !is_authenticated(usr))
SSnanoui.update_uis(src)
return
@@ -217,11 +217,11 @@
setMenuState(usr,COMM_SCREEN_STAT)
if("setmsg1")
- stat_msg1 = input("Line 1", "Enter Message Text", stat_msg1) as text|null
+ stat_msg1 = clean_input("Line 1", "Enter Message Text", stat_msg1)
setMenuState(usr,COMM_SCREEN_STAT)
if("setmsg2")
- stat_msg2 = input("Line 2", "Enter Message Text", stat_msg2) as text|null
+ stat_msg2 = clean_input("Line 2", "Enter Message Text", stat_msg2)
setMenuState(usr,COMM_SCREEN_STAT)
if("nukerequest")
@@ -439,7 +439,7 @@
to_chat(user, "The emergency shuttle may not be called while returning to Central Command.")
return
- if(ticker.mode.name == "blob")
+ if(SSticker.mode.name == "blob")
to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.")
return
@@ -464,7 +464,7 @@
to_chat(user, "The shuttle is refueling. Please wait another [round((54000-world.time)/600)] minutes before trying again.")
return
- if(ticker.mode.name == "epidemic")
+ if(SSticker.mode.name == "epidemic")
to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.")
return
@@ -481,7 +481,7 @@
/proc/cancel_call_proc(var/mob/user)
- if(ticker.mode.name == "meteor")
+ if(SSticker.mode.name == "meteor")
return
if(SSshuttle.cancelEvac(user))
@@ -494,7 +494,7 @@
/proc/post_status(command, data1, data2, mob/user = null)
- var/datum/radio_frequency/frequency = radio_controller.return_frequency(DISPLAY_FREQ)
+ var/datum/radio_frequency/frequency = SSradio.return_frequency(DISPLAY_FREQ)
if(!frequency) return
diff --git a/code/game/machinery/computer/depot.dm b/code/game/machinery/computer/depot.dm
index 4e6afa0c229..149e2b7ff49 100644
--- a/code/game/machinery/computer/depot.dm
+++ b/code/game/machinery/computer/depot.dm
@@ -283,7 +283,7 @@
return
message_sent = TRUE
if(user.mind && user.mind.special_role == SPECIAL_ROLE_TRAITOR)
- var/input = stripped_input(user, "Please choose a message to transmit to Syndicate HQ via quantum entanglement. Transmission does not guarantee a response. This function may only be used ONCE.", "To abort, send an empty message.", "") as text|null
+ var/input = stripped_input(user, "Please choose a message to transmit to Syndicate HQ via quantum entanglement. Transmission does not guarantee a response. This function may only be used ONCE.", "To abort, send an empty message.", "")
if(!input)
message_sent = FALSE
return
diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm
index e0969555ce9..74cc417e7ce 100644
--- a/code/game/machinery/computer/law.dm
+++ b/code/game/machinery/computer/law.dm
@@ -28,19 +28,17 @@
attackby(obj/item/O as obj, mob/user as mob, params)
if(istype(O, /obj/item/aiModule))
+ if(!current)//no AI selected
+ to_chat(user, "No AI selected. Please chose a target before proceeding with upload.")
+ return
var/turf/T = get_turf(current)
if(!atoms_share_level(T, src))
to_chat(user, "Unable to establish a connection: You're too far away from the target silicon!")
return
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode)
- var/obj/item/aiModule/M = O
- M.install(src)
- else
- if(mode.kickoff)
- to_chat(user, "You have been locked out from modifying the AI's laws!")
- else
- ..()
+ var/obj/item/aiModule/M = O
+ M.install(src)
+ return
+ return ..()
attack_hand(var/mob/user as mob)
@@ -73,18 +71,16 @@
attackby(obj/item/aiModule/module as obj, mob/user as mob, params)
if(istype(module, /obj/item/aiModule))
+ if(!current)//no borg selected
+ to_chat(user, "No borg selected. Please chose a target before proceeding with upload.")
+ return
var/turf/T = get_turf(current)
if(!atoms_share_level(T, src))
to_chat(user, "Unable to establish a connection: You're too far away from the target silicon!")
return
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode)
- module.install(src)
- else
- if(mode.kickoff)
- to_chat(user, "You have been locked out from modifying the borg's laws!")
- else
- return ..()
+ module.install(src)
+ return
+ return ..()
attack_hand(var/mob/user as mob)
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index fb09b40f440..dbe766a2c44 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -466,7 +466,7 @@
active2.fields["comments"] -= active2.fields["comments"][index]
if(href_list["search"])
- var/t1 = input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text
+ var/t1 = clean_input("Search String: (Name, DNA, or ID)", "Med. records", null, null)
if(!t1 || ..())
return 1
active1 = null
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index 87d35c2d7b4..d6e000d660d 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -281,7 +281,7 @@
auth = 0
screen = 0
else
- var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
+ var/dkey = trim(clean_input("Please enter the decryption key."))
if(dkey && dkey != "")
if(src.linkedServer.decryptkey == dkey)
auth = 1
@@ -332,7 +332,7 @@
message = noserver
else
if(auth)
- var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
+ var/dkey = trim(clean_input("Please enter the decryption key."))
if(dkey && dkey != "")
if(src.linkedServer.decryptkey == dkey)
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
@@ -395,7 +395,7 @@
//Select Your Name
if("Sender")
- customsender = input(usr, "Please enter the sender's name.") as text|null
+ customsender = clean_input("Please enter the sender's name.")
//Select Receiver
if("Recepient")
@@ -414,11 +414,11 @@
//Enter custom job
if("RecJob")
- customjob = input(usr, "Please enter the sender's job.") as text|null
+ customjob = clean_input("Please enter the sender's job.")
//Enter message
if("Message")
- custommessage = input(usr, "Please enter your message.") as text|null
+ custommessage = clean_input("Please enter your message.")
custommessage = sanitize(copytext(custommessage, 1, MAX_MESSAGE_LEN))
//Send message
diff --git a/code/game/machinery/computer/power.dm b/code/game/machinery/computer/power.dm
index a5198da6e56..416c73d2570 100644
--- a/code/game/machinery/computer/power.dm
+++ b/code/game/machinery/computer/power.dm
@@ -10,6 +10,13 @@
circuit = /obj/item/circuitboard/powermonitor
var/datum/powernet/powernet = null
var/datum/nano_module/power_monitor/power_monitor
+ var/is_secret_monitor = FALSE
+
+/obj/machinery/computer/monitor/secret //Hides the power monitor (such as ones on ruins & CentCom) from PDA's to prevent metagaming.
+ name = "outdated power monitoring console"
+ desc = "It monitors power levels across the local powernet."
+ circuit = /obj/item/circuitboard/powermonitor/secret
+ is_secret_monitor = TRUE
/obj/machinery/computer/monitor/New()
..()
@@ -38,7 +45,7 @@
if(isturf(T))
attached = locate() in T
if(attached)
- return attached.get_powernet()
+ return attached.powernet
/obj/machinery/computer/monitor/attack_ai(mob/user)
attack_hand(user)
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index 5d4e838db38..8def58c370b 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -20,12 +20,7 @@
return
if(stat & (NOPOWER|BROKEN))
return
- var/datum/game_mode/nations/mode = get_nations_mode()
- if(!mode)
- ui_interact(user)
- else
- if(mode.kickoff)
- to_chat(user, "You have been locked out from this console!")
+ ui_interact(user)
/obj/machinery/computer/robotics/proc/is_authenticated(var/mob/user as mob)
if(user.can_admin_interact())
diff --git a/code/game/machinery/computer/salvage_ship.dm b/code/game/machinery/computer/salvage_ship.dm
index 444db205e80..93583eda0e8 100644
--- a/code/game/machinery/computer/salvage_ship.dm
+++ b/code/game/machinery/computer/salvage_ship.dm
@@ -58,7 +58,6 @@
North of the Station |
East of the Station |
South of the Station
- South-west of the Mining Asteroid |
Trading Post Clown Asteroid |
Derelict Station |
@@ -99,8 +98,6 @@
salvage_move_to(/area/shuttle/salvage/south)
else if(href_list["commssat"])
salvage_move_to(/area/shuttle/salvage/commssat)
- else if(href_list["mining"])
- salvage_move_to(/area/shuttle/salvage/mining)
else if(href_list["abandoned_ship"])
salvage_move_to(/area/shuttle/salvage/abandoned_ship)
else if(href_list["clown_asteroid"])
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index c0c8c2d349e..bed10bb0923 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -398,7 +398,7 @@
switch(href_list["field"])
if("name")
if(istype(active1, /datum/data/record))
- var/t1 = reject_bad_name(input("Please input name:", "Secure. records", active1.fields["name"], null) as text)
+ var/t1 = reject_bad_name(clean_input("Please input name:", "Secure. records", active1.fields["name"], null))
if(!t1 || !length(trim(t1)) || ..() || active1 != a1)
return 1
active1.fields["name"] = t1
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index ac10eb6e22d..5647ae73766 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -245,7 +245,7 @@
switch(href_list["field"])
if("name")
if(istype(active1, /datum/data/record))
- var/t1 = reject_bad_name(input("Please input name:", "Secure. records", active1.fields["name"], null) as text)
+ var/t1 = reject_bad_name(clean_input("Please input name:", "Secure. records", active1.fields["name"], null))
if(!t1 || !length(trim(t1)) || incapable || active1 != a1)
return 1
active1.fields["name"] = t1
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index ece6615b786..9e91e254950 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -541,21 +541,20 @@ to destroy them and players will be able to make replacements.
/obj/item/stock_parts/capacitor = 1)
/obj/item/circuitboard/chem_dispenser
- name = "circuit board (Portable Chem Dispenser)"
- build_path = /obj/machinery/chem_dispenser/constructable
+ name = "circuit board (Chem Dispenser)"
+ build_path = /obj/machinery/chem_dispenser
board_type = "machine"
origin_tech = "materials=4;programming=4;plasmatech=4;biotech=3"
frame_desc = "Requires 2 Matter Bins, 1 Capacitor, 1 Manipulator, 1 Console Screen, and 1 Power Cell."
- req_components = list(
- /obj/item/stock_parts/matter_bin = 2,
+ req_components = list( /obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/capacitor = 1,
/obj/item/stock_parts/manipulator = 1,
/obj/item/stock_parts/console_screen = 1,
/obj/item/stock_parts/cell = 1)
/obj/item/circuitboard/chem_master
- name = "circuit board (Chem Master 2999)"
- build_path = /obj/machinery/chem_master/constructable
+ name = "circuit board (ChemMaster 3000)"
+ build_path = /obj/machinery/chem_master
board_type = "machine"
origin_tech = "materials=3;programming=2;biotech=3"
req_components = list(
@@ -563,6 +562,25 @@ to destroy them and players will be able to make replacements.
/obj/item/stock_parts/manipulator = 1,
/obj/item/stock_parts/console_screen = 1)
+/obj/item/circuitboard/chem_master/attackby(obj/item/I, mob/user, params)
+ if(isscrewdriver(I))
+ var/new_name = "ChemMaster"
+ var/new_path = /obj/machinery/chem_master
+
+ if(build_path == /obj/machinery/chem_master)
+ new_name = "CondiMaster"
+ new_path = /obj/machinery/chem_master/condimaster
+
+ build_path = new_path
+ name = "circuit board ([new_name] 3000)"
+ to_chat(user, "You change the circuit board setting to \"[new_name]\".")
+ else
+ return ..()
+
+/obj/item/circuitboard/chem_master/condi_master
+ name = "circuit board (CondiMaster 3000)"
+ build_path = /obj/machinery/chem_master/condimaster
+
/obj/item/circuitboard/chem_heater
name = "circuit board (Chemical Heater)"
build_path = /obj/machinery/chem_heater
@@ -617,30 +635,13 @@ to destroy them and players will be able to make replacements.
/obj/item/stock_parts/manipulator = 2,
/obj/item/reagent_containers/glass/beaker = 2)
-/obj/item/circuitboard/soda
+/obj/item/circuitboard/chem_dispenser/soda
name = "Circuit board (Soda Machine)"
build_path = /obj/machinery/chem_dispenser/soda
- board_type = "machine"
- frame_desc = "Requires 2 Matter Bins, 1 Manipulators, 1 Capacitor, 1 Console Screen, and 1 Power Cell."
- req_components = list(
- /obj/item/stock_parts/matter_bin = 2,
- /obj/item/stock_parts/manipulator = 1,
- /obj/item/stock_parts/capacitor = 1,
- /obj/item/stock_parts/console_screen = 1,
- /obj/item/stock_parts/cell = 1)
-/obj/item/circuitboard/beer
+/obj/item/circuitboard/chem_dispenser/beer
name = "Circuit board (Beer Machine)"
build_path = /obj/machinery/chem_dispenser/beer
- board_type = "machine"
- frame_desc = "Requires 2 Matter Bins, 1 Manipulators, 1 Capacitor, 1 Console Screen, and 1 Power Cell."
- req_components = list(
- /obj/item/stock_parts/matter_bin = 2,
- /obj/item/stock_parts/manipulator = 1,
- /obj/item/stock_parts/capacitor = 1,
- /obj/item/stock_parts/console_screen = 1,
- /obj/item/stock_parts/cell = 1)
-
/obj/item/circuitboard/circuit_imprinter
name = "Circuit board (Circuit Imprinter)"
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index fc60d8f005d..b45a8331188 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -5,7 +5,8 @@
icon_state = "pod0"
density = 1
anchored = 1.0
- layer = 2.8
+ layer = ABOVE_WINDOW_LAYER
+ plane = GAME_PLANE
interact_offline = 1
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100)
var/on = 0
@@ -208,7 +209,7 @@
occupantData["stat"] = occupant.stat
occupantData["health"] = occupant.health
occupantData["maxHealth"] = occupant.maxHealth
- occupantData["minHealth"] = config.health_threshold_dead
+ occupantData["minHealth"] = HEALTH_THRESHOLD_DEAD
occupantData["bruteLoss"] = occupant.getBruteLoss()
occupantData["oxyLoss"] = occupant.getOxyLoss()
occupantData["toxLoss"] = occupant.getToxLoss()
@@ -220,7 +221,7 @@
data["cellTemperatureStatus"] = "good"
if(air_contents.temperature > T0C) // if greater than 273.15 kelvin (0 celcius)
data["cellTemperatureStatus"] = "bad"
- else if(air_contents.temperature > 225)
+ else if(air_contents.temperature > TCRYO)
data["cellTemperatureStatus"] = "average"
data["isBeakerLoaded"] = beaker ? 1 : 0
@@ -324,7 +325,6 @@
overlays += "lid[on]" //if no occupant, just put the lid overlay on, and ignore the rest
return
-
if(occupant)
var/image/pickle = image(occupant.icon, occupant.icon_state)
pickle.overlays = occupant.overlays
@@ -378,9 +378,9 @@
occupant.Paralyse(max(5/efficiency, (1/occupant.bodytemperature)*3000/efficiency))
if(air_contents.oxygen > 2)
if(occupant.getOxyLoss())
- occupant.adjustOxyLoss(-10)
+ occupant.adjustOxyLoss(-6)
else
- occupant.adjustOxyLoss(-2)
+ occupant.adjustOxyLoss(-1.2)
if(beaker && next_trans == 0)
var/proportion = 10 * min(1/beaker.volume, 1)
// Yes, this means you can get more bang for your buck with a beaker of SF vs a patch
@@ -388,7 +388,7 @@
beaker.reagents.reaction(occupant, TOUCH, proportion)
beaker.reagents.trans_to(occupant, 1, 10)
next_trans++
- if(next_trans == 10)
+ if(next_trans == 17)
next_trans = 0
/obj/machinery/atmospherics/unary/cryo_cell/proc/heat_gas_contents()
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index a1bdff99d56..f9d708a6200 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -53,7 +53,7 @@
var/dat
- if(!( ticker ))
+ if(!( SSticker ))
return
dat += " [storage_name] "
@@ -231,9 +231,9 @@
/obj/item/reagent_containers/hypospray/CMO,
/obj/item/clothing/accessory/medal/gold/captain,
/obj/item/clothing/gloves/color/black/krav_maga/sec,
- /obj/item/storage/internal,
/obj/item/spacepod_key,
- /obj/item/nullrod
+ /obj/item/nullrod,
+ /obj/item/key
)
// These items will NOT be preserved
var/list/do_not_preserve_items = list (
@@ -364,13 +364,15 @@
// Skip past any cult sacrifice objective using this person
if(GAMEMODE_IS_CULT && is_sacrifice_target(occupant.mind))
- var/datum/game_mode/cult/cult_mode = ticker.mode
+ var/datum/game_mode/cult/cult_mode = SSticker.mode
var/list/p_s_t = cult_mode.get_possible_sac_targets()
if(p_s_t.len)
cult_mode.sacrifice_target = pick(p_s_t)
- for(var/datum/mind/H in ticker.mode.cult)
+ for(var/datum/mind/H in SSticker.mode.cult)
if(H.current)
- to_chat(H.current, "[ticker.cultdat.entity_name] murmurs, [occupant] is beyond your reach. Sacrifice [cult_mode.sacrifice_target.current] instead...")
+ to_chat(H.current, "[SSticker.cultdat.entity_name] murmurs, [occupant] is beyond your reach. Sacrifice [cult_mode.sacrifice_target.current] instead...")
+ H.current << 'sound/ambience/alarm4.ogg'
+ cult_mode.update_sac_objective(occupant.mind, occupant.mind.assigned_role)
else
cult_mode.bypass_phase()
@@ -397,14 +399,14 @@
//Handle job slot/tater cleanup.
var/job = occupant.mind.assigned_role
- job_master.FreeRole(job)
+ SSjobs.FreeRole(job)
if(occupant.mind.objectives.len)
occupant.mind.objectives.Cut()
occupant.mind.special_role = null
else
- if(ticker.mode.name == "AutoTraitor")
- var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode
+ if(SSticker.mode.name == "AutoTraitor")
+ var/datum/game_mode/traitor/autotraitor/current_mode = SSticker.mode
current_mode.possible_traitors.Remove(occupant)
// Delete them from datacore.
@@ -769,3 +771,12 @@
target_cryopod.take_occupant(person_to_cryo, 1)
return 1
return 0
+
+/proc/force_cryo_human(var/mob/living/carbon/person_to_cryo)
+ if(!istype(person_to_cryo))
+ return
+ if(!istype(person_to_cryo.loc, /obj/machinery/cryopod))
+ cryo_ssd(person_to_cryo)
+ if(istype(person_to_cryo.loc, /obj/machinery/cryopod))
+ var/obj/machinery/cryopod/P = person_to_cryo.loc
+ P.despawn_occupant()
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 8fefabbf877..75c4e466a79 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -54,6 +54,7 @@
/obj/machinery/disco/Destroy()
dance_over()
selection = null
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/machinery/disco/attackby(obj/item/O, mob/user, params)
@@ -128,7 +129,7 @@
active = TRUE
update_icon()
dance_setup()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
lights_spin()
updateUsrDialog()
else if(active)
@@ -472,7 +473,7 @@
L.stop_sound_channel(CHANNEL_JUKEBOX)
else if(active)
active = FALSE
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
dance_over()
playsound(src,'sound/machines/terminal_off.ogg',50,1)
icon_state = "disco0"
diff --git a/code/game/machinery/defib_mount.dm b/code/game/machinery/defib_mount.dm
index 49c5fbcbce6..77d68590efa 100644
--- a/code/game/machinery/defib_mount.dm
+++ b/code/game/machinery/defib_mount.dm
@@ -15,6 +15,10 @@
var/obj/item/defibrillator/defib //this mount's defibrillator
var/clamps_locked = FALSE //if true, and a defib is loaded, it can't be removed without unlocking the clamps
+/obj/machinery/defibrillator_mount/get_cell()
+ if(defib)
+ return defib.get_cell()
+
/obj/machinery/defibrillator_mount/New(location, direction, building = 0)
..()
@@ -28,7 +32,6 @@
pixel_x = (dir & 3)? 0 : (dir == 4 ? -30 : 30)
pixel_y = (dir & 3)? (dir == 1 ? -30 : 30) : 0
-
/obj/machinery/defibrillator_mount/loaded/New() //loaded subtype for mapping use
..()
defib = new/obj/item/defibrillator/loaded(src)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 54153118131..17b6f9e55c8 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -51,6 +51,7 @@ var/list/airlock_overlays = list()
explosion_block = 1
assemblytype = /obj/structure/door_assembly
normalspeed = 1
+ siemens_strength = 1
var/security_level = 0 //How much are wires secured
var/aiControlDisabled = FALSE //If TRUE, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
var/hackProof = FALSE // if TRUE, this door can't be hacked by the AI
@@ -70,7 +71,7 @@ var/list/airlock_overlays = list()
var/lockdownbyai = 0
var/justzap = 0
var/obj/item/airlock_electronics/electronics
- var/hasShocked = 0 //Prevents multiple shocks from happening
+ var/shockCooldown = FALSE //Prevents multiple shocks from happening
var/obj/item/note //Any papers pinned to the airlock
var/previous_airlock = /obj/structure/door_assembly //what airlock assembly mineral plating was applied to
var/airlock_material //material of inner filling; if its an airlock with glass, this should be set to "glass"
@@ -151,8 +152,8 @@ About the new airlock wires panel:
if(electrified_timer)
deltimer(electrified_timer)
electrified_timer = null
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
@@ -173,10 +174,8 @@ About the new airlock wires panel:
else /*if(justzap)*/
return
else if(user.hallucination > 50 && prob(10) && !operating)
- to_chat(user, "You feel a powerful shock course through your body!")
- user.adjustStaminaLoss(50)
- user.AdjustStunned(5)
- return
+ if(user.electrocute_act(50, src, 1, illusion = TRUE)) // We'll just go with a flat 50 damage, instead of doing powernet checks
+ return
..(user)
/obj/machinery/door/airlock/bumpopen(mob/living/simple_animal/user)
@@ -296,16 +295,14 @@ About the new airlock wires panel:
// The preceding comment was borrowed from the grille's shock script
/obj/machinery/door/airlock/shock(mob/user, prb)
if(!arePowerSystemsOn())
- return 0
- if(hasShocked)
- return 0 //Already shocked someone recently?
+ return FALSE
+ if(shockCooldown > world.time)
+ return FALSE //Already shocked someone recently?
if(..())
- hasShocked = 1
- sleep(10)
- hasShocked = 0
- return 1
+ shockCooldown = world.time + 10
+ return TRUE
else
- return 0
+ return FALSE
//Checks if the user can get shocked and shocks him if it can. Returns TRUE if it happened
/obj/machinery/door/airlock/proc/shock_user(mob/user, prob)
@@ -314,6 +311,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/update_icon(state=0, override=0)
if(operating && !override)
return
+ check_unres()
icon_state = density ? "closed" : "open"
switch(state)
if(0)
@@ -336,7 +334,6 @@ About the new airlock wires panel:
var/image/sparks_overlay
var/image/note_overlay
var/notetype = note_type()
-
switch(state)
if(AIRLOCK_CLOSED)
frame_overlay = get_airlock_overlay("closed", icon)
@@ -624,6 +621,31 @@ About the new airlock wires panel:
if(user)
attack_ai(user)
+/obj/machinery/door/airlock/proc/check_unres() //unrestricted sides. This overlay indicates which directions the player can access even without an ID
+ if(hasPower() && unres_sides)
+ if(unres_sides & NORTH)
+ var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_n") //layer=src.layer+1
+ I.pixel_y = 32
+ set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
+ add_overlay(I)
+ if(unres_sides & SOUTH)
+ var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_s") //layer=src.layer+1
+ I.pixel_y = -32
+ set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
+ add_overlay(I)
+ if(unres_sides & EAST)
+ var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_e") //layer=src.layer+1
+ I.pixel_x = 32
+ set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
+ add_overlay(I)
+ if(unres_sides & WEST)
+ var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_w") //layer=src.layer+1
+ I.pixel_x = -32
+ set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
+ add_overlay(I)
+ else
+ set_light(0)
+
/obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=0)
if(isElectrified() && density && istype(mover, /obj/item))
var/obj/item/I = mover
diff --git a/code/game/machinery/doors/airlock_control.dm b/code/game/machinery/doors/airlock_control.dm
index 7eb43cdec74..3b12c6f554a 100644
--- a/code/game/machinery/doors/airlock_control.dm
+++ b/code/game/machinery/doors/airlock_control.dm
@@ -39,8 +39,7 @@
if(command_completed(cur_command))
cur_command = null
else
- if(!isprocessing)
- START_PROCESSING(SSmachines, src)
+ START_PROCESSING(SSmachines, src)
/obj/machinery/door/airlock/proc/do_command(command)
switch(command)
@@ -127,10 +126,10 @@
return
/obj/machinery/door/airlock/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
if(new_frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK)
/obj/machinery/door/airlock/Initialize()
..()
@@ -143,7 +142,7 @@
/obj/machinery/door/airlock/New()
..()
- if(radio_controller)
+ if(SSradio)
set_frequency(frequency)
/obj/machinery/airlock_sensor
@@ -203,9 +202,9 @@
update_icon()
/obj/machinery/airlock_sensor/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK)
/obj/machinery/airlock_sensor/Initialize()
..()
@@ -213,12 +212,12 @@
/obj/machinery/airlock_sensor/New()
..()
- if(radio_controller)
+ if(SSradio)
set_frequency(frequency)
/obj/machinery/airlock_sensor/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
@@ -256,10 +255,15 @@
return
..()
+/obj/machinery/access_button/attack_ghost(mob/user)
+ if(user.can_advanced_admin_interact())
+ return attack_hand(user)
+
/obj/machinery/access_button/attack_hand(mob/user)
add_fingerprint(usr)
- if(!allowed(user))
- to_chat(user, "Access Denied")
+
+ if(!allowed(user) && !user.can_advanced_admin_interact())
+ to_chat(user, "Access denied.")
else if(radio_connection)
var/datum/signal/signal = new
@@ -271,9 +275,9 @@
flick("access_button_cycle", src)
/obj/machinery/access_button/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK)
/obj/machinery/access_button/Initialize()
..()
@@ -282,12 +286,12 @@
/obj/machinery/access_button/New()
..()
- if(radio_controller)
+ if(SSradio)
set_frequency(frequency)
/obj/machinery/access_button/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm
index df63da64f2b..01d90795a87 100644
--- a/code/game/machinery/doors/airlock_electronics.dm
+++ b/code/game/machinery/doors/airlock_electronics.dm
@@ -11,6 +11,8 @@
var/list/conf_access = null
var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access
var/const/max_brain_damage = 60 // Maximum brain damage a mob can have until it can't use the electronics
+ var/unres_sides = 0
+ var/unres_direction = null
/obj/item/airlock_electronics/attack_self(mob/user)
if(!ishuman(user) && !isrobot(user))
@@ -23,14 +25,22 @@
return
var/t1 = text("Access control \n")
+ t1 += ""
+ t1 += " Unrestricted Access Settings "
+ var/list/Directions = list("North","South",,"East",,,,"West")
+ for(var/direction in cardinal)
+ if (unres_direction && unres_direction == direction)
+ t1 += "[Directions[direction]] "
+ else
+ t1 += "[Directions[direction]] "
+
+ t1 += ""
t1 += "Access requirement is set to "
t1 += one_access ? "ONE" : "ALL"
t1 += conf_access == null ? "All " : "All "
- t1 += " "
-
var/list/accesses = get_all_accesses()
for(var/acc in accesses)
var/aname = get_access_desc(acc)
@@ -64,6 +74,14 @@
if(href_list["access"])
toggle_access(href_list["access"])
+
+ if(href_list["unres_direction"])
+ unres_direction = text2num(href_list["unres_direction"])
+ if (unres_sides == unres_direction)
+ unres_sides = 0
+ unres_direction = null
+ else
+ unres_sides = unres_direction
attack_self(usr)
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index 8e3c7f76342..a0d6efc5d1f 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -542,7 +542,7 @@
icon = 'icons/obj/doors/airlocks/glass_large/glass_large.dmi'
overlays_file = 'icons/obj/doors/airlocks/glass_large/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/glass_large/overlays.dmi'
- assemblytype = "obj/structure/door_assembly/multi_tile"
+ assemblytype = /obj/structure/door_assembly/multi_tile
/obj/machinery/door/airlock/multi_tile/narsie_act()
return
diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm
index 91591234551..d3bf12f72f0 100644
--- a/code/game/machinery/doors/alarmlock.dm
+++ b/code/game/machinery/doors/alarmlock.dm
@@ -13,15 +13,15 @@
air_connection = new
/obj/machinery/door/airlock/alarmlock/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src,air_frequency)
+ if(SSradio)
+ SSradio.remove_object(src,air_frequency)
air_connection = null
return ..()
/obj/machinery/door/airlock/alarmlock/Initialize()
..()
- radio_controller.remove_object(src, air_frequency)
- air_connection = radio_controller.add_object(src, air_frequency, RADIO_TO_AIRALARM)
+ SSradio.remove_object(src, air_frequency)
+ air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM)
open()
/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index adf22a06850..fdfaae71477 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -28,7 +28,7 @@
var/real_explosion_block //ignore this, just use explosion_block
var/heat_proof = FALSE // For rglass-windowed airlocks and firedoors
var/emergency = FALSE
-
+ var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access
//Multi-tile doors
var/width = 1
@@ -55,6 +55,10 @@
..()
update_dir()
+/obj/machinery/door/power_change()
+ ..()
+ update_icon()
+
/obj/machinery/door/proc/update_dir()
if(width > 1)
if(dir in list(EAST, WEST))
@@ -134,8 +138,6 @@
if(operating)
return
add_fingerprint(user)
- if(!requiresID())
- user = null
if(density && !emagged)
if(allowed(user))
@@ -157,7 +159,7 @@
return try_to_activate_door(user)
/obj/machinery/door/attack_tk(mob/user)
- if(requiresID() && !allowed(null))
+ if(!allowed(null))
return
..()
@@ -165,9 +167,7 @@
add_fingerprint(user)
if(operating || emagged)
return
- if(!requiresID())
- user = null //so allowed(user) always succeeds
- if(allowed(user) || user.can_advanced_admin_interact())
+ if(requiresID() && (allowed(user) || user.can_advanced_admin_interact()))
if(density)
open()
else
@@ -179,8 +179,15 @@
/obj/machinery/door/allowed(mob/M)
if(emergency)
return TRUE
+ if(unrestricted_side(M))
+ return TRUE
+ if(!requiresID())
+ return FALSE // Intentional. machinery/door/requiresID() always == 1. airlocks, however, == 0 if ID scan is disabled. Yes, this var is poorly named.
return ..()
+/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter)
+ return get_dir(src, M) & unres_sides
+
/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user)
return
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 21ff909796f..549b5be3929 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -77,7 +77,7 @@
else
do_animate("deny")
return
- if(!ticker)
+ if(!SSticker)
return
var/mob/living/M = AM
if(!M.restrained() && M.mob_size > MOB_SIZE_TINY && (!(isrobot(M) && M.stat)))
@@ -87,10 +87,7 @@
if(operating || !density)
return
add_fingerprint(user)
- if(!requiresID())
- user = null
-
- if(allowed(user))
+ if(!requiresID() || allowed(user))
open_and_close()
else
do_animate("deny")
@@ -217,7 +214,7 @@
return attack_hand(user)
/obj/machinery/door/window/attack_hand(mob/user)
- return attackby(user, user)
+ return try_to_activate_door(user)
/obj/machinery/door/window/emag_act(mob/user, obj/weapon)
if(!operating && density && !emagged)
@@ -231,7 +228,6 @@
return 1
/obj/machinery/door/window/attackby(obj/item/I, mob/living/user, params)
-
//If it's in the process of opening/closing, ignore the click
if(operating)
return
diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm
index 5209003fc59..b1a6f96e2eb 100644
--- a/code/game/machinery/embedded_controller/airlock_controllers.dm
+++ b/code/game/machinery/embedded_controller/airlock_controllers.dm
@@ -76,6 +76,21 @@
name = "Airlock Controller"
tag_secure = 1
+/obj/machinery/embedded_controller/radio/airlock/airlock_controller/Initialize(mapload, given_id_tag, given_frequency, given_tag_exterior_door, given_tag_interior_door, given_tag_airpump, given_tag_chamber_sensor)
+ if(given_id_tag)
+ id_tag = given_id_tag
+ if(given_frequency)
+ set_frequency(given_frequency)
+ if(given_tag_exterior_door)
+ tag_exterior_door = given_tag_exterior_door
+ if(given_tag_interior_door)
+ tag_interior_door = given_tag_interior_door
+ if(given_tag_airpump)
+ tag_airpump = given_tag_airpump
+ if(given_tag_chamber_sensor)
+ tag_chamber_sensor = given_tag_chamber_sensor
+ ..()
+
/obj/machinery/embedded_controller/radio/airlock/airlock_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -129,7 +144,6 @@
name = "Access Controller"
tag_secure = 1
-
/obj/machinery/embedded_controller/radio/airlock/access_controller/update_icon()
if(on && program)
if(program.memory["processing"])
diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm
index 23ee6e19403..e0a49fdfc8c 100644
--- a/code/game/machinery/embedded_controller/embedded_controller_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm
@@ -59,8 +59,8 @@
set_frequency(frequency)
/obj/machinery/embedded_controller/radio/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
@@ -82,6 +82,6 @@
qdel(signal)
/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, radio_filter)
+ radio_connection = SSradio.add_object(src, frequency, radio_filter)
diff --git a/code/game/machinery/embedded_controller/embedded_program_base.dm b/code/game/machinery/embedded_controller/embedded_program_base.dm
index 1fe527df13b..5bd46b2f3e0 100644
--- a/code/game/machinery/embedded_controller/embedded_program_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_program_base.dm
@@ -17,8 +17,8 @@
/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
return
-/datum/computer/file/embedded_program/proc/process()
- return
+/datum/computer/file/embedded_program/process()
+ return FALSE
/datum/computer/file/embedded_program/proc/post_signal(datum/signal/signal, comm_line)
if(master)
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index f1651d5bb99..e9504157063 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -21,6 +21,16 @@ FIRE ALARM
var/wiresexposed = 0
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
+ var/report_fire_alarms = TRUE // Should triggered fire alarms also trigger an actual alarm?
+ var/show_alert_level = TRUE // Should fire alarms display the current alert level?
+
+/obj/machinery/firealarm/no_alarm
+ report_fire_alarms = FALSE
+
+/obj/machinery/firealarm/syndicate
+ report_fire_alarms = FALSE
+ show_alert_level = FALSE
+
/obj/machinery/firealarm/update_icon()
if(wiresexposed)
@@ -143,7 +153,7 @@ FIRE ALARM
alarm()
time = 0
timing = 0
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
updateDialog()
last_process = world.timeofday
@@ -206,49 +216,47 @@ FIRE ALARM
last_process = world.timeofday
if(oldTiming != timing)
if(timing)
- processing_objects += src
+ START_PROCESSING(SSobj, src)
else
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
else if(href_list["tp"])
var/tp = text2num(href_list["tp"])
time += tp
time = min(max(round(time), 0), 120)
/obj/machinery/firealarm/proc/reset()
- if(!( working ))
+ if(!working)
return
var/area/A = get_area(src)
A.fire_reset()
+
for(var/obj/machinery/firealarm/FA in A)
- fire_alarm.clearAlarm(loc, FA)
- return
+ if(is_station_contact(z) && FA.report_fire_alarms)
+ SSalarms.fire_alarm.clearAlarm(loc, FA)
/obj/machinery/firealarm/proc/alarm(var/duration = 0)
- if(!( working))
+ if(!working)
return
+
var/area/A = get_area(src)
for(var/obj/machinery/firealarm/FA in A)
- fire_alarm.triggerAlarm(loc, FA, duration)
+ if(is_station_contact(z) && FA.report_fire_alarms)
+ SSalarms.fire_alarm.triggerAlarm(loc, FA, duration)
+ else
+ A.fire_alert() // Manually trigger alarms if the alarm isn't reported
+
update_icon()
- //playsound(loc, 'sound/ambience/signal.ogg', 75, 0)
- return
/obj/machinery/firealarm/New(location, direction, building)
..()
- if(location)
- loc = location
-
- if(direction)
- dir = direction
-
if(building)
buildstage = 0
- wiresexposed = 1
+ wiresexposed = TRUE
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
- if(is_station_contact(z))
+ if(is_station_contact(z) && show_alert_level)
if(security_level)
overlays += image('icons/obj/monitors.dmi', "overlay_[get_security_level()]")
else
diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm
index c11b3d7a725..68e22f2e8c7 100644
--- a/code/game/machinery/floodlight.dm
+++ b/code/game/machinery/floodlight.dm
@@ -12,6 +12,8 @@
var/open = FALSE
var/brightness_on = 14
+/obj/machinery/floodlight/get_cell()
+ return cell
/obj/machinery/floodlight/Initialize()
. = ..()
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 49a05371050..e6d967c8eb4 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -44,6 +44,7 @@ var/list/holopads = list()
idle_power_usage = 5
active_power_usage = 100
layer = TURF_LAYER+0.1 //Preventing mice and drones from sneaking under them.
+ plane = FLOOR_PLANE
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0)
var/list/masters = list()//List of living mobs that use the holopad
var/list/holorays = list()//Holoray-mob link.
diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm
index 3c36edb1685..22cf6d56ecd 100755
--- a/code/game/machinery/igniter.dm
+++ b/code/game/machinery/igniter.dm
@@ -3,14 +3,18 @@
desc = "It's useful for igniting plasma."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "igniter1"
+ plane = FLOOR_PLANE
armor = list(melee = 50, bullet = 30, laser = 70, energy = 50, bomb = 20, bio = 0, rad = 0)
var/id = null
- var/on = 1.0
- anchored = 1.0
+ var/on = FALSE
+ anchored = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 2
active_power_usage = 4
+/obj/machinery/igniter/on
+ on = TRUE
+
/obj/machinery/igniter/attack_ai(mob/user as mob)
return src.attack_hand(user)
@@ -50,8 +54,8 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "migniter"
var/id = null
- var/disable = 0
- var/last_spark = 0
+ var/disable = FALSE
+ var/last_spark = FALSE
var/base_state = "migniter"
anchored = 1
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index d0399dfa2a4..ee6bd060c16 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -30,7 +30,7 @@
pixel_x = 25
if(WEST)
pixel_x = -25
- if(radio_controller)
+ if(SSradio)
set_frequency(frequency)
spawn(5)
src.area = get_area(src)
@@ -49,14 +49,14 @@
set_frequency(frequency)
/obj/machinery/light_switch/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_LOGIC)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_LOGIC)
return
/obj/machinery/light_switch/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 553016400ad..f8305e0fb7d 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -118,24 +118,22 @@ Class Procs:
var/use_log = list()
var/list/settagwhitelist = list()//WHITELIST OF VARIABLES THAT THE set_tag HREF CAN MODIFY, DON'T PUT SHIT YOU DON'T NEED ON HERE, AND IF YOU'RE GONNA USE set_tag (format_tag() proc), ADD TO THIS LIST.
atom_say_verb = "beeps"
- var/defer_process = 0
+ var/siemens_strength = 0.7 // how badly will it shock you?
-/obj/machinery/Initialize()
- addAtProcessing()
+/obj/machinery/Initialize(mapload)
+ if(!armor)
+ armor = list(melee = 25, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0)
. = ..()
- power_change()
+ GLOB.machines += src
-/obj/machinery/proc/addAtProcessing()
if(use_power)
myArea = get_area(src)
if(!speed_process)
- if(!defer_process)
- START_PROCESSING(SSmachines, src)
- else
- START_DEFERRED_PROCESSING(SSmachines, src)
+ START_PROCESSING(SSmachines, src)
else
- GLOB.fast_processing += src
- isprocessing = TRUE // all of these isprocessing = TRUE can be removed when the PS is dead
+ START_PROCESSING(SSfastprocess, src)
+
+ power_change()
// gotta go fast
/obj/machinery/makeSpeedProcess()
@@ -143,28 +141,24 @@ Class Procs:
return
speed_process = TRUE
STOP_PROCESSING(SSmachines, src)
- GLOB.fast_processing += src
+ START_PROCESSING(SSfastprocess, src)
// gotta go slow
/obj/machinery/makeNormalProcess()
if(!speed_process)
return
speed_process = FALSE
+ STOP_PROCESSING(SSfastprocess, src)
START_PROCESSING(SSmachines, src)
- GLOB.fast_processing -= src
-
-/obj/machinery/New() //new
- if(!armor)
- armor = list(melee = 25, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0)
- GLOB.machines += src
- ..()
/obj/machinery/Destroy()
if(myArea)
myArea = null
- GLOB.fast_processing -= src
- STOP_PROCESSING(SSmachines, src)
- GLOB.machines -= src
+ GLOB.machines.Remove(src)
+ if(!speed_process)
+ STOP_PROCESSING(SSmachines, src)
+ else
+ STOP_PROCESSING(SSfastprocess, src)
return ..()
/obj/machinery/proc/locate_machinery()
@@ -354,28 +348,28 @@ Class Procs:
return attack_hand(user)
/obj/machinery/attack_hand(mob/user as mob)
- if(user.lying || user.stat)
- return 1
+ if(user.incapacitated())
+ return TRUE
if(!user.IsAdvancedToolUser())
to_chat(user, "You don't have the dexterity to do this!")
- return 1
+ return TRUE
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.getBrainLoss() >= 60)
visible_message("[H] stares cluelessly at [src] and drools.")
- return 1
+ return TRUE
else if(prob(H.getBrainLoss()))
to_chat(user, "You momentarily forget how to use [src].")
- return 1
+ return TRUE
if(panel_open)
add_fingerprint(user)
- return 0
+ return FALSE
if(!interact_offline && stat & (NOPOWER|BROKEN|MAINT))
- return 1
+ return TRUE
add_fingerprint(user)
@@ -407,7 +401,7 @@ Class Procs:
if(can_deconstruct)
on_deconstruction()
if(component_parts && component_parts.len)
- spawn_frame()
+ spawn_frame(disassembled)
for(var/obj/item/I in component_parts)
I.forceMove(loc)
qdel(src)
@@ -559,9 +553,7 @@ Class Procs:
threatcount += 2
if(check_records || check_arrest)
- var/perpname = perp.name
- if(id)
- perpname = id.registered_name
+ var/perpname = perp.get_visible_name(TRUE)
var/datum/data/record/R = find_security_record("name", perpname)
if(check_records && !R)
@@ -575,16 +567,13 @@ Class Procs:
/obj/machinery/proc/shock(mob/user, prb)
if(inoperable())
- return 0
+ return FALSE
if(!prob(prb))
- return 0
- if((TK in user.mutations) && !Adjacent(user))
- return 0
+ return FALSE
do_sparks(5, 1, src)
- if(electrocute_mob(user, get_area(src), src, 0.7))
- if(user.stunned)
- return 1
- return 0
+ if(electrocute_mob(user, get_area(src), src, siemens_strength, TRUE))
+ return TRUE
+ return FALSE
//called on machinery construction (i.e from frame to machinery) but not on initialization
/obj/machinery/proc/on_construction()
@@ -604,3 +593,11 @@ Class Procs:
emp_act(EMP_LIGHT)
else
ex_act(EXPLODE_HEAVY)
+
+/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
+ var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
+ for (var/i in 1 to 32)
+ . += hex2num(md5[i])
+ . = . % 9
+ AM.pixel_x = -8 + ((.%3)*8)
+ AM.pixel_y = -8 + (round( . / 3)*8)
diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm
index 3af76895428..9b982df99fd 100644
--- a/code/game/machinery/magnet.dm
+++ b/code/game/machinery/magnet.dm
@@ -36,8 +36,8 @@
center = T
spawn(10) // must wait for map loading to finish
- if(radio_controller)
- radio_controller.add_object(src, freq, RADIO_MAGNETS)
+ if(SSradio)
+ SSradio.add_object(src, freq, RADIO_MAGNETS)
spawn()
magnetic_process()
@@ -208,8 +208,8 @@
spawn(45) // must wait for map loading to finish
- if(radio_controller)
- radio_connection = radio_controller.add_object(src, frequency, RADIO_MAGNETS)
+ if(SSradio)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_MAGNETS)
if(path) // check for default path
@@ -217,8 +217,8 @@
/obj/machinery/magnetic_controller/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm
index f278ee2adda..d4175b10ae1 100644
--- a/code/game/machinery/navbeacon.dm
+++ b/code/game/machinery/navbeacon.dm
@@ -72,7 +72,7 @@
// called when turf state changes
// hide the object if turf is intact
/obj/machinery/navbeacon/hide(intact)
- invisibility = intact ? INVISIBILITY_MAXIMUM : SEE_INVISIBLE_MINIMUM
+ invisibility = intact ? INVISIBILITY_MAXIMUM : 0
updateicon()
// update the icon_state
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 2e4b7b19378..f354feb1629 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -284,7 +284,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(12)
var/list/jobs = list()
data["jobs"] = jobs
- for(var/datum/job/job in job_master.occupations)
+ for(var/datum/job/job in SSjobs.occupations)
if(job_blacklisted(job))
continue
if(job.is_position_available())
diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm
index e98c4e90c30..e77eef869dc 100644
--- a/code/game/machinery/overview.dm
+++ b/code/game/machinery/overview.dm
@@ -183,8 +183,8 @@
qdel(I)
qdel(J)
H.icon = HI
- H.layer = 25
- H.plane = HUD_PLANE
+ H.layer = ABOVE_HUD_LAYER
+ H.plane = ABOVE_HUD_PLANE
usr.mapobjs += H
#else
diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm
index 1b3dfe19001..bb5847fc6fb 100644
--- a/code/game/machinery/pipe/pipe_dispenser.dm
+++ b/code/game/machinery/pipe/pipe_dispenser.dm
@@ -2,8 +2,8 @@
name = "Pipe Dispenser"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "pipe_d"
- density = 1
- anchored = 1
+ density = TRUE
+ anchored = TRUE
var/unwrenched = 0
var/wait = 0
@@ -75,29 +75,25 @@
/obj/machinery/pipedispenser/Topic(href, href_list)
if(..() || unwrenched)
- return 1
+ return
usr.set_machine(src)
add_fingerprint(usr)
+ if(world.time < wait + 4)
+ return
+ wait = world.time
if(href_list["make"])
- if(!wait)
- var/p_type = text2num(href_list["make"])
- var/p_dir = text2num(href_list["dir"])
- var/obj/item/pipe/P = new (loc, pipe_type=p_type, dir=p_dir)
- P.update()
- P.add_fingerprint(usr)
- wait = world.time + 10
+ var/p_type = text2num(href_list["make"])
+ var/p_dir = text2num(href_list["dir"])
+ var/obj/item/pipe/P = new (loc, pipe_type=p_type, dir=p_dir)
+ P.update()
+ P.add_fingerprint(usr)
if(href_list["makemeter"])
- if(wait < world.time)
- new /obj/item/pipe_meter(loc)
- wait = world.time + 15
+ new /obj/item/pipe_meter(loc)
if(href_list["makegsensor"])
- if(!wait)
- new /obj/item/pipe_gsensor(loc)
- wait = 1
- spawn(15)
- wait = 0
+ new /obj/item/pipe_gsensor(loc)
+ return TRUE
/obj/machinery/pipedispenser/attackby(var/obj/item/W as obj, var/mob/user as mob, params)
add_fingerprint(usr)
@@ -140,8 +136,6 @@
name = "Disposal Pipe Dispenser"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "pipe_d"
- density = 1
- anchored = 1.0
//Allow you to drag-drop disposal pipes into it
/obj/machinery/pipedispenser/disposal/MouseDrop_T(var/obj/structure/disposalconstruct/pipe, mob/usr)
@@ -182,16 +176,10 @@
popup.open()
/obj/machinery/pipedispenser/disposal/Topic(href, href_list)
- if(..() || unwrenched)
- return 1
-
- usr.set_machine(src)
- add_fingerprint(usr)
-
- if(wait < world.time)
+ if(!..())
+ return
+ if(href_list["dmake"])
var/p_type = text2num(href_list["dmake"])
var/obj/structure/disposalconstruct/C = new(loc, p_type)
if(p_type in list(PIPE_DISPOSALS_BIN, PIPE_DISPOSALS_OUTLET, PIPE_DISPOSALS_CHUTE))
C.density = TRUE
- C.add_fingerprint(usr)
- wait = world.time + 15
diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm
index 17fae9df6f6..0d6f76aad38 100644
--- a/code/game/machinery/poolcontroller.dm
+++ b/code/game/machinery/poolcontroller.dm
@@ -20,13 +20,36 @@
var/list/linkedmist = list() //Used to keep track of created mist
var/deep_water = FALSE //set to 1 to drown even standing people
+/obj/machinery/poolcontroller/invisible
+ invisibility = INVISIBILITY_MAXIMUM
+ name = "Water Controller"
+ desc = "An invisible water controller. Players shouldn't see this."
-/obj/machinery/poolcontroller/New() //This proc automatically happens on world start
+/obj/machinery/poolcontroller/invisible/sea
+ name = "Sea Controller"
+ desc = "A controller for the underwater portion of the sea. Players shouldn't see this."
+ deep_water = TRUE
+
+/obj/machinery/poolcontroller/Initialize(mapload)
+ var/contents_loop = linked_area
if(!linked_area)
- for(var/turf/simulated/floor/beach/water/W in range(srange,src)) //Search for /turf/simulated/floor/beach/water in the range of var/srange
- linkedturfs += W //Add found pool turfs to the central list.
- W.linkedcontroller = src // And add the linked controller to itself.
- ..() //Changed to call parent as per MarkvA's recommendation
+ contents_loop = range(srange, src)
+
+ for(var/turf/T in contents_loop)
+ if(istype(T, /turf/simulated/floor/beach/water))
+ var/turf/simulated/floor/beach/water/W = T
+ W.linkedcontroller = src
+ linkedturfs += T
+ else if(istype(T, /turf/unsimulated/beach/water))
+ var/turf/unsimulated/beach/water/W = T
+ W.linkedcontroller = src
+ linkedturfs += T
+
+ . = ..()
+
+/obj/machinery/poolcontroller/invisible/Initialize(mapload)
+ linked_area = get_area(src)
+ . = ..()
/obj/machinery/poolcontroller/emag_act(user as mob) //Emag_act, this is called when it is hit with a cryptographic sequencer.
if(!emagged) //If it is not already emagged, emag it.
@@ -190,20 +213,6 @@
return 1
-/obj/machinery/poolcontroller/seacontroller
- invisibility = 101
- unacidable = 1
- name = "Sea Controller"
- desc = "A controller for the underwater portion of the sea. Players shouldn't see this."
- deep_water = TRUE //deep sea is deep water
-
-/obj/machinery/poolcontroller/seacontroller/Initialize()
- linked_area = get_area(src)
- for(var/turf/unsimulated/beach/water/W in linked_area)
- linkedturfs += W //Add found pool turfs to the central list.
- W.linkedcontroller = src // And add the linked controller to itself.
- ..()
-
#undef FRIGID
#undef COOL
#undef NORMAL
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index e3ba1e642a9..8f542a2ea3c 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -977,6 +977,7 @@ var/list/turret_icons
/atom/movable/porta_turret_cover
icon = 'icons/obj/turrets.dmi'
+ anchored = TRUE
// Syndicate turrets
/obj/machinery/porta_turret/syndicate
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 81006be3fdd..b8f2d153d9f 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -8,6 +8,7 @@
idle_power_usage = 4
active_power_usage = 250
var/obj/item/charging = null
+ var/using_power = FALSE
var/list/allowed_devices = list(/obj/item/gun/energy, /obj/item/melee/baton, /obj/item/modular_computer, /obj/item/rcs, /obj/item/bodyanalyzer)
var/icon_state_off = "rechargeroff"
var/icon_state_charged = "recharger2"
@@ -81,22 +82,21 @@
if(stat & (NOPOWER|BROKEN) || !anchored)
return
- var/using_power = 0
+ using_power = FALSE
if(charging)
if(istype(charging, /obj/item/gun/energy))
var/obj/item/gun/energy/E = charging
if(E.power_supply.charge < E.power_supply.maxcharge)
E.power_supply.give(E.power_supply.chargerate)
use_power(250)
- using_power = 1
-
+ using_power = TRUE
if(istype(charging, /obj/item/melee/baton))
var/obj/item/melee/baton/B = charging
if(B.bcell)
if(B.bcell.give(B.bcell.chargerate))
use_power(200)
- using_power = 1
+ using_power = TRUE
if(istype(charging, /obj/item/modular_computer))
var/obj/item/modular_computer/C = charging
@@ -107,21 +107,21 @@
if(B.battery.charge < B.battery.maxcharge)
B.battery.give(B.battery.chargerate)
use_power(200)
- using_power = 1
+ using_power = TRUE
if(istype(charging, /obj/item/rcs))
var/obj/item/rcs/R = charging
if(R.rcell)
if(R.rcell.give(R.rcell.chargerate))
use_power(200)
- using_power = 1
+ using_power = TRUE
if(istype(charging, /obj/item/bodyanalyzer))
var/obj/item/bodyanalyzer/B = charging
if(B.power_supply)
if(B.power_supply.give(B.power_supply.chargerate))
use_power(200)
- using_power = 1
+ using_power = TRUE
update_icon(using_power)
@@ -141,7 +141,7 @@
B.bcell.charge = 0
..(severity)
-/obj/machinery/recharger/update_icon(using_power = 0) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
+/obj/machinery/recharger/update_icon(using_power = FALSE) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
if(stat & (NOPOWER|BROKEN) || !anchored)
icon_state = icon_state_off
return
@@ -153,6 +153,23 @@
return
icon_state = icon_state_idle
+/obj/machinery/recharger/examine(mob/user)
+ ..()
+ if(charging && (!in_range(user, src) && !issilicon(user) && !isobserver(user)))
+ to_chat(user, "You're too far away to examine [src]'s contents and display!")
+ return
+
+ if(charging)
+ to_chat(user, "\The [src] contains:")
+ to_chat(user, "- \A [charging].")
+ if(!(stat & (NOPOWER|BROKEN)))
+ var/obj/item/stock_parts/cell/C = charging.get_cell()
+ to_chat(user, "The status display reads:")
+ if(using_power)
+ to_chat(user, "- Recharging [(C.chargerate/C.maxcharge)*100]% cell charge per cycle.")
+ if(charging)
+ to_chat(user, "- \The [charging]'s cell is at [C.percent()]%.")
+
// Atlantis: No need for that copy-pasta code, just use var to store icon_states instead.
/obj/machinery/recharger/wallcharger
name = "wall recharger"
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index 3777dfc866d..ccba902b058 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -12,6 +12,9 @@
var/set_temperature = 50 // in celcius, add T0C for kelvin
var/heating_power = 40000
+/obj/machinery/space_heater/get_cell()
+ return cell
+
/obj/machinery/space_heater/New()
..()
cell = new(src)
@@ -39,7 +42,6 @@
else
to_chat(user, "The charge meter reads [cell ? round(cell.percent(),1) : 0]%")
-
/obj/machinery/space_heater/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
..(severity)
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index 5f875d7fdc8..642676c6eff 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -50,15 +50,15 @@
var/const/STATUS_DISPLAY_CUSTOM = 99
/obj/machinery/status_display/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src,frequency)
+ if(SSradio)
+ SSradio.remove_object(src,frequency)
return ..()
// register for radio system
/obj/machinery/status_display/Initialize()
..()
- if(radio_controller)
- radio_controller.add_object(src, frequency)
+ if(SSradio)
+ SSradio.add_object(src, frequency)
// timed process
/obj/machinery/status_display/process()
@@ -78,6 +78,9 @@
set_picture("ai_bsod")
..(severity)
+/obj/machinery/status_display/get_spooked()
+ spookymode = TRUE
+
// set what is displayed
/obj/machinery/status_display/proc/update()
if(friendc && !ignore_friendc)
@@ -227,6 +230,9 @@
set_picture("ai_bsod")
..(severity)
+/obj/machinery/ai_status_display/get_spooked()
+ spookymode = TRUE
+
/obj/machinery/ai_status_display/proc/update()
if(mode==0) //Blank
overlays.Cut()
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index b09d80bd804..3776e18e450 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -11,11 +11,13 @@
var/obj/item/clothing/suit/space/suit = null
var/obj/item/clothing/head/helmet/space/helmet = null
var/obj/item/clothing/mask/mask = null
+ var/obj/item/clothing/shoes/magboots/magboots = null
var/obj/item/storage = null
var/helmet_type = null
var/suit_type = null
var/mask_type = null
+ var/magboots_type = null
var/storage_type = null
var/locked = FALSE
@@ -63,7 +65,7 @@
suit_type = /obj/item/clothing/suit/space/hardsuit/engineering
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/engineering
mask_type = /obj/item/clothing/mask/breath
- storage_type = /obj/item/clothing/shoes/magboots
+ magboots_type = /obj/item/clothing/shoes/magboots
req_access = list(access_engine_equip)
/obj/machinery/suit_storage_unit/engine/secure
@@ -74,7 +76,7 @@
suit_type = /obj/item/clothing/suit/space/hardsuit/elite
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/elite
mask_type = /obj/item/clothing/mask/gas
- storage_type = /obj/item/clothing/shoes/magboots/advance
+ magboots_type = /obj/item/clothing/shoes/magboots/advance
req_access = list(access_ce)
/obj/machinery/suit_storage_unit/ce/secure
@@ -85,7 +87,7 @@
suit_type = /obj/item/clothing/suit/space/hardsuit/security
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/security
mask_type = /obj/item/clothing/mask/gas/sechailer
- storage_type = /obj/item/clothing/shoes/magboots
+ magboots_type = /obj/item/clothing/shoes/magboots
req_access = list(access_security)
/obj/machinery/suit_storage_unit/security/secure
@@ -99,7 +101,7 @@
suit_type = /obj/item/clothing/suit/space/hardsuit/atmos
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/atmos
mask_type = /obj/item/clothing/mask/gas
- storage_type = /obj/item/clothing/shoes/magboots
+ magboots_type = /obj/item/clothing/shoes/magboots
req_access = list(access_atmospherics)
/obj/machinery/suit_storage_unit/atmos/secure
@@ -115,6 +117,12 @@
/obj/machinery/suit_storage_unit/mining/secure
secure = TRUE
+/obj/machinery/suit_storage_unit/lavaland
+ name = "mining suit storage unit"
+ suit_type = /obj/item/clothing/suit/hooded/explorer
+ mask_type = /obj/item/clothing/mask/gas/explorer
+ req_access = list(access_mining_station)
+
/obj/machinery/suit_storage_unit/cmo
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/medical
@@ -128,7 +136,7 @@
/obj/machinery/suit_storage_unit/cmo/secure/sec_storage
name = "medical suit storage unit"
mask_type = /obj/item/clothing/mask/gas
- storage_type = /obj/item/clothing/shoes/magboots
+ magboots_type = /obj/item/clothing/shoes/magboots
/obj/machinery/suit_storage_unit/clown
name = "clown suit storage unit"
@@ -150,13 +158,13 @@
/obj/machinery/suit_storage_unit/syndicate
name = "syndicate suit storage unit"
- suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
- helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/syndi
- mask_type = /obj/item/clothing/mask/gas/syndicate
- storage_type = /obj/item/tank/jetpack/oxygen/harness
+ suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
+ helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/syndi
+ mask_type = /obj/item/clothing/mask/gas/syndicate
+ magboots_type = /obj/item/clothing/shoes/magboots/syndie
+ storage_type = /obj/item/tank/jetpack/oxygen/harness
req_access = list(access_syndicate)
safeties = FALSE //in a syndicate base, everything can be used as a murder weapon at a moment's notice.
- uv_super = TRUE //so efficient
/obj/machinery/suit_storage_unit/syndicate/secure
secure = TRUE
@@ -209,6 +217,11 @@
/obj/machinery/suit_storage_unit/telecoms/secure
secure = TRUE
+/obj/machinery/suit_storage_unit/radsuit
+ name = "radiation suit storage unit"
+ suit_type = /obj/item/clothing/suit/radiation
+ helmet_type = /obj/item/clothing/head/radiation
+
//copied from /obj/effect/nasavoidsuitspawner
/obj/machinery/suit_storage_unit/telecoms/Initialize()
switch(pick(list("red", "green", "ntblue", "purple", "yellow", "ltblue")))
@@ -245,6 +258,8 @@
helmet = new helmet_type(src)
if(mask_type)
mask = new mask_type(src)
+ if(magboots_type)
+ magboots = new magboots_type(src)
if(storage_type)
storage = new storage_type(src)
update_icon()
@@ -257,6 +272,7 @@
QDEL_NULL(suit)
QDEL_NULL(helmet)
QDEL_NULL(mask)
+ QDEL_NULL(magboots)
QDEL_NULL(storage)
QDEL_NULL(wires)
return ..()
@@ -324,7 +340,10 @@
if(istype(I, /obj/item/clothing/mask) && !mask)
mask = I
. = TRUE
- if((istype(I, /obj/item/tank) || istype(I, /obj/item/clothing/shoes/magboots)) && !storage)
+ if(istype(I, /obj/item/clothing/shoes/magboots) && !magboots)
+ magboots = I
+ . = TRUE
+ if((istype(I, /obj/item/tank)) && !storage)
storage = I
. = TRUE
if(.)
@@ -410,6 +429,8 @@
qdel(suit) // Delete everything but the occupant.
mask = null
qdel(mask)
+ magboots = null
+ qdel(magboots)
storage = null
qdel(storage)
else
@@ -427,8 +448,8 @@
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
- if(electrocute_mob(user, get_area(src), src, 1))
- return 1
+ if(electrocute_mob(user, src, src, 1, TRUE))
+ return TRUE
/obj/machinery/suit_storage_unit/relaymove(mob/user)
if(locked)
@@ -544,7 +565,10 @@
dat+= text("Breathmask storage compartment: [] ",(mask ? mask.name : "No breathmask detected.") )
if(mask && state_open)
dat+="Dispense mask "
- dat+= text("Tank, Magboots storage compartment: [] ",(storage ? storage.name : "No storage item detected.") )
+ dat+= text("Magboots storage compartment: [] ",(magboots ? magboots.name : "No magboots detected.") )
+ if(magboots && state_open)
+ dat+="Dispense magboots "
+ dat+= text("Tank storage compartment: [] ",(storage ? storage.name : "No storage item detected.") )
if(storage && state_open)
dat+="Dispense storage item "
if(occupant)
@@ -604,6 +628,10 @@
dispense_mask(usr)
updateUsrDialog()
update_icon()
+ if(href_list["dispense_magboots"])
+ dispense_magboots(usr)
+ updateUsrDialog()
+ update_icon()
if(href_list["dispense_storage"])
dispense_storage(usr)
updateUsrDialog()
@@ -671,6 +699,13 @@
else
mask.forceMove(loc)
mask = null
+
+/obj/machinery/suit_storage_unit/proc/dispense_magboots(mob/user as mob)
+ if(!magboots)
+ return
+ else
+ magboots.forceMove(loc)
+ magboots = null
/obj/machinery/suit_storage_unit/proc/dispense_storage(mob/user as mob)
if(!storage)
diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm
index 304dc7dc639..1a63371915b 100644
--- a/code/game/machinery/syndicatebeacon.dm
+++ b/code/game/machinery/syndicatebeacon.dm
@@ -57,8 +57,8 @@
return
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/N = M
- ticker.mode.equip_traitor(N)
- ticker.mode.traitors += N.mind
+ SSticker.mode.equip_traitor(N)
+ SSticker.mode.traitors += N.mind
N.mind.special_role = SPECIAL_ROLE_TRAITOR
var/objective = "Free Objective"
switch(rand(1,100))
@@ -188,11 +188,11 @@
/obj/machinery/power/singularity_beacon/process()
if(!active)
return PROCESS_KILL
+
+ if(surplus() >= 1500)
+ add_load(1500)
else
- if(surplus() > 1500)
- draw_power(1500)
- else
- Deactivate()
+ Deactivate()
/obj/machinery/power/singularity_beacon/syndicate
icontype = "beaconsynd"
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index f02b8411e38..bc2af073fc6 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -39,7 +39,7 @@
/obj/machinery/syndicatebomb/process()
if(!active)
- GLOB.fast_processing -= src
+ STOP_PROCESSING(SSfastprocess, src)
detonation_timer = null
next_beep = null
countdown.stop()
@@ -73,7 +73,7 @@
if(defused && payload in src)
payload.defuse()
countdown.stop()
- GLOB.fast_processing -= src
+ STOP_PROCESSING(SSfastprocess, src)
/obj/machinery/syndicatebomb/New()
wires = new(src)
@@ -86,7 +86,7 @@
/obj/machinery/syndicatebomb/Destroy()
QDEL_NULL(wires)
QDEL_NULL(countdown)
- GLOB.fast_processing -= src
+ STOP_PROCESSING(SSfastprocess, src)
return ..()
/obj/machinery/syndicatebomb/examine(mob/user)
@@ -205,7 +205,7 @@
/obj/machinery/syndicatebomb/proc/activate()
active = TRUE
- GLOB.fast_processing += src
+ START_PROCESSING(SSfastprocess, src)
countdown.start()
next_beep = world.time + 10
detonation_timer = world.time + (timer_set * 10)
@@ -275,6 +275,16 @@
desc = "Do not taunt. Warranty invalid if exposed to high temperature. Not suitable for agents under 3 years of age."
payload = /obj/item/bombcore/large
can_unanchor = FALSE
+ var/explosive_wall_group = EXPLOSIVE_WALL_GROUP_SYNDICATE_BASE // If set, this bomb will also cause explosive walls in the same group to explode
+
+/obj/machinery/syndicatebomb/self_destruct/try_detonate(ignore_active = FALSE)
+ . = ..()
+ if(. && explosive_wall_group)
+ for(var/wall in GLOB.explosive_walls)
+ var/turf/simulated/wall/mineral/plastitanium/explosive/E = wall
+ if(E.explosive_wall_group == explosive_wall_group)
+ E.self_destruct()
+ sleep(5)
///Bomb Cores///
@@ -292,6 +302,7 @@
var/range_medium = 9
var/range_light = 17
var/range_flame = 17
+ var/admin_log = TRUE
/obj/item/bombcore/ex_act(severity) //Little boom can chain a big boom
detonate()
@@ -305,7 +316,7 @@
if(adminlog)
message_admins(adminlog)
log_game(adminlog)
- explosion(get_turf(src), range_heavy, range_medium, range_light, flame_range = range_flame)
+ explosion(get_turf(src), range_heavy, range_medium, range_light, flame_range = range_flame, adminlog = admin_log)
if(loc && istype(loc, /obj/machinery/syndicatebomb))
qdel(loc)
qdel(src)
@@ -396,6 +407,9 @@
range_light = 20
range_flame = 20
+/obj/item/bombcore/large/explosive_wall
+ admin_log = FALSE
+
/obj/item/bombcore/large/underwall
layer = ABOVE_OPEN_TURF_LAYER
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index 8e34e2e19bc..8cd285c994a 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -140,7 +140,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/datum/radio_frequency/connection = signal.data["connection"]
- if(connection.frequency in ANTAG_FREQS) // if antag broadcast, just
+ if(connection.frequency in SSradio.ANTAG_FREQS) // if antag broadcast, just
Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
@@ -162,13 +162,13 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/proc/Is_Bad_Connection(old_freq, new_freq) //Makes sure players cant read radios of a higher level than they are
var/old_type = CREW_RADIO_TYPE
var/new_type = CREW_RADIO_TYPE
- for(var/antag_freq in ANTAG_FREQS)
+ for(var/antag_freq in SSradio.ANTAG_FREQS)
if(old_freq == antag_freq)
old_type = SYNDICATE_RADIO_TYPE
if(new_freq == antag_freq)
new_type = SYNDICATE_RADIO_TYPE
- for(var/cent_freq in CENT_FREQS)
+ for(var/cent_freq in SSradio.CENT_FREQS)
if(old_freq == cent_freq)
old_type = CENTCOMM_RADIO_TYPE
if(new_freq == cent_freq)
@@ -249,7 +249,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
if(connection.frequency != display_freq)
bad_connection = Is_Bad_Connection(connection.frequency, display_freq)
- new_connection = radio_controller.return_frequency(display_freq)
+ new_connection = SSradio.return_frequency(display_freq)
var/list/obj/item/radio/radios = list()
@@ -276,8 +276,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Broadcast to antag radios! ---
else if(data == 3)
- for(var/antag_freq in ANTAG_FREQS)
- var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(antag_freq)
+ for(var/antag_freq in SSradio.ANTAG_FREQS)
+ var/datum/radio_frequency/antag_connection = SSradio.return_frequency(antag_freq)
for(var/obj/item/radio/R in antag_connection.devices["[RADIO_CHAT]"])
if(R.receive_range(antag_freq, level) > -1)
radios += R
@@ -356,7 +356,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/part_b_extra = ""
if(data == 3) // intercepted radio message
part_b_extra = " (Intercepted)"
- var/part_a = "\[[freq_text]\][part_b_extra]" // goes in the actual output
+ var/part_a = "\[[freq_text]\][part_b_extra]" // goes in the actual output
// --- Some more pre-message formatting ---
var/part_b = "" // Tweaked for security headsets -- TLE
@@ -452,7 +452,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
H = new
M = H
- var/datum/radio_frequency/connection = radio_controller.return_frequency(frequency)
+ var/datum/radio_frequency/connection = SSradio.return_frequency(frequency)
var/display_freq = connection.frequency
@@ -485,8 +485,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Broadcast to antag radios! ---
else if(data == 3)
- for(var/freq in ANTAG_FREQS)
- var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(freq)
+ for(var/freq in SSradio.ANTAG_FREQS)
+ var/datum/radio_frequency/antag_connection = SSradio.return_frequency(freq)
for(var/obj/item/radio/R in antag_connection.devices["[RADIO_CHAT]"])
var/turf/position = get_turf(R)
// TODO: Make the radio system cooperate with the space manager
@@ -545,7 +545,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
if(length(heard_normal) || length(heard_garbled) || length(heard_gibberish))
/* --- Some miscellaneous variables to format the string output --- */
- var/part_a = "" // goes in the actual output
+ var/part_a = "" // goes in the actual output
var/freq_text = get_frequency_name(display_freq)
// --- Some more pre-message formatting ---
diff --git a/code/game/machinery/telecomms/ntsl2.dm b/code/game/machinery/telecomms/ntsl2.dm
index f01f173ebb3..a5c4f3f1464 100644
--- a/code/game/machinery/telecomms/ntsl2.dm
+++ b/code/game/machinery/telecomms/ntsl2.dm
@@ -9,110 +9,111 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
* as well as allowing users to save and load configurations.
*/
/datum/nttc_configuration
+ var/regex/word_blacklist = new("( [ckey] attempted to upload an NTTC configuration containing JS abusable tags!")
+ log_admin("EXPLOIT WARNING: [ckey] attempted to upload an NTTC configuration containing JS abusable tags")
+ return FALSE
var/list/var_list = json_decode(text)
for(var/variable in var_list)
if(variable in to_serialize) // Don't just accept any random vars jesus christ!
@@ -236,6 +241,7 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
variable_value = nttc_sanitize(variable_value, sanitize_method)
if(variable_value != null)
vars[variable] = variable_value
+ return TRUE
// Sanitizing user input. Don't blindly trust the JSON.
/datum/nttc_configuration/proc/nttc_sanitize(variable, sanitize_method)
@@ -245,7 +251,8 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
switch(sanitize_method)
if("bool")
return variable ? TRUE : FALSE
- if("table", "array")
+ // if("table", "array")
+ if("array")
if(!islist(variable))
return list()
// Insert html filtering for the regexes here if you're boring
@@ -274,10 +281,10 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
// All job and coloring shit
if(toggle_job_color || toggle_name_color)
var/job = signal.data["job"]
- job_color = all_jobs[job]
+ job_class = all_jobs[job]
if(toggle_name_color)
- var/new_name = "" + signal.data["name"] + ""
+ var/new_name = "" + signal.data["name"] + ""
signal.data["name"] = new_name
signal.data["realname"] = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on
@@ -289,13 +296,13 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
if(toggle_job_color)
switch(job_indicator_type)
if(JOB_STYLE_1)
- new_name = signal.data["name"] + " ([job]) "
+ new_name = signal.data["name"] + " ([job]) "
if(JOB_STYLE_2)
- new_name = signal.data["name"] + " - [job] "
+ new_name = signal.data["name"] + " - [job] "
if(JOB_STYLE_3)
- new_name = "\[[job]\] " + signal.data["name"] + " "
+ new_name = "\[[job]\] " + signal.data["name"] + " "
if(JOB_STYLE_4)
- new_name = "([job]) " + signal.data["name"] + " "
+ new_name = "([job]) " + signal.data["name"] + " "
else
switch(job_indicator_type)
if(JOB_STYLE_1)
@@ -350,14 +357,14 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
S.speaking = GLOB.all_languages[setting_language]
// Regex replacements
- if(islist(regex) && regex.len > 0)
- for(var/datum/multilingual_say_piece/S in message_pieces)
- var/new_message = S.message
- for(var/reg in regex)
- var/replacePattern = pencode_to_html(regex[reg])
- var/regex/start = regex("[reg]", "gi")
- new_message = start.Replace(new_message, replacePattern)
- S.message = new_message
+ // if(islist(regex) && regex.len > 0)
+ // for(var/datum/multilingual_say_piece/S in message_pieces)
+ // var/new_message = S.message
+ // for(var/reg in regex)
+ // var/replacePattern = pencode_to_html(regex[reg])
+ // var/regex/start = regex("[reg]", "gi")
+ // new_message = start.Replace(new_message, replacePattern)
+ // S.message = new_message
// Make sure the message is valid after we tinkered with it, otherwise reject it
if(signal.data["message"] == "" || !signal.data["message"])
@@ -398,36 +405,41 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
log_action(user, new_language == "--DISABLE--" ? "disabled NTTC language conversion" : "set NTTC language conversion to [new_language]", TRUE)
// Tables
- if(href_list["create_row"])
- if(href_list["table"] && href_list["table"] in tables)
- if(requires_unlock[href_list["table"]] && !source.unlocked)
- return
- var/new_key = input(user, "Provide a key for the new row.", "New Row") as text|null
- if(!new_key)
- return
- var/new_value = input(user, "Provide a new value for the key [new_key]", "New Row") as text|null
- if(new_value == null)
- return
- var/list/table = vars[href_list["table"]]
- table[new_key] = new_value
- to_chat(user, "Added row [new_key] -> [new_value].")
- log_action(user, "updated [href_list["table"]] - new row [new_key] -> [new_value]")
+ // if(href_list["create_row"])
+ // if(href_list["table"] && href_list["table"] in tables)
+ // if(requires_unlock[href_list["table"]] && !source.unlocked)
+ // return
+ // var/new_key = clean_input(user, "Provide a key for the new row.", "New Row")
+ // if(!new_key)
+ // return
+ // var/new_value = clean_input(user, "Provide a new value for the key [new_key]", "New Row")
+ // if(new_value == null)
+ // return
+ // if(word_blacklist.Find(new_value)) //uh oh, they tried to be naughty
+ // message_admins("EXPLOIT WARNING: [user.ckey] attempted to add a NTTC regex row containing JS abusable tags!")
+ // log_admin("EXPLOIT WARNING: [user.ckey] attempted to add a NTTC regex row containing JS abusable tags")
+ // to_chat(user, "ERROR: Regex contained bad strings. Upload cancelled.")
+ // return
+ // var/list/table = vars[href_list["table"]]
+ // table[new_key] = new_value
+ // to_chat(user, "Added row [new_key] -> [new_value].")
+ // log_action(user, "updated [href_list["table"]] - new row [new_key] -> [new_value]")
- if(href_list["delete_row"])
- if(href_list["table"] && href_list["table"] in tables)
- if(requires_unlock[href_list["table"]] && !source.unlocked)
- return
- var/list/table = vars[href_list["table"]]
- table.Remove(href_list["delete_row"])
- to_chat(user, "Removed row [href_list["delete_row"]] from [href_list["table"]]")
- log_action(user, "updated [href_list["table"]] - removed row [href_list["delete_row"]]")
+ // if(href_list["delete_row"])
+ // if(href_list["table"] && href_list["table"] in tables)
+ // if(requires_unlock[href_list["table"]] && !source.unlocked)
+ // return
+ // var/list/table = vars[href_list["table"]]
+ // table.Remove(href_list["delete_row"])
+ // to_chat(user, "Removed row [href_list["delete_row"]] from [href_list["table"]]")
+ // log_action(user, "updated [href_list["table"]] - removed row [href_list["delete_row"]]")
// Arrays
if(href_list["create_item"])
if(href_list["array"] && href_list["array"] in arrays)
if(requires_unlock[href_list["array"]] && !source.unlocked)
return
- var/new_value = input(user, "Provide a value for the new index.", "New Index") as text|null
+ var/new_value = clean_input(user, "Provide a value for the new index.", "New Index")
if(new_value == null)
return
var/list/array = vars[href_list["array"]]
@@ -450,8 +462,8 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
if(href_list["load_config"])
var/json = input(user, "Provide configuration JSON below.", "Load Config", nttc_serialize()) as message
- nttc_deserialize(json, source)
- log_action(user, "has uploaded a NTTC JSON configuration: [ADMIN_SHOWDETAILS("Show", json)]", TRUE)
+ if(nttc_deserialize(json, source, user.ckey))
+ log_action(user, "has uploaded a NTTC JSON configuration: [ADMIN_SHOWDETAILS("Show", json)]", TRUE)
user << output(list2params(list(nttc_serialize())), "[window_id].browser:updateConfig")
@@ -470,7 +482,7 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
"tab_hack.html" = 'html/nttc/dist/tab_hack.html',
"tab_filtering.html" = 'html/nttc/dist/tab_filtering.html',
"tab_firewall.html" = 'html/nttc/dist/tab_firewall.html',
- "tab_regex.html" = 'html/nttc/dist/tab_regex.html',
+ // "tab_regex.html" = 'html/nttc/dist/tab_regex.html',
"uiTitleFluff.png" = 'html/nttc/dist/uiTitleFluff.png'
)
diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm
index 8014a149cf4..54bd17920bd 100644
--- a/code/game/machinery/transformer.dm
+++ b/code/game/machinery/transformer.dm
@@ -166,10 +166,10 @@
name = "Automatic X-Ray 5000"
desc = "A large metalic machine with an entrance and an exit. A sign on the side reads, 'backpack go in, backpack come out', 'human go in, irradiated human come out'."
-/obj/machinery/transformer/xray/New()
+/obj/machinery/transformer/xray/Initialize(mapload)
+ . = ..()
// On us
new /obj/machinery/conveyor/auto(loc, EAST)
- addAtProcessing()
/obj/machinery/transformer/xray/conveyor/New()
..()
diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm
index 2a46eb40eba..af2a1a8d9c0 100644
--- a/code/game/machinery/turret_control.dm
+++ b/code/game/machinery/turret_control.dm
@@ -142,7 +142,7 @@
/obj/machinery/turretid/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300)
+ ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 350)
ui.open()
ui.set_auto_update(1)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index fb780e5d550..cf7937474c8 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -38,6 +38,8 @@
layer = 2.9
anchored = 1
density = 1
+ max_integrity = 300
+ integrity_failure = 100
armor = list(melee = 20, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
var/icon_vend //Icon_state when vending
var/icon_deny //Icon_state when denying access
@@ -96,30 +98,27 @@
var/item_slot = FALSE
var/obj/item/inserted_item = null
-/obj/machinery/vending/New()
- ..()
+/obj/machinery/vending/Initialize(mapload)
+ . = ..()
wires = new(src)
- spawn(50)
- if(product_slogans)
- slogan_list += splittext(product_slogans, ";")
+ if(product_slogans)
+ slogan_list += splittext(product_slogans, ";")
- // So not all machines speak at the exact same time.
- // The first time this machine says something will be at slogantime + this random value,
- // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated.
- last_slogan = world.time + rand(0, slogan_delay)
+ // So not all machines speak at the exact same time.
+ // The first time this machine says something will be at slogantime + this random value,
+ // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated.
+ last_slogan = world.time + rand(0, slogan_delay)
- if(product_ads)
- ads_list += splittext(product_ads, ";")
+ if(product_ads)
+ ads_list += splittext(product_ads, ";")
- build_inventory()
- power_change()
-
- return
-
- return
+ build_inventory()
+ power_change()
/obj/machinery/vending/Destroy()
- eject_item()
+ QDEL_NULL(wires)
+ QDEL_NULL(coin)
+ QDEL_NULL(inserted_item)
return ..()
/**
@@ -148,34 +147,31 @@
product_records.Add(product)
-/obj/machinery/vending/Destroy()
- QDEL_NULL(wires)
- QDEL_NULL(coin)
- return ..()
-
-/obj/machinery/vending/ex_act(severity)
+/obj/machinery/vending/ex_act(severity) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable
switch(severity)
- if(1.0)
+ if(1)
+ obj_integrity = 0
qdel(src)
- return
- if(2.0)
- if(prob(50))
- qdel(src)
- return
- if(3.0)
- if(prob(25))
- malfunction()
+ if(2)
+ take_damage(rand(100, 250), BRUTE, "bomb", 0)
+ if(3)
+ take_damage(rand(10, 90), BRUTE, "bomb", 0)
/obj/machinery/vending/RefreshParts() //Better would be to make constructable child
if(component_parts)
for(var/obj/item/vending_refill/VR in component_parts)
refill_inventory(VR, product_records, usr)
-/obj/machinery/vending/blob_act()
- if(prob(75))
- malfunction()
- else
+/obj/machinery/vending/deconstruct(disassembled = TRUE)
+ eject_item()
+ if(!refill_canister) //the non constructable vendors drop metal instead of a machine frame.
+ new /obj/item/stack/sheet/metal(loc, 3)
qdel(src)
+ else
+ ..()
+
+/obj/machinery/vending/blob_act(obj/structure/blob/B) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable
+ take_damage(400, BRUTE, "melee", 0, get_dir(src, B))
/obj/machinery/vending/proc/refill_inventory(obj/item/vending_refill/refill, list/machine, mob/user)
var/total = 0
@@ -236,7 +232,7 @@
if(default_unfasten_wrench(user, I, time = 60))
return
- if(istype(I, /obj/item/screwdriver) && anchored)
+ if(isscrewdriver(I) && anchored)
playsound(loc, I.usesound, 50, 1)
panel_open = !panel_open
to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.")
@@ -247,9 +243,9 @@
return
if(panel_open)
- if(istype(I, /obj/item/multitool)||istype(I, /obj/item/wirecutters))
+ if(ismultitool(I) || iswirecutter(I))
return attack_hand(user)
- if(component_parts && istype(I, /obj/item/crowbar))
+ if(component_parts && iscrowbar(I))
var/datum/data/vending_product/machine = product_records
for(var/datum/data/vending_product/machine_content in machine)
while(machine_content.amount !=0)
@@ -259,15 +255,17 @@
if(!machine_content.amount)
break
default_deconstruction_crowbar(I)
- if(istype(I, /obj/item/coin) && premium.len > 0)
- user.drop_item()
- I.loc = src
+ return
+ if(istype(I, /obj/item/coin) && premium.len)
+ if(!user.drop_item())
+ return
+ I.forceMove(src)
coin = I
categories |= CAT_COIN
to_chat(user, "You insert the [I] into the [src]")
SSnanoui.update_uis(src)
return
- else if(istype(I, refill_canister) && refill_canister != null)
+ if(istype(I, refill_canister) && refill_canister != null)
if(stat & (BROKEN|NOPOWER))
to_chat(user, "It does nothing.")
else if(panel_open)
@@ -281,21 +279,18 @@
to_chat(user, "You loaded [transfered] items in \the [name].")
else
to_chat(user, "The [name] is fully stocked.")
- return;
else
to_chat(user, "You should probably unscrew the service panel first.")
- else if(item_slot_check(user, I))
+ return
+ if(item_slot_check(user, I))
insert_item(user, I)
return
- else
- return ..()
+ return ..()
//Override this proc to do per-machine checks on the inserted item, but remember to call the parent to handle these generic checks before your logic!
/obj/machinery/vending/proc/item_slot_check(mob/user, obj/item/I)
if(!item_slot)
return FALSE
- if(alert(user, "Do you want to attempt to insert [I]?", "","Yes", "No") == "No")
- return FALSE
if(inserted_item)
to_chat(user, "There is something already inserted!")
return FALSE
@@ -314,28 +309,32 @@
/obj/machinery/vending/proc/insert_item(mob/user, obj/item/I)
if(!item_slot || inserted_item)
return
- if(!user.canUnEquip(I))
+ if(!user.drop_item())
to_chat(user, "[I] is stuck to your hand, you can't seem to put it down!")
return
- user.unEquip(I)
inserted_item = I
I.forceMove(src)
to_chat(user, "You insert [I] into [src].")
SSnanoui.update_uis(src)
-/obj/machinery/vending/proc/eject_item()
+/obj/machinery/vending/proc/eject_item(mob/user)
if(!item_slot || !inserted_item)
return
- inserted_item.forceMove(get_turf(src))
+ var/put_on_turf = TRUE
+ if(user && iscarbon(user) && user.Adjacent(src))
+ if(user.put_in_hands(inserted_item))
+ put_on_turf = FALSE
+ if(put_on_turf)
+ var/turf/T = get_turf(src)
+ inserted_item.forceMove(T)
inserted_item = null
SSnanoui.update_uis(src)
/obj/machinery/vending/emag_act(user as mob)
- emagged = 1
+ emagged = TRUE
to_chat(user, "You short out the product lock on [src]")
- return
/**
* Receive payment with cashmoney.
@@ -511,7 +510,7 @@
categories &= ~CAT_COIN
if(href_list["remove_item"])
- eject_item()
+ eject_item(usr)
if(href_list["pay"])
if(currently_vending && vendor_account && !vendor_account.suspended)
@@ -593,7 +592,7 @@
return
if(coin.string_attached)
if(prob(50))
- to_chat(user, "You successfully pull the coin out before the [src] could swallow it.")
+ to_chat(user, "You successfully pull the coin out before [src] could swallow it.")
else
to_chat(user, "You weren't able to pull the coin out fast enough, the machine ate it, string and all.")
QDEL_NULL(coin)
@@ -605,25 +604,33 @@
R.amount--
if(((last_reply + (vend_delay + 200)) <= world.time) && vend_reply)
- spawn(0)
- speak(src.vend_reply)
- last_reply = world.time
+ speak(src.vend_reply)
+ last_reply = world.time
use_power(vend_power_usage) //actuators and stuff
if(icon_vend) //Show the vending animation if needed
- flick(icon_vend,src)
- spawn(vend_delay)
- do_vend(R)
- status_message = ""
- status_error = 0
- vend_ready = 1
- currently_vending = null
- SSnanoui.update_uis(src)
+ flick(icon_vend, src)
+ addtimer(CALLBACK(src, .proc/delayed_vend, R, user), vend_delay)
+
+/obj/machinery/vending/proc/delayed_vend(datum/data/vending_product/R, mob/user)
+ do_vend(R, user)
+ status_message = ""
+ status_error = 0
+ vend_ready = 1
+ currently_vending = null
+ SSnanoui.update_uis(src)
//override this proc to add handling for what to do with the vended product when you have a inserted item and remember to include a parent call for this generic handling
-/obj/machinery/vending/proc/do_vend(datum/data/vending_product/R)
+/obj/machinery/vending/proc/do_vend(datum/data/vending_product/R, mob/user)
if(!item_slot || !inserted_item)
- new R.product_path(get_turf(src))
+ var/put_on_turf = TRUE
+ var/obj/vended = new R.product_path()
+ if(user && iscarbon(user) && user.Adjacent(src))
+ if(user.put_in_hands(vended))
+ put_on_turf = FALSE
+ if(put_on_turf)
+ var/turf/T = get_turf(src)
+ vended.forceMove(T)
return TRUE
return FALSE
@@ -638,7 +645,7 @@
qdel(vended)
*/
-/obj/machinery/vending/proc/stock(var/datum/data/vending_product/R, var/mob/user)
+/obj/machinery/vending/proc/stock(datum/data/vending_product/R, mob/user)
if(panel_open)
to_chat(user, "You stock the [src] with \a [R.product_name]")
R.amount++
@@ -664,8 +671,6 @@
if(shoot_inventory && prob(shoot_chance))
throw_item()
- return
-
/obj/machinery/vending/proc/speak(message)
if(stat & NOPOWER)
return
@@ -686,28 +691,38 @@
icon_state = "[initial(icon_state)]-off"
stat |= NOPOWER
-//Oh no we're malfunctioning! Dump out some product and break.
-/obj/machinery/vending/proc/malfunction()
- for(var/datum/data/vending_product/R in product_records)
- if(R.amount <= 0) //Try to use a record that actually has something to dump.
- continue
- var/dump_path = R.product_path
- if(!dump_path)
- continue
+/obj/machinery/vending/obj_break(damage_flag)
+ if(!(stat & BROKEN))
+ stat |= BROKEN
+ icon_state = "[initial(icon_state)]-broken"
- while(R.amount>0)
- new dump_path(loc)
- R.amount--
- break
+ var/dump_amount = 0
+ var/found_anything = TRUE
+ while (found_anything)
+ found_anything = FALSE
+ for(var/record in shuffle(product_records))
+ var/datum/data/vending_product/R = record
+ if(R.amount <= 0) //Try to use a record that actually has something to dump.
+ continue
+ var/dump_path = R.product_path
+ if(!dump_path)
+ continue
+ R.amount--
+ // busting open a vendor will destroy some of the contents
+ if(found_anything && prob(80))
+ continue
- stat |= BROKEN
- icon_state = "[initial(icon_state)]-broken"
- return
+ var/obj/O = new dump_path(loc)
+ step(O, pick(alldirs))
+ found_anything = TRUE
+ dump_amount++
+ if(dump_amount >= 16)
+ return
//Somebody cut an important wire and now we're following a new definition of "pitch."
/obj/machinery/vending/proc/throw_item()
var/obj/throw_item = null
- var/mob/living/target = locate() in view(7,src)
+ var/mob/living/target = locate() in view(7, src)
if(!target)
return 0
@@ -722,12 +737,12 @@
throw_item = new dump_path(loc)
break
if(!throw_item)
- return 0
- spawn(0)
- throw_item.throw_at(target, 16, 3, src)
+ return
+ throw_item.throw_at(target, 16, 3)
visible_message("[src] launches [throw_item.name] at [target.name]!")
- return 1
+/obj/machinery/vending/onTransitZ()
+ return
/*
* Vending machine types
*/
@@ -791,6 +806,9 @@
product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!"
refill_canister = /obj/item/vending_refill/boozeomat
+/obj/machinery/vending/boozeomat/syndicate_access
+ req_access = list(access_syndicate)
+
/obj/machinery/vending/assist
products = list( /obj/item/assembly/prox_sensor = 5,/obj/item/assembly/igniter = 3,/obj/item/assembly/signaler = 4,
/obj/item/wirecutters = 1, /obj/item/cartridge/signal = 4)
@@ -840,28 +858,39 @@
component_parts += new /obj/item/vending_refill/coffee(0)
/obj/machinery/vending/coffee/item_slot_check(mob/user, obj/item/I)
+ if(!(istype(I, /obj/item/reagent_containers/glass) || istype(I, /obj/item/reagent_containers/food/drinks)))
+ return FALSE
if(!..())
return FALSE
- if(!(istype(I, /obj/item/reagent_containers/glass) || istype(I, /obj/item/reagent_containers/food/drinks)))
- to_chat(user, "[I] is not compatible with this machine.")
- return FALSE
if(!I.is_open_container())
- to_chat(user, "You need to open [I] before you insert it.")
+ to_chat(user, "You need to open [I] before inserting it.")
return FALSE
return TRUE
-/obj/machinery/vending/coffee/do_vend(datum/data/vending_product/R)
+/obj/machinery/vending/coffee/do_vend(datum/data/vending_product/R, mob/user)
if(..())
return
var/obj/item/reagent_containers/food/drinks/vended = new R.product_path()
if(istype(vended, /obj/item/reagent_containers/food/drinks/mug))
- vended.forceMove(get_turf(src))
+ var/put_on_turf = TRUE
+ if(user && iscarbon(user) && user.Adjacent(src))
+ if(user.put_in_hands(vended))
+ put_on_turf = FALSE
+ if(put_on_turf)
+ var/turf/T = get_turf(src)
+ vended.forceMove(T)
return
vended.reagents.trans_to(inserted_item, vended.reagents.total_volume)
if(vended.reagents.total_volume)
- vended.forceMove(get_turf(src))
+ var/put_on_turf = TRUE
+ if(user && iscarbon(user) && user.Adjacent(src))
+ if(user.put_in_hands(vended))
+ put_on_turf = FALSE
+ if(put_on_turf)
+ var/turf/T = get_turf(src)
+ vended.forceMove(T)
else
qdel(vended)
@@ -982,6 +1011,33 @@
contraband = list(/obj/item/clothing/under/patriotsuit = 1,/obj/item/bedsheet/patriot = 3)
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0)
+
+/obj/machinery/vending/toyliberationstation
+ name = "\improper Syndicate Donksoft Toy Vendor"
+ desc = "An ages 8 and up approved vendor that dispenses toys. If you were to find the right wires, you can unlock the adult mode setting!"
+ icon_state = "syndi"
+ product_slogans = "Get your cool toys today!;Trigger a valid hunter today!;Quality toy weapons for cheap prices!;Give them to HoPs for all access!;Give them to HoS to get permabrigged!"
+ product_ads = "Feel robust with your toys!;Express your inner child today!;Toy weapons don't kill people, but valid hunters do!;Who needs responsibilities when you have toy weapons?;Make your next murder FUN!"
+ vend_reply = "Come back for more!"
+ products = list(/obj/item/gun/projectile/automatic/toy = 10,
+ /obj/item/gun/projectile/automatic/toy/pistol= 10,
+ /obj/item/gun/projectile/shotgun/toy = 10,
+ /obj/item/toy/sword = 10,
+ /obj/item/ammo_box/foambox = 20,
+ /obj/item/toy/foamblade = 10,
+ /obj/item/toy/syndicateballoon = 10,
+ /obj/item/clothing/suit/syndicatefake = 5,
+ /obj/item/clothing/head/syndicatefake = 5) //OPS IN DORMS oh wait it's just an assistant
+ contraband = list(/obj/item/gun/projectile/shotgun/toy/crossbow= 10, //Congrats, you unlocked the +18 setting!
+ /obj/item/gun/projectile/automatic/c20r/toy/riot = 10,
+ /obj/item/gun/projectile/automatic/l6_saw/toy/riot = 10,
+ /obj/item/gun/projectile/automatic/sniper_rifle/toy = 10,
+ /obj/item/ammo_box/foambox/riot = 20,
+ /obj/item/toy/katana = 10,
+ /obj/item/twohanded/dualsaber/toy = 5,
+ /obj/item/toy/cards/deck/syndicate = 10) //Gambling and it hurts, making it a +18 item
+ armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0)
+
/obj/machinery/vending/cigarette
name = "cigarette machine"
desc = "If you want to get cancer, might as well do it in style."
@@ -998,6 +1054,37 @@
/obj/machinery/vending/cigarette/free
prices = list()
+/obj/machinery/vending/cigarette/syndicate
+ products = list(/obj/item/storage/fancy/cigarettes/cigpack_syndicate = 7,
+ /obj/item/storage/fancy/cigarettes/cigpack_uplift = 3,
+ /obj/item/storage/fancy/cigarettes/cigpack_robust = 2,
+ /obj/item/storage/fancy/cigarettes/cigpack_carp = 3,
+ /obj/item/storage/fancy/cigarettes/cigpack_midori = 1,
+ /obj/item/storage/box/matches = 10,
+ /obj/item/lighter/zippo = 4,
+ /obj/item/storage/fancy/rollingpapers = 5)
+
+/obj/machinery/vending/cigarette/syndicate/free
+ prices = list()
+
+/obj/machinery/vending/cigarette/beach //Used in the lavaland_biodome_beach.dmm ruin
+ name = "\improper ShadyCigs Ultra"
+ desc = "Now with extra premium products!"
+ product_ads = "Probably not bad for you!;Dope will get you through times of no money better than money will get you through times of no dope!;It's good for you!"
+ product_slogans = "Turn on, tune in, drop out!;Better living through chemistry!;Toke!;Don't forget to keep a smile on your lips and a song in your heart!"
+ products = list(/obj/item/storage/fancy/cigarettes = 5,
+ /obj/item/storage/fancy/cigarettes/cigpack_uplift = 3,
+ /obj/item/storage/fancy/cigarettes/cigpack_robust = 3,
+ /obj/item/storage/fancy/cigarettes/cigpack_carp = 3,
+ /obj/item/storage/fancy/cigarettes/cigpack_midori = 3,
+ /obj/item/storage/box/matches = 10,
+ /obj/item/lighter/random = 4,
+ /obj/item/storage/fancy/rollingpapers = 5)
+ premium = list(/obj/item/clothing/mask/cigarette/cigar/havana = 2,
+ /obj/item/storage/fancy/cigarettes/cigpack_robustgold = 1,
+ /obj/item/lighter/zippo = 3)
+ prices = list()
+
/obj/machinery/vending/cigarette/New()
..()
component_parts = list()
@@ -1015,23 +1102,29 @@
icon_deny = "med-deny"
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!"
req_access_txt = "5"
- products = list(/obj/item/reagent_containers/glass/bottle/charcoal = 4,/obj/item/reagent_containers/glass/bottle/morphine = 4,/obj/item/reagent_containers/glass/bottle/ether = 4,/obj/item/reagent_containers/glass/bottle/epinephrine = 4,
- /obj/item/reagent_containers/glass/bottle/toxin = 4,/obj/item/reagent_containers/syringe/antiviral = 6,/obj/item/reagent_containers/syringe/insulin = 4,
- /obj/item/reagent_containers/syringe = 12,/obj/item/healthanalyzer = 5,/obj/item/healthupgrade = 5,/obj/item/reagent_containers/glass/beaker = 4, /obj/item/reagent_containers/hypospray/safety = 2,
- /obj/item/reagent_containers/dropper = 2,/obj/item/stack/medical/bruise_pack/advanced = 3, /obj/item/stack/medical/ointment/advanced = 3,
- /obj/item/stack/medical/bruise_pack = 3,/obj/item/stack/medical/splint = 4, /obj/item/sensor_device = 2, /obj/item/reagent_containers/hypospray/autoinjector = 4,
- /obj/item/pinpointer/crew = 2)
- contraband = list(/obj/item/reagent_containers/glass/bottle/pancuronium = 1,/obj/item/reagent_containers/glass/bottle/sulfonal = 1)
+ products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/food/pill/patch/styptic = 10, /obj/item/reagent_containers/food/pill/patch/silver_sulf = 10,
+ /obj/item/reagent_containers/glass/bottle/charcoal = 4, /obj/item/reagent_containers/glass/bottle/epinephrine = 4, /obj/item/reagent_containers/glass/bottle/diphenhydramine = 4,
+ /obj/item/reagent_containers/glass/bottle/salicylic = 4, /obj/item/reagent_containers/glass/bottle/potassium_iodide =3, /obj/item/reagent_containers/glass/bottle/saline = 5,
+ /obj/item/reagent_containers/glass/bottle/morphine = 4, /obj/item/reagent_containers/glass/bottle/ether = 4, /obj/item/reagent_containers/glass/bottle/atropine = 3,
+ /obj/item/reagent_containers/glass/bottle/oculine = 2, /obj/item/reagent_containers/glass/bottle/toxin = 4, /obj/item/reagent_containers/syringe/antiviral = 6,
+ /obj/item/reagent_containers/syringe/insulin = 6, /obj/item/reagent_containers/syringe/calomel = 10, /obj/item/reagent_containers/hypospray/autoinjector = 5, /obj/item/reagent_containers/food/pill/salbutamol = 10,
+ /obj/item/reagent_containers/food/pill/mannitol = 10, /obj/item/reagent_containers/food/pill/mutadone = 5, /obj/item/stack/medical/bruise_pack/advanced = 4, /obj/item/stack/medical/ointment/advanced = 4, /obj/item/stack/medical/bruise_pack = 4,
+ /obj/item/stack/medical/splint = 4, /obj/item/reagent_containers/glass/beaker = 4, /obj/item/reagent_containers/dropper = 4, /obj/item/healthanalyzer = 4,
+ /obj/item/healthupgrade = 4, /obj/item/reagent_containers/hypospray/safety = 2, /obj/item/sensor_device = 2, /obj/item/pinpointer/crew = 2)
+ contraband = list(/obj/item/reagent_containers/glass/bottle/sulfonal = 1, /obj/item/reagent_containers/glass/bottle/pancuronium = 1)
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0)
+/obj/machinery/vending/medical/syndicate_access
+ name = "\improper SyndiMed Plus"
+ req_access = list(access_syndicate)
+
//This one's from bay12
/obj/machinery/vending/plasmaresearch
name = "\improper Toximate 3000"
desc = "All the fine parts you need in one vending machine!"
- products = list(/obj/item/clothing/under/rank/scientist = 6,/obj/item/clothing/suit/bio_suit = 6,/obj/item/clothing/head/bio_hood = 6,
- /obj/item/transfer_valve = 6,/obj/item/assembly/timer = 6,/obj/item/assembly/signaler = 6,
- /obj/item/assembly/prox_sensor = 6,/obj/item/assembly/igniter = 6)
- contraband = list(/obj/item/assembly/health = 3)
+ products = list(/obj/item/assembly/prox_sensor = 8, /obj/item/assembly/igniter = 8, /obj/item/assembly/signaler = 8,
+ /obj/item/wirecutters = 1, /obj/item/assembly/timer = 8)
+ contraband = list(/obj/item/flashlight = 5, /obj/item/assembly/voice = 3, /obj/item/assembly/health = 3, /obj/item/assembly/infra = 3)
/obj/machinery/vending/wallmed1
name = "\improper NanoMed"
@@ -1039,10 +1132,9 @@
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?"
icon_state = "wallmed"
icon_deny = "wallmed-deny"
- req_access_txt = "5"
- density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude
- products = list(/obj/item/stack/medical/bruise_pack = 2,/obj/item/stack/medical/ointment = 2,/obj/item/reagent_containers/hypospray/autoinjector = 4,/obj/item/healthanalyzer = 1)
- contraband = list(/obj/item/reagent_containers/syringe/charcoal = 4,/obj/item/reagent_containers/syringe/antiviral = 4,/obj/item/reagent_containers/food/pill/tox = 1)
+ density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
+ products = list(/obj/item/stack/medical/bruise_pack = 2, /obj/item/stack/medical/ointment = 2, /obj/item/reagent_containers/hypospray/autoinjector = 4, /obj/item/healthanalyzer = 1)
+ contraband = list(/obj/item/reagent_containers/syringe/charcoal = 4, /obj/item/reagent_containers/syringe/antiviral = 4, /obj/item/reagent_containers/food/pill/tox = 1)
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0)
/obj/machinery/vending/wallmed2
@@ -1050,10 +1142,9 @@
desc = "Wall-mounted Medical Equipment dispenser."
icon_state = "wallmed"
icon_deny = "wallmed-deny"
- req_access_txt = "5"
- density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude
- products = list(/obj/item/reagent_containers/hypospray/autoinjector = 5,/obj/item/reagent_containers/syringe/charcoal = 3,/obj/item/stack/medical/bruise_pack = 3,
- /obj/item/stack/medical/ointment =3,/obj/item/healthanalyzer = 3)
+ density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
+ products = list(/obj/item/reagent_containers/hypospray/autoinjector = 5, /obj/item/reagent_containers/syringe/charcoal = 3, /obj/item/stack/medical/bruise_pack = 3,
+ /obj/item/stack/medical/ointment = 3, /obj/item/healthanalyzer = 3)
contraband = list(/obj/item/reagent_containers/food/pill/tox = 3)
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0)
@@ -1200,7 +1291,8 @@
/obj/item/clothing/head/cueball = 1,/obj/item/clothing/under/scratch = 1,
/obj/item/clothing/under/victdress = 1, /obj/item/clothing/under/victdress/red = 1, /obj/item/clothing/suit/victcoat = 1, /obj/item/clothing/suit/victcoat/red = 1,
/obj/item/clothing/under/victsuit = 1, /obj/item/clothing/under/victsuit/redblk = 1, /obj/item/clothing/under/victsuit/red = 1, /obj/item/clothing/suit/tailcoat = 1,
- /obj/item/clothing/suit/draculacoat = 1, /obj/item/clothing/head/zepelli = 1)
+ /obj/item/clothing/suit/draculacoat = 1, /obj/item/clothing/head/zepelli = 1,
+ /obj/item/clothing/under/redhawaiianshirt = 1, /obj/item/clothing/under/pinkhawaiianshirt = 1, /obj/item/clothing/under/bluehawaiianshirt = 1, /obj/item/clothing/under/orangehawaiianshirt = 1)
contraband = list(/obj/item/clothing/suit/judgerobe = 1,/obj/item/clothing/head/powdered_wig = 1,/obj/item/gun/magic/wand = 1, /obj/item/clothing/mask/balaclava=1, /obj/item/clothing/mask/horsehead = 2)
premium = list(/obj/item/clothing/suit/hgpirate = 1, /obj/item/clothing/head/hgpiratecap = 1, /obj/item/clothing/head/helmet/roman = 1, /obj/item/clothing/head/helmet/roman/legionaire = 1, /obj/item/clothing/under/roman = 1, /obj/item/clothing/shoes/roman = 1, /obj/item/shield/riot/roman = 1)
refill_canister = /obj/item/vending_refill/autodrobe
@@ -1393,7 +1485,7 @@
/obj/item/clothing/glasses/regular=2,/obj/item/clothing/glasses/sunglasses/fake=2,/obj/item/clothing/head/sombrero=1,/obj/item/clothing/suit/poncho=1,
/obj/item/clothing/suit/ianshirt=1,/obj/item/clothing/shoes/laceup=2,/obj/item/clothing/shoes/black=4,
/obj/item/clothing/shoes/sandal=1, /obj/item/clothing/gloves/fingerless=2,
- /obj/item/storage/belt/fannypack=1, /obj/item/storage/belt/fannypack/blue=1, /obj/item/storage/belt/fannypack/red=1)
+ /obj/item/storage/belt/fannypack=1, /obj/item/storage/belt/fannypack/blue=1, /obj/item/storage/belt/fannypack/red=1, /obj/item/clothing/suit/mantle = 2, /obj/item/clothing/suit/mantle/old = 1, /obj/item/clothing/suit/mantle/regal = 2)
contraband = list(/obj/item/clothing/under/syndicate/tacticool=1,/obj/item/clothing/mask/balaclava=1,/obj/item/clothing/head/ushanka=1,/obj/item/clothing/under/soviet=1,/obj/item/storage/belt/fannypack/black=1)
premium = list(/obj/item/clothing/under/suit_jacket/checkered=1,/obj/item/clothing/head/mailman=1,/obj/item/clothing/under/rank/mailman=1,/obj/item/clothing/suit/jacket/leather=1,/obj/item/clothing/under/pants/mustangjeans=1)
refill_canister = /obj/item/vending_refill/clothing
diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm
index b2851129a29..c4c4c674294 100644
--- a/code/game/machinery/wishgranter.dm
+++ b/code/game/machinery/wishgranter.dm
@@ -13,26 +13,28 @@
/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user)
. = ..()
+
if(.)
- return
+ return ..()
+
if(charges <= 0)
- to_chat(user, "The Wish Granter lies silent.")
- return
+ to_chat(user, "The Wish Granter lies silent.")
+ return TRUE
else if(!ishuman(user))
- to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
+ to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's..")
return
else if(is_special_character(user))
- to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
+ to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
else if(!insisting)
- to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
+ to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
insisting = TRUE
else
- to_chat(user, "You speak. [pick("I want the station to disappear", "Humanity is corrupt, mankind must be destroyed", "I want to be rich", "I want to rule the world", "I want immortality.")]. The Wish Granter answers.")
- to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.")
+ to_chat(user, "You speak. [pick("I want the station to disappear", "Humanity is corrupt, mankind must be destroyed", "I want to be rich", "I want to rule the world", "I want immortality.")]. The Wish Granter answers.")
+ to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.")
charges--
insisting = FALSE
@@ -46,37 +48,43 @@
var/list/types = list()
/obj/machinery/wish_granter/super/attack_hand(mob/living/carbon/user)
+ . = ..()
+
+ if(.)
+ return ..()
+
if(!ishuman(user))
- to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
- return
- else if(is_special_character(user) || jobban_isbanned(user, ROLE_TRAITOR) || jobban_isbanned(user, "Syndicate"))
- to_chat(user, "Something instinctual makes you pull away.")
- return
+ to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
+ return TRUE
+
+ if(is_special_character(user) || jobban_isbanned(user, ROLE_TRAITOR) || jobban_isbanned(user, "Syndicate"))
+ to_chat(user, "Something instinctual makes you pull away.")
+ return TRUE
+
+ to_chat(user, "Your touch makes the Wish Granter stir. Are you really sure you want to do this?")
+
+ for(var/supname in GLOB.all_superheroes)
+ types += supname
+
+ var/wish
+ if(types.len == 1)
+ wish = pick(types)
else
-
- to_chat(user, "Your touch makes the Wish Granter stir. Are you really sure you want to do this?")
-
- for(var/supname in GLOB.all_superheroes)
- types += supname
-
- var/wish
- if(types.len == 1)
- wish = pick(types)
- else
- wish = input("You want to become...","Wish") as null|anything in types
+ wish = input("You want to become...", "Wish") as null|anything in types
- if(!src || !wish || user.stat == DEAD || (get_dist(src, user) > 4)) //another check after the input to check if someone already used it, closed it, or if they're dead, or if they ran off
- return
+ if(!wish || user.stat == DEAD || (get_dist(src, user) > 4)) // Another check after the input to check if someone already used it, closed it, or if they're dead, or if they ran off.
+ return
- var/datum/superheroes/S = GLOB.all_superheroes[wish]
- if(S.activated)
- to_chat(user,"There can only be one! Pick something else!")
- return
+ var/datum/superheroes/S = GLOB.all_superheroes[wish]
+ if(S.activated)
+ to_chat(user,"There can only be one! Pick something else!")
+ return
- S.create(user)
- S.activated = TRUE //sets this superhero as taken so we don't have duplicates
- playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1)
- visible_message("The wishgranter fades into mist..")
- add_attack_logs(null, user, "Became [GLOB.all_superheroes[wish]]")
- notify_ghosts("[GLOB.all_superheroes[wish]] has appeared in [get_area(user)].", source = user)
- qdel(src)
+ S.create(user)
+ S.activated = TRUE //sets this superhero as taken so we don't have duplicates
+
+ playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1)
+ visible_message("The wishgranter fades into mist..")
+ add_attack_logs(null, user, "Became [GLOB.all_superheroes[wish]]")
+ notify_ghosts("[GLOB.all_superheroes[wish]] has appeared in [get_area(user)].", source = user)
+ qdel(src)
diff --git a/code/game/magic/Uristrunes.dm b/code/game/magic/Uristrunes.dm
index 1a242594bfe..e0621db3d9b 100644
--- a/code/game/magic/Uristrunes.dm
+++ b/code/game/magic/Uristrunes.dm
@@ -1,7 +1,7 @@
/proc/get_rune_cult(word)
var/animated
- if(word && !(ticker.cultdat.theme == "fire" || ticker.cultdat.theme == "death"))
+ if(word && !(SSticker.cultdat.theme == "fire" || SSticker.cultdat.theme == "death"))
animated = 1
else
animated = 0
@@ -18,11 +18,11 @@ var/runetype = "rune"
var/lookup = "[symbol_bits]-[animated]"
- if(!ticker.mode)//work around for maps with runes and cultdat is not loaded all the way
+ if(!SSticker.mode)//work around for maps with runes and cultdat is not loaded all the way
runetype = "rune"
- else if(ticker.cultdat.theme == "fire")
+ else if(SSticker.cultdat.theme == "fire")
runetype = "fire-rune"
- else if(ticker.cultdat.theme == "death")
+ else if(SSticker.cultdat.theme == "death")
runetype = "death-rune"
diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm
index f1ad010ea93..8a910670201 100644
--- a/code/game/mecha/equipment/tools/medical_tools.dm
+++ b/code/game/mecha/equipment/tools/medical_tools.dm
@@ -4,7 +4,7 @@
/obj/item/mecha_parts/mecha_equipment/medical/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/mecha_parts/mecha_equipment/medical/can_attach(obj/mecha/medical/M)
@@ -13,19 +13,19 @@
/obj/item/mecha_parts/mecha_equipment/medical/attach(obj/mecha/M)
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/mecha_parts/mecha_equipment/medical/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/mecha_parts/mecha_equipment/medical/process()
if(!chassis)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return 1
/obj/item/mecha_parts/mecha_equipment/medical/detach()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/mecha_parts/mecha_equipment/medical/sleeper
@@ -66,7 +66,7 @@
return
target.forceMove(src)
patient = target
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
update_equip_info()
occupant_message("[target] successfully loaded into [src]. Life support functions engaged.")
chassis.visible_message("[chassis] loads [target] into [src].")
@@ -90,7 +90,7 @@
patient.forceMove(get_turf(src))
occupant_message("[patient] ejected. Life support functions disabled.")
log_message("[patient] ejected. Life support functions disabled.")
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
patient = null
update_equip_info()
@@ -98,7 +98,7 @@
if(patient)
occupant_message("Unable to detach [src] - equipment occupied!")
return
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/mecha_parts/mecha_equipment/medical/sleeper/get_equip_info()
@@ -221,7 +221,7 @@
set_ready_state(1)
log_message("Deactivated.")
occupant_message("[src] deactivated - no power.")
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
var/mob/living/carbon/M = patient
if(!M)
@@ -263,11 +263,11 @@
processed_reagents = new
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/detach()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/critfail()
@@ -374,7 +374,7 @@
m++
if(processed_reagents.len)
message += " added to production"
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
occupant_message(message)
occupant_message("Reagent processing started.")
log_message("Reagent processing started.")
@@ -513,7 +513,7 @@
if(!processed_reagents.len || reagents.total_volume >= reagents.maximum_volume || !chassis.has_charge(energy_drain))
occupant_message("Reagent processing stopped.")
log_message("Reagent processing stopped.")
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
var/amount = synth_speed / processed_reagents.len
for(var/reagent in processed_reagents)
diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm
index b1a110813e8..635f1718134 100644
--- a/code/game/mecha/equipment/tools/mining_tools.dm
+++ b/code/game/mecha/equipment/tools/mining_tools.dm
@@ -59,12 +59,12 @@
drill.log_message("Drilled through [src]")
drill.move_ores()
-/turf/simulated/floor/plating/airless/asteroid/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+/turf/simulated/floor/plating/asteroid/airless/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
if(istype(drill, /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill))
- for(var/turf/simulated/floor/plating/airless/asteroid/M in range(1, src))
+ for(var/turf/simulated/floor/plating/asteroid/airless/M in range(1, src))
M.gets_drilled()
else
- for(var/turf/simulated/floor/plating/airless/asteroid/M in range(1, drill.chassis))
+ for(var/turf/simulated/floor/plating/asteroid/airless/M in range(1, drill.chassis))
if(get_dir(drill.chassis, M) & drill.chassis.dir)
M.gets_drilled()
drill.log_message("Drilled through [src]")
@@ -116,14 +116,14 @@
/obj/item/mecha_parts/mecha_equipment/mining_scanner/attach(obj/mecha/M)
. = ..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
M.occupant_sight_flags |= SEE_TURFS
if(M.occupant)
M.occupant.update_sight()
/obj/item/mecha_parts/mecha_equipment/mining_scanner/detach()
chassis.occupant_sight_flags &= ~SEE_TURFS
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
if(chassis.occupant)
chassis.occupant.update_sight()
return ..()
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm
index a42e76015c1..4cfbc5c8143 100644
--- a/code/game/mecha/equipment/tools/other_tools.dm
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -193,7 +193,7 @@
selectable = 0
/obj/item/mecha_parts/mecha_equipment/repair_droid/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
if(chassis)
chassis.overlays -= droid_overlay
return ..()
@@ -205,7 +205,7 @@
/obj/item/mecha_parts/mecha_equipment/repair_droid/detach()
chassis.overlays -= droid_overlay
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info()
if(!chassis) return
@@ -217,12 +217,12 @@
if(href_list["toggle_repairs"])
chassis.overlays -= droid_overlay
if(equip_ready)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
droid_overlay = new(icon, icon_state = "repair_droid_a")
log_message("Activated.")
set_ready_state(0)
else
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
droid_overlay = new(icon, icon_state = "repair_droid")
log_message("Deactivated.")
set_ready_state(1)
@@ -232,7 +232,7 @@
/obj/item/mecha_parts/mecha_equipment/repair_droid/process()
if(!chassis)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
set_ready_state(1)
return
var/h_boost = health_boost
@@ -250,10 +250,10 @@
repaired = 1
if(repaired)
if(!chassis.use_power(energy_drain))
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
set_ready_state(1)
else //no repair needed, we turn off
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
set_ready_state(1)
chassis.overlays -= droid_overlay
droid_overlay = new(icon, icon_state = "repair_droid")
@@ -273,11 +273,11 @@
selectable = 0
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/detach()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
..()
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_charge()
@@ -302,11 +302,11 @@
..()
if(href_list["toggle_relay"])
if(equip_ready) //inactive
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
set_ready_state(0)
log_message("Activated.")
else
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
set_ready_state(1)
log_message("Deactivated.")
@@ -317,12 +317,12 @@
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/process()
if(!chassis || chassis.internal_damage & MECHA_INT_SHORT_CIRCUIT)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
set_ready_state(1)
return
var/cur_charge = chassis.get_charge()
if(isnull(cur_charge) || !chassis.cell)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
set_ready_state(1)
occupant_message("No powercell detected.")
return
@@ -358,11 +358,11 @@
/obj/item/mecha_parts/mecha_equipment/generator/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/mecha_parts/mecha_equipment/generator/detach()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
..()
/obj/item/mecha_parts/mecha_equipment/generator/Topic(href, href_list)
@@ -370,11 +370,11 @@
if(href_list["toggle"])
if(equip_ready) //inactive
set_ready_state(0)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
log_message("Activated.")
else
set_ready_state(1)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
log_message("Deactivated.")
/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
@@ -447,11 +447,11 @@
/obj/item/mecha_parts/mecha_equipment/generator/process()
if(!chassis)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
set_ready_state(1)
return
if(fuel_amount<=0)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
log_message("Deactivated - no fuel.")
set_ready_state(1)
return
@@ -460,7 +460,7 @@
set_ready_state(1)
occupant_message("No powercell detected.")
log_message("Deactivated.")
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
var/use_fuel = fuel_per_cycle_idle
if(cur_charge < chassis.cell.maxcharge)
diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm
index 0a623bf5cb1..940e89b804b 100644
--- a/code/game/mecha/equipment/tools/work_tools.dm
+++ b/code/game/mecha/equipment/tools/work_tools.dm
@@ -232,7 +232,7 @@
occupant_message("Deconstructing [target]...")
if(do_after_cooldown(F))
chassis.spark_system.start()
- F.ChangeTurf(/turf/space)
+ F.ChangeTurf(F.baseturf)
F.air_update_turf()
playsound(F, usesound, 50, 1)
else if(istype(target, /obj/machinery/door/airlock))
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 3db9272cce8..fc8d8b1e83d 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -33,6 +33,7 @@
"Phazon",
"Exosuit Equipment",
"Cyborg Upgrade Modules",
+ "Medical",
"Misc"
)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 6cfd1d63942..258d0eb7898 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -23,6 +23,7 @@
infra_luminosity = 15 //byond implementation is bugged.
force = 5
armor = list(melee = 20, bullet = 10, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+ var/ruin_mecha = FALSE //if the mecha starts on a ruin, don't automatically give it a tracking beacon to prevent metagaming.
var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items)
var/can_move = 0 // time of next allowed movement
var/mob/living/carbon/occupant = null
@@ -118,7 +119,7 @@
smoke_system.attach(src)
add_cell()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
GLOB.poi_list |= src
log_message("[src] created.")
GLOB.mechas_list += src //global mech list
@@ -137,6 +138,10 @@
////////////////////////
////// Helpers /////////
////////////////////////
+
+/obj/mecha/get_cell()
+ return cell
+
/obj/mecha/proc/add_airtank()
internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
return internal_tank
@@ -670,7 +675,7 @@
QDEL_NULL(cell)
QDEL_NULL(internal_tank)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
GLOB.poi_list.Remove(src)
equipment.Cut()
cell = null
@@ -1518,6 +1523,8 @@
if(user == occupant)
user.sight |= occupant_sight_flags
+ ..()
+
/obj/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
if(!no_effect)
if(selected)
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index ab38ee3a0d0..5b4a8143bef 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -20,9 +20,9 @@
update_pressure()
/obj/mecha/working/ripley/Destroy()
- while(damage_absorption.["brute"] < 0.6)
- new /obj/item/asteroid/goliath_hide(loc)
- damage_absorption.["brute"] = damage_absorption.["brute"] + 0.1 //If a goliath-plated ripley gets killed, all the plates drop
+ while(damage_absorption["brute"] < 0.6)
+ new /obj/item/stack/sheet/animalhide/goliath_hide(loc)
+ damage_absorption["brute"] = damage_absorption["brute"] + 0.1 //If a goliath-plated ripley gets killed, all the plates drop
for(var/atom/movable/A in cargo)
A.forceMove(loc)
step_rand(A)
@@ -31,28 +31,28 @@
/obj/mecha/working/ripley/go_out()
..()
- if(damage_absorption.["brute"] < 0.6 && damage_absorption.["brute"] > 0.3)
+ if(damage_absorption["brute"] < 0.6 && damage_absorption["brute"] > 0.3)
overlays = null
overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-open")
- else if(damage_absorption.["brute"] == 0.3)
+ else if(damage_absorption["brute"] == 0.3)
overlays = null
overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full-open")
/obj/mecha/working/ripley/moved_inside(var/mob/living/carbon/human/H as mob)
..()
- if(damage_absorption.["brute"] < 0.6 && damage_absorption.["brute"] > 0.3)
+ if(damage_absorption["brute"] < 0.6 && damage_absorption["brute"] > 0.3)
overlays = null
overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g")
- else if(damage_absorption.["brute"] == 0.3)
+ else if(damage_absorption["brute"] == 0.3)
overlays = null
overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full")
/obj/mecha/working/ripley/mmi_moved_inside(var/obj/item/mmi/mmi_as_oc as obj,mob/user as mob)
..()
- if(damage_absorption.["brute"] < 0.6 && damage_absorption.["brute"] > 0.3)
+ if(damage_absorption["brute"] < 0.6 && damage_absorption["brute"] > 0.3)
overlays = null
overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g")
- else if(damage_absorption.["brute"] == 0.3)
+ else if(damage_absorption["brute"] == 0.3)
overlays = null
overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full")
diff --git a/code/game/mecha/working/working.dm b/code/game/mecha/working/working.dm
index e4c001a508a..516b57e898a 100644
--- a/code/game/mecha/working/working.dm
+++ b/code/game/mecha/working/working.dm
@@ -3,4 +3,5 @@
/obj/mecha/working/New()
..()
- trackers += new /obj/item/mecha_parts/mecha_tracking(src)
+ if(!ruin_mecha)
+ trackers += new /obj/item/mecha_parts/mecha_tracking(src)
diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm
index 59ae654c85b..118d3efcc2c 100644
--- a/code/game/objects/effects/alien_acid.dm
+++ b/code/game/objects/effects/alien_acid.dm
@@ -53,11 +53,11 @@
if(istype(target, /turf/simulated/mineral))
var/turf/simulated/mineral/M = target
- M.ChangeTurf(/turf/simulated/floor/plating/airless/asteroid)
+ M.ChangeTurf(/turf/simulated/floor/plating/asteroid/airless)
if(istype(target, /turf/simulated/floor))
var/turf/simulated/floor/F = target
- F.ChangeTurf(/turf/space)
+ F.ChangeTurf(F.baseturf)
if(istype(target, /turf/simulated/wall))
var/turf/simulated/wall/W = target
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 53072d7e82c..c410a9130a0 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -14,7 +14,6 @@ var/global/list/image/splatter_cache = list()
icon = 'icons/effects/blood.dmi'
icon_state = "mfloor1"
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
- appearance_flags = NO_CLIENT_COLOR
blood_DNA = list()
var/base_icon = 'icons/effects/blood.dmi'
var/blood_state = BLOOD_STATE_HUMAN
@@ -28,7 +27,7 @@ var/global/list/image/splatter_cache = list()
. = ..()
update_icon()
if(GAMEMODE_IS_CULT)
- var/datum/game_mode/cult/mode_ticker = ticker.mode
+ var/datum/game_mode/cult/mode_ticker = SSticker.mode
var/turf/T = get_turf(src)
if(T && (is_station_level(T.z)))//F I V E T I L E S
if(!(T in mode_ticker.bloody_floors))
@@ -48,7 +47,7 @@ var/global/list/image/splatter_cache = list()
/obj/effect/decal/cleanable/blood/Destroy()
if(GAMEMODE_IS_CULT)
- var/datum/game_mode/cult/mode_ticker = ticker.mode
+ var/datum/game_mode/cult/mode_ticker = SSticker.mode
var/turf/T = get_turf(src)
if(T && (is_station_level(T.z)))
mode_ticker.bloody_floors -= T
@@ -89,7 +88,7 @@ var/global/list/image/splatter_cache = list()
return TRUE
//Add "bloodiness" of this blood's type, to the human's shoes
-/obj/effect/decal/cleanable/blood/Crossed(atom/movable/O)
+/obj/effect/decal/cleanable/blood/Crossed(atom/movable/O, oldloc)
if(!off_floor && ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
@@ -155,7 +154,6 @@ var/global/list/image/splatter_cache = list()
layer = TURF_LAYER
random_icon_states = null
blood_DNA = list()
- appearance_flags = NO_CLIENT_COLOR
var/list/existing_dirs = list()
/obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in()
@@ -192,7 +190,7 @@ var/global/list/image/splatter_cache = list()
icon = 'icons/effects/blood.dmi'
icon_state = "gibbl5"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
- noclear = TRUE
+ no_clear = TRUE
var/fleshcolor = "#FFFFFF"
/obj/effect/decal/cleanable/blood/gibs/update_icon()
@@ -221,18 +219,11 @@ var/global/list/image/splatter_cache = list()
/obj/effect/decal/cleanable/blood/gibs/core
random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
-
-/obj/effect/decal/cleanable/blood/gibs/Initialize()
- . = ..()
- reagents.add_reagent("liquidgibs", 5)
+ scoop_reagents = list("liquidgibs" = 5)
/obj/effect/decal/cleanable/blood/gibs/cleangibs //most ironic name ever...
-
-/obj/effect/decal/cleanable/blood/gibs/cleangibs/Initialize() //no reagent!
- . = ..()
- reagents.remove_reagent("liquidgibs",5)
-
+ scoop_reagents = null
/obj/effect/decal/cleanable/blood/gibs/proc/streak(var/list/directions)
set waitfor = 0
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index d601283a703..d1ba3204bd0 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -15,10 +15,7 @@
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
anchored = TRUE
-
-/obj/effect/decal/cleanable/ash/Initialize()
- . = ..()
- reagents.add_reagent("ash", 10)
+ scoop_reagents = list("ash" = 10)
/obj/effect/decal/cleanable/dirt
name = "dirt"
@@ -40,11 +37,8 @@
/obj/effect/decal/cleanable/dirt/blackpowder
name = "black powder"
mouse_opacity = TRUE
- noscoop = TRUE
-
-/obj/effect/decal/cleanable/dirt/blackpowder/Initialize()
- . = ..()
- reagents.add_reagent("blackpowder", 40) // size 2 explosion when activated
+ no_scoop = TRUE
+ scoop_reagents = list("blackpowder" = 40) // size 2 explosion when activated
/obj/effect/decal/cleanable/flour
name = "flour"
@@ -127,22 +121,15 @@
icon = 'icons/effects/blood.dmi'
icon_state = "vomit_1"
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
- noclear = TRUE
-
-/obj/effect/decal/cleanable/vomit/Initialize()
- . = ..()
- reagents.add_reagent("vomit", 5)
+ no_clear = TRUE
+ scoop_reagents = list("vomit" = 5)
/obj/effect/decal/cleanable/vomit/green
name = "green vomit"
desc = "It's all gummy. Ew."
icon_state = "gvomit_1"
random_icon_states = list("gvomit_1", "gvomit_2", "gvomit_3", "gvomit_4")
-
-/obj/effect/decal/cleanable/vomit/green/Initialize()
- . = ..()
- reagents.remove_reagent("vomit", 5)
- reagents.add_reagent("green_vomit", 5)
+ scoop_reagents = list("green_vomit" = 5)
/obj/effect/decal/cleanable/tomato_smudge
name = "tomato smudge"
@@ -189,10 +176,7 @@
icon = 'icons/effects/effects.dmi'
icon_state = "flour"
color = "#D5820B"
-
-/obj/effect/decal/cleanable/fungus/Initialize()
- . = ..()
- reagents.add_reagent("fungus", 10)
+ scoop_reagents = list("fungus" = 10)
/obj/effect/decal/cleanable/confetti //PARTY TIME!
name = "confetti"
@@ -202,3 +186,11 @@
icon_state = "confetti1"
random_icon_states = list("confetti1", "confetti2", "confetti3")
anchored = TRUE
+
+/obj/effect/decal/cleanable/insectguts
+ name = "cockroach guts"
+ desc = "One bug squashed. Four more will rise in its place."
+ icon = 'icons/effects/blood.dmi'
+ icon_state = "xfloor1"
+ random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
+ anchored = TRUE
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/Cleanable/tracks.dm b/code/game/objects/effects/decals/Cleanable/tracks.dm
index 8598381aaf1..1e45c2aa4cf 100644
--- a/code/game/objects/effects/decals/Cleanable/tracks.dm
+++ b/code/game/objects/effects/decals/Cleanable/tracks.dm
@@ -29,7 +29,7 @@ var/global/list/image/fluidtrack_cache = list()
blood_state = BLOOD_STATE_HUMAN //the icon state to load images from
-/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
+/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O, oldloc)
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 52ec24df16c..461273bccdb 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,8 +1,6 @@
/obj/effect/decal/cleanable
anchored = TRUE
var/list/random_icon_states = list()
- var/noscoop = FALSE //if it has this, don't let it be scooped up
- var/noclear = FALSE //if it has this, don't delete it when its' scooped up
/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
return FALSE
@@ -10,7 +8,6 @@
/obj/effect/decal/cleanable/New()
if(random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)
- create_reagents(100)
if(smooth)
queue_smooth(src)
queue_smooth_neighbors(src)
@@ -19,25 +16,4 @@
/obj/effect/decal/cleanable/Destroy()
if(smooth)
queue_smooth_neighbors(src)
- return ..()
-
-/obj/effect/decal/cleanable/attackby(obj/item/W as obj, mob/user as mob,)
- if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks))
- if(src.reagents && W.reagents && !noscoop)
- if(!src.reagents.total_volume)
- to_chat(user, "There isn't enough [src] to scoop up!")
- return
- if(W.reagents.total_volume >= W.reagents.maximum_volume)
- to_chat(user, "[W] is full!")
- return
- to_chat(user, "You scoop the [src] into [W]!")
- reagents.trans_to(W, reagents.total_volume)
- if(!reagents.total_volume && !noclear) //scooped up all of it
- qdel(src)
- return
-
-/obj/effect/decal/cleanable/ex_act()
- if(reagents)
- for(var/datum/reagent/R in reagents.reagent_list)
- R.on_ex_act()
- ..()
\ No newline at end of file
+ return ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm
new file mode 100644
index 00000000000..31ae7ab68de
--- /dev/null
+++ b/code/game/objects/effects/decals/decal.dm
@@ -0,0 +1,15 @@
+/obj/effect/turf_decal
+ icon = 'icons/turf/decals.dmi'
+ icon_state = "warningline"
+ layer = TURF_DECAL_LAYER
+
+/obj/effect/turf_decal/Initialize(mapload)
+ . = ..()
+ qdel(src) // return INITIALIZE_HINT_QDEL <-- Doesn't work
+
+/obj/effect/turf_decal/ComponentInitialize()
+ . = ..()
+ var/turf/T = loc
+ if(!istype(T)) //you know this will happen somehow
+ CRASH("Turf decal initialized in an object/nullspace")
+ T.AddComponent(/datum/component/decal, icon, icon_state, dir, CLEAN_GOD, color, null, null, alpha)
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 52ad55c48a4..64561630d06 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -54,3 +54,16 @@
/obj/effect/decal/straw/edge
icon_state = "strawscatterededge"
+
+/obj/effect/decal/ants
+ name = "space ants"
+ desc = "A bunch of space ants."
+ icon = 'icons/goonstation/effects/effects.dmi'
+ icon_state = "spaceants"
+ scoop_reagents = list("ants" = 20)
+
+/obj/effect/decal/ants/Initialize(mapload)
+ . = ..()
+ var/scale = (rand(2, 10) / 10) + (rand(0, 5) / 100)
+ transform = matrix(transform, scale, scale, MATRIX_SCALE)
+ setDir(pick(NORTH, SOUTH, EAST, WEST))
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/turfdecals/dirt.dm b/code/game/objects/effects/decals/turfdecals/dirt.dm
new file mode 100644
index 00000000000..a2a1e8c6455
--- /dev/null
+++ b/code/game/objects/effects/decals/turfdecals/dirt.dm
@@ -0,0 +1,5 @@
+/obj/effect/turf_decal/sand
+ icon_state = "sandyfloor"
+
+/obj/effect/turf_decal/sand/plating
+ icon_state = "sandyplating"
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/turfdecals/markings.dm b/code/game/objects/effects/decals/turfdecals/markings.dm
new file mode 100644
index 00000000000..8687967e1d1
--- /dev/null
+++ b/code/game/objects/effects/decals/turfdecals/markings.dm
@@ -0,0 +1,152 @@
+/obj/effect/turf_decal/stripes/line
+ icon_state = "warningline"
+
+/obj/effect/turf_decal/stripes/end
+ icon_state = "warn_end"
+
+/obj/effect/turf_decal/stripes/corner
+ icon_state = "warninglinecorner"
+
+/obj/effect/turf_decal/stripes/box
+ icon_state = "warn_box"
+
+/obj/effect/turf_decal/stripes/full
+ icon_state = "warn_full"
+
+/obj/effect/turf_decal/stripes/asteroid/line
+ icon_state = "ast_warn"
+
+/obj/effect/turf_decal/stripes/asteroid/end
+ icon_state = "ast_warn_end"
+
+/obj/effect/turf_decal/stripes/asteroid/corner
+ icon_state = "ast_warn_corner"
+
+/obj/effect/turf_decal/stripes/asteroid/box
+ icon_state = "ast_warn_box"
+
+/obj/effect/turf_decal/stripes/asteroid/full
+ icon_state = "ast_warn_full"
+
+/obj/effect/turf_decal/stripes/white/line
+ icon_state = "warningline_white"
+
+/obj/effect/turf_decal/stripes/white/end
+ icon_state = "warn_end_white"
+
+/obj/effect/turf_decal/stripes/white/corner
+ icon_state = "warninglinecorner_white"
+
+/obj/effect/turf_decal/stripes/white/box
+ icon_state = "warn_box_white"
+
+/obj/effect/turf_decal/stripes/white/full
+ icon_state = "warn_full_white"
+
+/obj/effect/turf_decal/stripes/red/line
+ icon_state = "warningline_red"
+
+/obj/effect/turf_decal/stripes/red/end
+ icon_state = "warn_end_red"
+
+/obj/effect/turf_decal/stripes/red/corner
+ icon_state = "warninglinecorner_red"
+
+/obj/effect/turf_decal/stripes/red/box
+ icon_state = "warn_box_red"
+
+/obj/effect/turf_decal/stripes/red/full
+ icon_state = "warn_full_red"
+
+/obj/effect/turf_decal/delivery
+ icon_state = "delivery"
+
+/obj/effect/turf_decal/delivery/white
+ icon_state = "delivery_white"
+
+/obj/effect/turf_decal/delivery/red
+ icon_state = "delivery_red"
+
+/obj/effect/turf_decal/bot
+ icon_state = "bot"
+
+/obj/effect/turf_decal/bot/right
+ icon_state = "bot_right"
+
+/obj/effect/turf_decal/bot/left
+ icon_state = "bot_left"
+
+/obj/effect/turf_decal/bot_white
+ icon_state = "bot_white"
+
+/obj/effect/turf_decal/bot_white/right
+ icon_state = "bot_right_white"
+
+/obj/effect/turf_decal/bot_white/left
+ icon_state = "bot_left_white"
+
+/obj/effect/turf_decal/bot_red
+ icon_state = "bot_red"
+
+/obj/effect/turf_decal/bot_red/right
+ icon_state = "bot_right_red"
+
+/obj/effect/turf_decal/bot_red/left
+ icon_state = "bot_left_red"
+
+/obj/effect/turf_decal/loading_area
+ icon_state = "loadingarea"
+
+/obj/effect/turf_decal/loading_area/white
+ icon_state = "loadingarea_white"
+
+/obj/effect/turf_decal/loading_area/red
+ icon_state = "loadingarea_red"
+
+/obj/effect/turf_decal/caution
+ icon_state = "caution"
+
+/obj/effect/turf_decal/caution/white
+ icon_state = "caution_white"
+
+/obj/effect/turf_decal/caution/red
+ icon_state = "caution_red"
+
+/obj/effect/turf_decal/caution/stand_clear
+ icon_state = "stand_clear"
+
+/obj/effect/turf_decal/caution/stand_clear/white
+ icon_state = "stand_clear_white"
+
+/obj/effect/turf_decal/caution/stand_clear/red
+ icon_state = "stand_clear_red"
+
+/obj/effect/turf_decal/arrows
+ icon_state = "arrows"
+
+/obj/effect/turf_decal/arrows/white
+ icon_state = "arrows_white"
+
+/obj/effect/turf_decal/arrows/red
+ icon_state = "arrows_red"
+
+/obj/effect/turf_decal/box
+ icon_state = "box"
+
+/obj/effect/turf_decal/box/corners
+ icon_state = "box_corners"
+
+/obj/effect/turf_decal/box/white
+ icon_state = "box_white"
+
+/obj/effect/turf_decal/box/white/corners
+ icon_state = "box_corners_white"
+
+/obj/effect/turf_decal/box/red
+ icon_state = "box_red"
+
+/obj/effect/turf_decal/box/red/corners
+ icon_state = "box_corners_red"
+
+/obj/effect/turf_decal/plaque
+ icon_state = "plaque"
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/turfdecals/tilecoloring.dm b/code/game/objects/effects/decals/turfdecals/tilecoloring.dm
new file mode 100644
index 00000000000..1708753dc1e
--- /dev/null
+++ b/code/game/objects/effects/decals/turfdecals/tilecoloring.dm
@@ -0,0 +1,39 @@
+/obj/effect/turf_decal/tile
+ name = "tile decal"
+ icon_state = "tile_corner"
+ layer = TURF_PLATING_DECAL_LAYER
+ alpha = 110
+
+/obj/effect/turf_decal/tile/blue
+ name = "blue corner"
+ color = "#52B4E9"
+
+/obj/effect/turf_decal/tile/green
+ name = "green corner"
+ color = "#9FED58"
+
+/obj/effect/turf_decal/tile/yellow
+ name = "yellow corner"
+ color = "#EFB341"
+
+/obj/effect/turf_decal/tile/red
+ name = "red corner"
+ color = "#DE3A3A"
+
+/obj/effect/turf_decal/tile/bar
+ name = "bar corner"
+ color = "#791500"
+ alpha = 130
+
+/obj/effect/turf_decal/tile/purple
+ name = "purple corner"
+ color = "#D381C9"
+
+/obj/effect/turf_decal/tile/brown
+ name = "brown corner"
+ color = "#A46106"
+
+/obj/effect/turf_decal/tile/neutral
+ name = "neutral corner"
+ color = "#D4D4D4"
+ alpha = 50
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/turfdecals/weather.dm b/code/game/objects/effects/decals/turfdecals/weather.dm
new file mode 100644
index 00000000000..9e8da6a3f89
--- /dev/null
+++ b/code/game/objects/effects/decals/turfdecals/weather.dm
@@ -0,0 +1,12 @@
+/obj/effect/turf_decal/weather
+ name = "sandy floor"
+ icon_state = "sandyfloor"
+
+/obj/effect/turf_decal/weather/snow
+ name = "snowy floor"
+ icon_state = "snowyfloor"
+
+/obj/effect/turf_decal/weather/snow/corner
+ name = "snow corner piece"
+ icon = 'icons/turf/snow.dmi'
+ icon_state = "snow_corner"
\ No newline at end of file
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index d061aca8d95..8bb117b832c 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -345,7 +345,7 @@ steam.start() -- spawns the effect
return 1
-/obj/effect/effect/bad_smoke/Crossed(mob/living/carbon/M as mob )
+/obj/effect/effect/bad_smoke/Crossed(mob/living/carbon/M as mob, oldloc)
..()
if(istype(M, /mob/living/carbon))
if(M.internal != null && M.wear_mask && (M.wear_mask.flags & AIRTIGHT))
@@ -569,7 +569,7 @@ steam.start() -- spawns the effect
M.coughedtime = 0
return
-/obj/effect/effect/sleep_smoke/Crossed(mob/living/carbon/M as mob )
+/obj/effect/effect/sleep_smoke/Crossed(mob/living/carbon/M as mob, oldloc)
..()
if(istype(M, /mob/living/carbon))
if(M.internal != null && M.wear_mask && (M.wear_mask.flags & AIRTIGHT))
@@ -672,7 +672,7 @@ steam.start() -- spawns the effect
R.updatehealth()
return
-/obj/effect/effect/mustard_gas/Crossed(mob/living/carbon/human/R as mob )
+/obj/effect/effect/mustard_gas/Crossed(mob/living/carbon/human/R as mob, oldloc)
..()
if(istype(R, /mob/living/carbon/human))
if(R.internal != null && usr.wear_mask && (R.wear_mask.flags & AIRTIGHT) && R.wear_suit != null && !istype(R.wear_suit, /obj/item/clothing/suit/storage/labcoat) && !istype(R.wear_suit, /obj/item/clothing/suit/straight_jacket) && !istype(R.wear_suit, /obj/item/clothing/suit/straight_jacket && !istype(R.wear_suit, /obj/item/clothing/suit/armor)))
@@ -984,7 +984,7 @@ steam.start() -- spawns the effect
qdel(src)
-/obj/structure/foam/Crossed(var/atom/movable/AM)
+/obj/structure/foam/Crossed(var/atom/movable/AM, oldloc)
if(metal)
return
diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm
index 1231c8136fa..04ea1dc0841 100644
--- a/code/game/objects/effects/effect_system/effect_system.dm
+++ b/code/game/objects/effects/effect_system/effect_system.dm
@@ -14,11 +14,11 @@ would spawn and follow the beaker, even if it is carried or thrown.
/obj/effect/particle_effect/New()
..()
- if(ticker)
+ if(SSticker)
cameranet.updateVisibility(src)
/obj/effect/particle_effect/Destroy()
- if(ticker)
+ if(SSticker)
cameranet.updateVisibility(src)
return ..()
diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm
index 6d746377ec7..f134bd44b10 100644
--- a/code/game/objects/effects/effect_system/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/effects_foam.dm
@@ -24,12 +24,12 @@
spawn(3 + metal*3)
process()
spawn(120)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
sleep(30)
if(metal)
var/turf/T = get_turf(src)
- if(istype(T, /turf/space))
+ if(istype(T, /turf/space) && !istype(T, /turf/space/transit))
T.ChangeTurf(/turf/simulated/floor/plating/metalfoam)
var/turf/simulated/floor/plating/metalfoam/MF = get_turf(src)
MF.metal = metal
@@ -76,10 +76,10 @@
F = new /obj/effect/particle_effect/foam(T, metal)
F.amount = amount
if(!metal)
- F.create_reagents(15)
+ F.create_reagents(25)
if(reagents)
for(var/datum/reagent/R in reagents.reagent_list)
- F.reagents.add_reagent(R.id, min(R.volume, 3), R.data, reagents.chem_temp)
+ F.reagents.add_reagent(R.id, min(R.volume, 5), R.data, reagents.chem_temp)
F.color = mix_color_from_reagents(reagents.reagent_list)
// foam disolves when heated
@@ -94,7 +94,7 @@
spawn(5)
qdel(src)
-/obj/effect/particle_effect/foam/Crossed(atom/movable/AM)
+/obj/effect/particle_effect/foam/Crossed(atom/movable/AM, oldloc)
if(metal)
return
@@ -149,14 +149,14 @@
F.amount = amount
if(!metal) // don't carry other chemicals if a metal foam
- F.create_reagents(15)
+ F.create_reagents(25)
if(carried_reagents)
for(var/id in carried_reagents)
if(banned_reagents.Find("[id]"))
continue
var/datum/reagent/reagent_volume = carried_reagents[id]
- F.reagents.add_reagent(id, min(reagent_volume, 3), null, temperature)
+ F.reagents.add_reagent(id, min(reagent_volume, 5), null, temperature)
F.color = mix_color_from_reagents(F.reagents.reagent_list)
else
F.reagents.add_reagent("cleaner", 1)
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index 405a0ec46f7..93ab0c8e51b 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -30,15 +30,15 @@
/obj/effect/particle_effect/smoke/New()
..()
- processing_objects |= src
+ START_PROCESSING(SSobj, src)
lifetime += rand(-1,1)
/obj/effect/particle_effect/smoke/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/particle_effect/smoke/proc/kill_smoke()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
INVOKE_ASYNC(src, .proc/fade_out)
QDEL_IN(src, 10)
@@ -52,7 +52,7 @@
steps--
return 1
-/obj/effect/particle_effect/smoke/Crossed(mob/living/M)
+/obj/effect/particle_effect/smoke/Crossed(mob/living/M, oldloc)
if(!istype(M))
return
smoke_mob(M)
@@ -207,4 +207,4 @@
return 1
/datum/effect_system/smoke_spread/sleeping
- effect_type = /obj/effect/particle_effect/smoke/sleeping
\ No newline at end of file
+ effect_type = /obj/effect/particle_effect/smoke/sleeping
diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm
index 21b9759df62..5feec285408 100644
--- a/code/game/objects/effects/effects.dm
+++ b/code/game/objects/effects/effects.dm
@@ -13,4 +13,39 @@
return
/obj/effect/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
- return FALSE
\ No newline at end of file
+ return FALSE
+
+/obj/effect/decal
+ plane = FLOOR_PLANE
+ var/no_scoop = FALSE //if it has this, don't let it be scooped up
+ var/no_clear = FALSE //if it has this, don't delete it when its' scooped up
+ var/list/scoop_reagents = null
+
+/obj/effect/decal/Initialize(mapload)
+ . = ..()
+ if(scoop_reagents)
+ create_reagents(100)
+ reagents.add_reagent_list(scoop_reagents)
+
+/obj/effect/decal/attackby(obj/item/I, mob/user)
+ if(istype(I, /obj/item/reagent_containers/glass) || istype(I, /obj/item/reagent_containers/food/drinks))
+ scoop(I, user)
+
+/obj/effect/decal/proc/scoop(obj/item/I, mob/user)
+ if(reagents && I.reagents && !no_scoop)
+ if(!reagents.total_volume)
+ to_chat(user, "There isn't enough [src] to scoop up!")
+ return
+ if(I.reagents.total_volume >= I.reagents.maximum_volume)
+ to_chat(user, "[I] is full!")
+ return
+ to_chat(user, "You scoop [src] into [I]!")
+ reagents.trans_to(I, reagents.total_volume)
+ if(!reagents.total_volume && !no_clear) //scooped up all of it
+ qdel(src)
+
+/obj/effect/decal/ex_act()
+ if(reagents)
+ for(var/datum/reagent/R in reagents.reagent_list)
+ R.on_ex_act()
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/mapping_helpers.dm b/code/game/objects/effects/mapping_helpers.dm
new file mode 100644
index 00000000000..44a16c5ae5f
--- /dev/null
+++ b/code/game/objects/effects/mapping_helpers.dm
@@ -0,0 +1,90 @@
+/obj/effect/baseturf_helper //Set the baseturfs of every turf in the /area/ it is placed.
+ name = "baseturf editor"
+ icon = 'icons/effects/mapping_helpers.dmi'
+ icon_state = ""
+
+ var/baseturf
+
+ layer = POINT_LAYER
+
+/obj/effect/baseturf_helper/Initialize(mapload)
+ . = ..()
+ var/area/thearea = get_area(src)
+ for(var/turf/T in get_area_turfs(thearea, z))
+ replace_baseturf(T)
+ return INITIALIZE_HINT_QDEL
+
+/obj/effect/baseturf_helper/proc/replace_baseturf(turf/thing)
+ if(thing.baseturf != thing.type)
+ thing.baseturf = baseturf
+
+/obj/effect/baseturf_helper/space
+ name = "space baseturf editor"
+ baseturf = /turf/space
+
+/obj/effect/baseturf_helper/asteroid
+ name = "asteroid baseturf editor"
+ baseturf = /turf/simulated/floor/plating/asteroid
+
+/obj/effect/baseturf_helper/asteroid/airless
+ name = "asteroid airless baseturf editor"
+ baseturf = /turf/simulated/floor/plating/asteroid/airless
+
+/obj/effect/baseturf_helper/asteroid/basalt
+ name = "asteroid basalt baseturf editor"
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt
+
+/obj/effect/baseturf_helper/asteroid/snow
+ name = "asteroid snow baseturf editor"
+ baseturf = /turf/simulated/floor/plating/asteroid/snow
+
+/obj/effect/baseturf_helper/beach/sand
+ name = "beach sand baseturf editor"
+ baseturf = /turf/simulated/floor/beach/sand
+
+/obj/effect/baseturf_helper/beach/water
+ name = "water baseturf editor"
+ baseturf = /turf/simulated/floor/beach/water
+
+/obj/effect/baseturf_helper/lava
+ name = "lava baseturf editor"
+ baseturf = /turf/simulated/floor/plating/lava/smooth
+
+/obj/effect/baseturf_helper/lava_land/surface
+ name = "lavaland baseturf editor"
+ baseturf = /turf/simulated/floor/plating/lava/smooth/lava_land_surface
+
+/obj/effect/mapping_helpers
+ icon = 'icons/effects/mapping_helpers.dmi'
+ icon_state = ""
+ var/late = FALSE
+
+/obj/effect/mapping_helpers/Initialize(mapload)
+ ..()
+
+ return late ? INITIALIZE_HINT_LATELOAD : qdel(src) // INITIALIZE_HINT_QDEL <-- Doesn't work
+
+/obj/effect/mapping_helpers/no_lava
+ icon_state = "no_lava"
+
+/obj/effect/mapping_helpers/airlock
+ layer = DOOR_HELPER_LAYER
+
+/obj/effect/mapping_helpers/airlock/unres
+ name = "airlock unresctricted side helper"
+ icon_state = "airlock_unres_helper"
+
+/obj/effect/mapping_helpers/airlock/unres/Initialize(mapload)
+ if(!mapload)
+ log_world("### MAP WARNING, [src] spawned outside of mapload!")
+ return
+ var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in src.loc
+ if(airlock)
+ airlock.unres_sides ^= dir
+ else
+ log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
+ ..()
+/obj/effect/mapping_helpers/no_lava/New()
+ var/turf/T = get_turf(src)
+ T.flags |= NO_LAVA_GEN
+ . = ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 547df1b96ef..76e28f013a1 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -11,7 +11,7 @@
/obj/effect/mine/proc/mineEffect(mob/living/victim)
to_chat(victim, "*click*")
-/obj/effect/mine/Crossed(AM as mob|obj)
+/obj/effect/mine/Crossed(AM as mob|obj, oldloc)
if(!isliving(AM))
return
var/mob/living/M = AM
diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm
index 3ea1fc0c3d6..191f776d01c 100644
--- a/code/game/objects/effects/misc.dm
+++ b/code/game/objects/effects/misc.dm
@@ -92,4 +92,36 @@
name = "horrific experiment"
desc = "Some sort of pod filled with blood and vicerea. You swear you can see it moving..."
icon = 'icons/obj/cloning.dmi'
- icon_state = "pod_g"
\ No newline at end of file
+ icon_state = "pod_g"
+
+
+//Makes a tile fully lit no matter what
+/obj/effect/fullbright
+ icon = 'icons/effects/alphacolors.dmi'
+ icon_state = "white"
+ plane = LIGHTING_PLANE
+ layer = LIGHTING_LAYER
+ blend_mode = BLEND_ADD
+
+
+/obj/effect/dummy/lighting_obj
+ name = "lighting fx obj"
+ desc = "Tell a coder if you're seeing this."
+ icon_state = "nothing"
+ light_color = "#FFFFFF"
+ light_range = MINIMUM_USEFUL_LIGHT_RANGE
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+
+/obj/effect/dummy/lighting_obj/Initialize(mapload, _color, _range, _power, _duration)
+ . = ..()
+ set_light(_range ? _range : light_range, _power ? _power : light_power, _color ? _color : light_color)
+ if(_duration)
+ QDEL_IN(src, _duration)
+
+/obj/effect/dummy/lighting_obj/moblight
+ name = "mob lighting fx"
+
+/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration)
+ . = ..()
+ if(!ismob(loc))
+ return INITIALIZE_HINT_QDEL
\ No newline at end of file
diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm
index faaf623fa50..f36902664f8 100644
--- a/code/game/objects/effects/portals.dm
+++ b/code/game/objects/effects/portals.dm
@@ -3,68 +3,125 @@
desc = "Looks unstable. Best to test it with the clown."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "portal"
- density = 1
- unacidable = 1//Can't destroy energy portals.
- var/failchance = 5
+ unacidable = TRUE
+ anchored = TRUE
+
var/obj/item/target = null
var/creator = null
- anchored = 1
- var/precision = 1 // how close to the portal you will teleport. 0 = on the portal, 1 = adjacent
- var/can_multitool_to_remove = 0
+
+ var/failchance = 5
+ var/fail_icon = "portal1"
+
+ var/precision = TRUE // how close to the portal you will teleport. FALSE = on the portal, TRUE = adjacent
+ var/can_multitool_to_remove = FALSE
var/ignore_tele_proof_area_setting = FALSE
-/obj/effect/portal/Bumped(mob/M as mob|obj)
- teleport(M)
+/obj/effect/portal/New(loc, turf/target, creator = null, lifespan = 300)
+ ..()
-/obj/effect/portal/New(loc, turf/target, creator=null, lifespan=300)
GLOB.portals += src
- src.loc = loc
+
src.target = target
src.creator = creator
+
if(lifespan > 0)
spawn(lifespan)
qdel(src)
/obj/effect/portal/Destroy()
GLOB.portals -= src
- if(istype(creator, /obj))
+
+ if(isobj(creator))
var/obj/O = creator
O.portal_destroyed(src)
+
creator = null
target = null
return ..()
-/obj/effect/portal/proc/teleport(atom/movable/M as mob|obj)
- if(istype(M, /obj/effect)) //sparks don't teleport
+/obj/effect/portal/singularity_pull()
+ return
+
+/obj/effect/portal/singularity_act()
+ return
+
+/obj/effect/portal/Crossed(atom/movable/AM, oldloc)
+ if(isobserver(AM))
+ return ..()
+
+ if(target && (get_turf(oldloc) == get_turf(target)))
+ return ..()
+
+ if(!teleport(AM))
+ return ..()
+
+/obj/effect/portal/attack_tk(mob/user)
+ return
+
+/obj/effect/portal/attack_hand(mob/user)
+ . = ..()
+ if(.)
return
- if(M.anchored&&istype(M, /obj/mecha))
- return
- if(!( target ))
- qdel(src)
- return
- if(istype(M, /atom/movable))
- if(prob(failchance))
- src.icon_state = "portal1"
- if(!do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to deep space.
- invalid_teleport()
- else
- if(!do_teleport(M, target, precision, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to a turf adjacent to target.
- invalid_teleport()
+ if(get_turf(user) == get_turf(src))
+ teleport(user)
+ if(Adjacent(user))
+ user.forceMove(get_turf(src))
+
+/obj/effect/portal/attack_ghost(mob/dead/observer/O)
+ if(target)
+ O.forceMove(target)
/obj/effect/portal/attackby(obj/item/A, mob/user)
- if(istype(A, /obj/item/multitool) && can_multitool_to_remove)
+ if(ismultitool(A) && can_multitool_to_remove)
qdel(src)
+ else if(user && Adjacent(user))
+ user.forceMove(get_turf(src))
+ return TRUE
+
+/obj/effect/portal/proc/can_teleport(atom/movable/M)
+ . = TRUE
+
+ if(!istype(M))
+ . = FALSE
+
+ if(!M.simulated || iseffect(M))
+ . = FALSE
+
+ if(M.anchored && ismecha(M))
+ . = FALSE
+
+/obj/effect/portal/proc/teleport(atom/movable/M)
+ if(!can_teleport(M))
+ return FALSE
+
+ if(!target)
+ qdel(src)
+ return FALSE
+
+ if(ismegafauna(M))
+ message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [key_name_admin(usr)].")
+
+ if(prob(failchance))
+ icon_state = fail_icon
+ if(!do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to deep space.
+ invalid_teleport()
+ return FALSE
+ else
+ if(!do_teleport(M, target, precision, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to a turf adjacent to target.
+ invalid_teleport()
+ return FALSE
+
+ return TRUE
/obj/effect/portal/proc/invalid_teleport()
visible_message("[src] flickers and fails due to bluespace interference!")
do_sparks(5, 0, loc)
qdel(src)
-
/obj/effect/portal/redspace
name = "redspace portal"
desc = "A portal capable of bypassing bluespace interference."
icon_state = "portal1"
failchance = 0
precision = 0
- ignore_tele_proof_area_setting = TRUE
\ No newline at end of file
+ ignore_tele_proof_area_setting = TRUE
diff --git a/code/game/objects/effects/snowcloud.dm b/code/game/objects/effects/snowcloud.dm
index 08a64d62f17..5723b66bc04 100644
--- a/code/game/objects/effects/snowcloud.dm
+++ b/code/game/objects/effects/snowcloud.dm
@@ -9,12 +9,12 @@
/obj/effect/snowcloud/New(turf, obj/machinery/snow_machine/SM)
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
if(SM && istype(SM))
parent_machine = SM
/obj/effect/snowcloud/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/snowcloud/process()
@@ -73,12 +73,12 @@
anchored = TRUE
/obj/effect/snow/New()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
icon_state = "snow[rand(1,6)]"
..()
/obj/effect/snow/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/snow/process()
diff --git a/code/game/objects/effects/spawners/airlock_spawner.dm b/code/game/objects/effects/spawners/airlock_spawner.dm
new file mode 100644
index 00000000000..496f02c61d1
--- /dev/null
+++ b/code/game/objects/effects/spawners/airlock_spawner.dm
@@ -0,0 +1,345 @@
+/*
+Spawners for mappers. Just plonk one down of the desired size and it will place the machinery for you. The red arrow things indicate where the chamber is.
+This spawner places pipe leading up to the interior door, you will need to finish it off yourself with a connector, canister, and pipe connecting the two. It also assumes you already put in wall and floor.
+*/
+
+#define HALF_X round((tiles_in_x_direction - 1) * 0.5) //These are required so that the airlock can be in the middle of the chamber wall
+#define HALF_Y round((tiles_in_y_direction - 1) * 0.5)
+#define CHAMBER_LONG 1
+#define CHAMBER_SQUARE 2
+#define CHAMBER_BIGGER 3
+#define DOOR_NORMAL_PLACEMENT 1
+#define DOOR_FLIPPED_PLACEMENT 2
+
+#define AIRPUMP_TAG "[id_to_link]_pump"
+#define SENSOR_TAG "[id_to_link]_sensor"
+#define OUTER_DOOR_TAG "[id_to_link]_outer"
+#define INNER_DOOR_TAG "[id_to_link]_inner"
+
+/obj/effect/spawner/airlock
+ name = "1 by 1 airlock spawner (interior north, exterior south)"
+ desc = "If you can see this, there's probably a missing airlock here. Better tell an admin and report this on the github."
+ icon = 'icons/obj/airlock_spawner.dmi'
+ icon_state = "1x1_N_to_S"
+ layer = SPLASHSCREEN_PLANE //So we absolutely always appear above everything else. We delete ourself after spawning so this is fine
+ var/interior_direction = NORTH //This is also the direction the spawner will send the pipe
+ var/exterior_direction = SOUTH
+ var/opposite_interior_direction //We're checking these often enough for them to merit their own vars
+ var/interior_direction_cw
+ var/interior_direction_ccw
+ var/north_or_south_interior //Used a bit everywhere for locational stuff
+ var/north_or_south_exterior //Likewise
+ var/tiles_in_x_direction = 1
+ var/tiles_in_y_direction = 1
+ var/id_to_link
+ var/radio_frequency = 1379
+ var/required_access = list(access_external_airlocks)
+ var/door_name = "external access"
+ var/door_type = /obj/machinery/door/airlock/external/glass
+ var/one_door_interior //For square airlocks, if you set this then a) only one door will spawn, and b) you can choose if the door should go opposite to how it normally goes. Please use the define
+ var/one_door_exterior //See above
+
+/obj/effect/spawner/airlock/Initialize()
+ ..()
+ forceMove(locate(x + 1, y + 1, z)) //Needs to move because our icon_state implies we are one turf to the northeast, when we're not
+ opposite_interior_direction = turn(interior_direction, 180) //Do it this way (instead of setting it directly) to avoid code mishaps
+ interior_direction_cw = turn(interior_direction, 90)
+ interior_direction_ccw = turn(interior_direction, 270)
+ if(interior_direction == NORTH || interior_direction == SOUTH)
+ north_or_south_interior = TRUE
+ if(exterior_direction == NORTH || exterior_direction == SOUTH)
+ north_or_south_exterior = TRUE
+ id_to_link = "[UID()]" //We want unique IDs, this will give us a unique ID
+ var/turf/turf_interior = get_airlock_location(interior_direction)
+ var/turf/turf_exterior = get_airlock_location(exterior_direction)
+ handle_door_creation(turf_interior, TRUE, one_door_interior)
+ handle_door_creation(turf_exterior, FALSE, one_door_exterior)
+ handle_pipes_creation(turf_interior)
+ handle_control_placement()
+ qdel(src)
+
+/obj/effect/spawner/airlock/proc/get_airlock_location(desired_direction) //Finds a turf to place an airlock and returns it, this turf will be in the middle of the relevant wall
+ var/turf/T
+ switch(desired_direction)
+ if(NORTH)
+ T = locate(x + HALF_X, y + tiles_in_y_direction, z)
+ if(SOUTH)
+ T = locate(x + HALF_X, y - 1, z)
+ if(EAST)
+ T = locate(x + tiles_in_x_direction, y + HALF_Y, z)
+ if(WEST)
+ T = locate(x - 1, y + HALF_Y, z)
+ return T
+
+/obj/effect/spawner/airlock/proc/handle_door_creation(turf/T, is_this_an_interior_airlock, one_door_only) //Creates a door (or two) and also creates a button
+ var/obj/machinery/door/airlock/A
+ if(one_door_only != DOOR_FLIPPED_PLACEMENT)
+ A = new door_type(T)
+ handle_door_stuff(A, is_this_an_interior_airlock)
+ var/obj/machinery/access_button/the_button = spawn_button(T, is_this_an_interior_airlock ? interior_direction : exterior_direction)
+ if(one_door_only == DOOR_NORMAL_PLACEMENT) //We only need one door, we are done
+ return
+ if(!(tiles_in_x_direction % 2) && (is_this_an_interior_airlock && north_or_south_interior || !is_this_an_interior_airlock && north_or_south_exterior)) //Handle extra airlock for aesthetics
+ A = new door_type(get_step(T, EAST))
+ handle_door_stuff(A, is_this_an_interior_airlock)
+ if(one_door_only == DOOR_FLIPPED_PLACEMENT)
+ the_button.forceMove(get_step(the_button, EAST))
+ else if(!(tiles_in_y_direction % 2) && (is_this_an_interior_airlock && !north_or_south_interior || !is_this_an_interior_airlock && !north_or_south_exterior)) //Handle extra airlock for aesthetics
+ A = new door_type(get_step(T, NORTH))
+ handle_door_stuff(A, is_this_an_interior_airlock)
+ if(one_door_only == DOOR_FLIPPED_PLACEMENT)
+ the_button.forceMove(get_step(the_button, NORTH))
+
+/obj/effect/spawner/airlock/proc/handle_door_stuff(obj/machinery/door/airlock/A, is_this_an_interior_airlock) //This sets up the door vars correctly and then locks it before first use
+ A.set_frequency(radio_frequency)
+ A.id_tag = is_this_an_interior_airlock ? INNER_DOOR_TAG : OUTER_DOOR_TAG
+ A.req_access = required_access
+ A.name = door_name
+ A.lock()
+
+/obj/effect/spawner/airlock/proc/spawn_button(turf/T, some_direction)
+ var/obj/machinery/access_button/the_button = new(T)
+ the_button.master_tag = id_to_link
+ the_button.set_frequency(radio_frequency)
+ switch(some_direction)
+ if(NORTH)
+ the_button.pixel_x -= 25
+ the_button.pixel_y = 7
+ if(EAST)
+ the_button.pixel_x = 7
+ the_button.pixel_y = -25
+ if(SOUTH)
+ the_button.pixel_x -= 25
+ the_button.pixel_y -= 7
+ if(WEST)
+ the_button.pixel_x -= 7
+ the_button.pixel_y -= 25
+ the_button.req_access = required_access
+ return the_button
+
+/obj/effect/spawner/airlock/proc/handle_control_placement() //Stick the sensor and controller on the same bit of wall, this will ONLY be unsuitable if airlocks are on both the south and west turfs
+ var/turf/T = get_turf(src)
+ var/obj/machinery/airlock_sensor/AS = new(T)
+ var/obj/machinery/embedded_controller/radio/airlock/airlock_controller/AC = new(T, id_to_link, radio_frequency, OUTER_DOOR_TAG, INNER_DOOR_TAG, AIRPUMP_TAG, SENSOR_TAG)
+ AC.req_access = required_access
+ AS.id_tag = SENSOR_TAG
+ AS.set_frequency(radio_frequency)
+ if(interior_direction != WEST && exterior_direction != WEST) //If west wall is free, place stuff there
+ AC.pixel_x -= 25
+ AC.pixel_y += 9
+ AS.pixel_x -= 25
+ AS.pixel_y -= 9
+ else if(interior_direction != SOUTH && exterior_direction != SOUTH) //If south wall is free, place stuff there
+ AC.pixel_x += 9
+ AC.pixel_y -= 25
+ AS.pixel_x -= 9
+ AS.pixel_y -= 25
+ else //Send them over to the other side of the chamber
+ T = locate(x + tiles_in_x_direction - 1, y + tiles_in_y_direction - 1, z)
+ AC.forceMove(T)
+ AS.forceMove(T)
+ AC.pixel_x += 25
+ AC.pixel_y += 9
+ AS.pixel_x += 25
+ AS.pixel_y -= 9
+
+/obj/effect/spawner/airlock/proc/handle_pipes_creation(turf/T) //This places all required piping down, then properly initializes it. T is the turf that the interior airlock occupies
+ var/turf/below_T = get_step(T, opposite_interior_direction)
+
+ var/two_way_pipe = interior_direction | opposite_interior_direction
+ var/chamber_shape //This determines the layout of the chamber and therefore how many vents should be present
+ if(tiles_in_x_direction == 2 && tiles_in_y_direction == 2)
+ chamber_shape = CHAMBER_SQUARE
+ else if(tiles_in_x_direction > 1 && tiles_in_y_direction > 1)
+ chamber_shape = CHAMBER_BIGGER
+ else
+ chamber_shape = CHAMBER_LONG
+ pipe_creation_helper(/obj/machinery/atmospherics/pipe/simple/visible, T, interior_direction, two_way_pipe)
+ switch(chamber_shape)
+ if(CHAMBER_LONG) //Easy enough, place a single vent
+ pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
+ below_T,
+ interior_direction)
+ if(CHAMBER_SQUARE) //We need a T-manifold and two vents for this
+ pipe_creation_helper(/obj/machinery/atmospherics/pipe/manifold/visible,
+ below_T,
+ north_or_south_interior ? WEST : SOUTH,
+ NORTH | EAST | (north_or_south_interior ? SOUTH : WEST))
+ pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
+ get_step(below_T, opposite_interior_direction),
+ interior_direction)
+ pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
+ north_or_south_interior ? EAST_OF_TURF(below_T) : NORTH_OF_TURF(below_T),
+ turn(interior_direction, interior_direction == SOUTH || interior_direction == EAST ? -90 : 90))
+ if(CHAMBER_BIGGER) //We need a central column of manifolds and a vent either side of each manifold
+ var/depth = north_or_south_interior ? tiles_in_y_direction : tiles_in_x_direction
+ var/turf/put_thing_here = below_T
+ for(var/i in 1 to depth)
+ if(i != depth)//We're placing more pipe later, so we need a 4-way manifold
+ pipe_creation_helper(/obj/machinery/atmospherics/pipe/manifold4w/visible, put_thing_here, interior_direction, NORTH | EAST | SOUTH | WEST)
+ else //We stop here, so place a T-manifold down
+ pipe_creation_helper(/obj/machinery/atmospherics/pipe/manifold/visible,
+ put_thing_here,
+ opposite_interior_direction,
+ interior_direction_cw | interior_direction | interior_direction_ccw)
+ pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
+ get_step(put_thing_here, interior_direction_cw),
+ interior_direction_ccw)
+ pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
+ get_step(put_thing_here, interior_direction_ccw),
+ interior_direction_cw)
+ put_thing_here = get_step(put_thing_here, opposite_interior_direction) //Now move the turf we're generating stuff from 1 forward
+
+/obj/effect/spawner/airlock/proc/pipe_creation_helper(path, location, direction, initialization_directions) //Create some kind of atmospherics machinery and initialize it properly
+ var/obj/machinery/atmospherics/A = new path(location)
+ A.dir = direction
+ A.on_construction(A.dir, initialization_directions ? initialization_directions : A.dir)
+ if(istype(A, /obj/machinery/atmospherics/unary/vent_pump/high_volume))
+ var/obj/machinery/atmospherics/unary/vent_pump/high_volume/created_pump = A
+ created_pump.id_tag = AIRPUMP_TAG
+ created_pump.set_frequency(radio_frequency)
+
+
+//Premade airlocks for mappers, probably won't need all of these but whatever
+/obj/effect/spawner/airlock/s_to_n
+ name = "1 by 1 airlock spawner (interior south, exterior north)"
+ icon_state = "1x1_S_to_N"
+ interior_direction = SOUTH
+ exterior_direction = NORTH
+/obj/effect/spawner/airlock/e_to_w
+ name = "1 by 1 airlock spawner (interior east, exterior west)"
+ icon_state = "1x1_E_to_W"
+ interior_direction = EAST
+ exterior_direction = WEST
+/obj/effect/spawner/airlock/w_to_e
+ name = "1 by 1 airlock spawner (interior west, exterior east)"
+ icon_state = "1x1_W_to_E"
+ interior_direction = WEST
+ exterior_direction = EAST
+
+/obj/effect/spawner/airlock/long //Long and thin
+ name = "long airlock spawner (interior north, exterior south)"
+ icon_state = "1x2_N_to_S"
+ tiles_in_y_direction = 2
+/obj/effect/spawner/airlock/s_to_n/long
+ name = "long airlock spawner (interior south, exterior north)"
+ icon_state = "1x2_S_to_N"
+ tiles_in_y_direction = 2
+/obj/effect/spawner/airlock/e_to_w/long
+ name = "long airlock spawner (interior east, exterior west)"
+ icon_state = "1x2_E_to_W"
+ tiles_in_x_direction = 2
+/obj/effect/spawner/airlock/w_to_e/long
+ name = "long airlock spawner (interior west, exterior east)"
+ icon_state = "1x2_W_to_E"
+ tiles_in_x_direction = 2
+
+/obj/effect/spawner/airlock/long/square //Square
+ name = "square airlock spawner (interior north, exterior south)"
+ icon_state = "2x2_N_to_S"
+ tiles_in_x_direction = 2
+/obj/effect/spawner/airlock/s_to_n/long/square
+ name = "square airlock spawner (interior south, exterior north)"
+ icon_state = "2x2_S_to_N"
+ tiles_in_x_direction = 2
+/obj/effect/spawner/airlock/e_to_w/long/square
+ name = "square airlock spawner (interior east, exterior west)"
+ icon_state = "2x2_E_to_W"
+ tiles_in_y_direction = 2
+/obj/effect/spawner/airlock/w_to_e/long/square
+ name = "square airlock spawner (interior west, exterior east)"
+ icon_state = "2x2_W_to_E"
+ tiles_in_y_direction = 2
+/obj/effect/spawner/airlock/long/square/e_to_s
+ name = "square airlock spawner (interior east, exterior south)"
+ icon_state = "2x2_E_to_S"
+ interior_direction = EAST
+ exterior_direction = SOUTH
+
+/obj/effect/spawner/airlock/long/square/wide
+ name = "rectangular airlock spawner (interior north, exterior south)"
+ icon_state = "3x2_N_to_S"
+ tiles_in_x_direction = 3
+/obj/effect/spawner/airlock/s_to_n/long/square/wide
+ name = "rectangular airlock spawner (interior south, exterior north)"
+ icon_state = "3x2_S_to_N"
+ tiles_in_x_direction = 3
+/obj/effect/spawner/airlock/e_to_w/long/square/wide
+ name = "rectangular airlock spawner (interior east, exterior west)"
+ icon_state = "3x2_E_to_W"
+ tiles_in_y_direction = 3
+/obj/effect/spawner/airlock/w_to_e/long/square/wide
+ name = "rectangular airlock spawner (interior west, exterior east)"
+ icon_state = "3x2_W_to_E"
+ tiles_in_y_direction = 3
+
+/obj/effect/spawner/airlock/long/square/three
+ name = "3 by 3 square airlock spawner (interior north, exterior south)"
+ icon_state = "3x3_N_to_S"
+ interior_direction = NORTH
+ exterior_direction = SOUTH
+ tiles_in_x_direction = 3
+ tiles_in_y_direction = 3
+
+/obj/effect/spawner/airlock/e_to_w/arrivals
+ required_access = null
+
+/obj/effect/spawner/airlock/engineer
+ required_access = list(access_engine)
+ door_name = "engineering external access"
+/obj/effect/spawner/airlock/e_to_w/engineer
+ required_access = list(access_engine)
+ door_name = "engineering external access"
+/obj/effect/spawner/airlock/s_to_n/engineer
+ required_access = list(access_engine)
+ door_name = "engineering external access"
+/obj/effect/spawner/airlock/long/engineer
+ required_access = list(access_engine)
+ door_name = "engineering external access"
+/obj/effect/spawner/airlock/long/square/engine
+ required_access = list(access_engine)
+ door_name = "engine external access"
+ icon_state = "2x2_N_to_S_leftdoors"
+ door_type = /obj/machinery/door/airlock/external
+ one_door_interior = DOOR_NORMAL_PLACEMENT
+ one_door_exterior = DOOR_NORMAL_PLACEMENT
+/obj/effect/spawner/airlock/long/square/engine/reversed
+ icon_state = "2x2_N_to_S_rightdoors"
+ one_door_interior = DOOR_FLIPPED_PLACEMENT
+ one_door_exterior = DOOR_FLIPPED_PLACEMENT
+
+/obj/effect/spawner/airlock/w_to_e/long/square/wide/mining
+ door_name = "mining external access"
+ required_access = list(access_mining)
+/obj/effect/spawner/airlock/long/square/wide/mining
+ door_name = "mining external access"
+ required_access = list(access_mining)
+
+/obj/effect/spawner/airlock/e_to_w/minisat
+ door_name = "minisat external access"
+ required_access = list(access_minisat)
+/obj/effect/spawner/airlock/long/square/e_to_s/telecoms
+ door_name = "telecoms external access"
+ required_access = list(access_tcomsat, access_external_airlocks)
+ door_type = /obj/machinery/door/airlock/external
+
+/obj/effect/spawner/airlock/long/square/three/syndicate
+ name = "3 by 3 square airlock spawner (interior west, exterior north)"
+ icon_state = "3x3_W_to_N"
+ interior_direction = WEST
+ exterior_direction = NORTH
+ door_name = "ship external access"
+ req_access = list(access_syndicate)
+ door_type = /obj/machinery/door/airlock/external
+
+#undef HALF_X
+#undef HALF_Y
+#undef CHAMBER_LONG
+#undef CHAMBER_SQUARE
+#undef CHAMBER_BIGGER
+#undef DOOR_NORMAL_PLACEMENT
+#undef DOOR_FLIPPED_PLACEMENT
+#undef AIRPUMP_TAG
+#undef SENSOR_TAG
+#undef OUTER_DOOR_TAG
+#undef INNER_DOOR_TAG
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index 057c52a2a4c..4dcd2cbdd32 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -140,8 +140,8 @@
/obj/item/suppressor = 4,
/obj/item/clothing/under/chameleon = 2,
/obj/item/stamp/chameleon = 2,
- /obj/item/clothing/shoes/syndigaloshes = 5,
- /obj/item/clothing/mask/gas/voice = 2,
+ /obj/item/clothing/shoes/chameleon/noslip = 5,
+ /obj/item/clothing/mask/chameleon = 2,
/obj/item/dnascrambler = 1,
/obj/item/storage/backpack/satchel_flat = 2,
/obj/item/storage/toolbox/syndicate = 2,
@@ -242,7 +242,8 @@
/obj/item/gun/projectile/automatic/toy/pistol/enforcer = 50,
/obj/item/gun/projectile/shotgun/toy = 50,
/obj/item/gun/projectile/shotgun/toy/crossbow = 50,
- /obj/item/gun/projectile/shotgun/toy/tommygun = 50
+ /obj/item/gun/projectile/shotgun/toy/tommygun = 50,
+ /obj/item/gun/projectile/automatic/sniper_rifle/toy = 50
)
diff --git a/code/game/objects/effects/spawners/random_spawners.dm b/code/game/objects/effects/spawners/random_spawners.dm
index 18392256fb8..03e49c56a50 100644
--- a/code/game/objects/effects/spawners/random_spawners.dm
+++ b/code/game/objects/effects/spawners/random_spawners.dm
@@ -214,7 +214,7 @@
/obj/item/storage/pill_bottle/zoom = 1,
/obj/item/storage/pill_bottle/random_drug_bottle = 2,
/obj/item/storage/backpack/duffel/syndie/surgery = 1,
- /obj/item/clothing/shoes/syndigaloshes = 1,
+ /obj/item/clothing/shoes/chameleon/noslip = 1,
/obj/item/storage/belt/military = 1,
/obj/item/clothing/under/chameleon = 1,
/obj/item/storage/backpack/satchel_flat = 1,
@@ -279,7 +279,7 @@
/obj/item/clothing/glasses/thermal = 1,
/obj/item/chameleon = 1,
/obj/item/reagent_containers/hypospray/autoinjector/stimulants = 1,
- /obj/item/storage/box/syndie_kit/atmosgasgrenades = 1,
+ /obj/item/storage/box/syndie_kit/atmosn2ogrenades = 1,
/obj/item/grenade/plastic/x4 = 1)
diff --git a/code/game/objects/effects/spawners/windowspawner.dm b/code/game/objects/effects/spawners/windowspawner.dm
index 1034d31eb45..e19aa54fd7d 100644
--- a/code/game/objects/effects/spawners/windowspawner.dm
+++ b/code/game/objects/effects/spawners/windowspawner.dm
@@ -47,3 +47,8 @@
name = "reinforced plasma window spawner"
icon_state = "pwindow_spawner"
windowtospawn = /obj/structure/window/plasmareinforced
+
+/obj/effect/spawner/window/shuttle
+ name = "shuttle window spawner"
+ icon_state = "swindow_spawner"
+ windowtospawn = /obj/structure/window/shuttle
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index f0233bb0f9e..d4336aa6cf3 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -107,7 +107,7 @@
..()
pixel_x = rand(3,-3)
pixel_y = rand(3,-3)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/structure/spider/eggcluster/process()
amount_grown += rand(0,2)
@@ -140,10 +140,10 @@
..()
pixel_x = rand(6,-6)
pixel_y = rand(6,-6)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/structure/spider/spiderling/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
entry_vent = null
return ..()
diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm
index e8cd72b81e9..c1231e698fc 100644
--- a/code/game/objects/effects/step_triggers.dm
+++ b/code/game/objects/effects/step_triggers.dm
@@ -1,23 +1,43 @@
/* Simple object type, calls a proc when "stepped" on by something */
/obj/effect/step_trigger
- var/affect_ghosts = 0
- var/stopper = 1 // stops throwers
- invisibility = 101 // nope cant see this shit
- anchored = 1
+ var/affect_ghosts = FALSE
+ var/stopper = TRUE // stops throwers
+ var/mobs_only = FALSE
+ invisibility = INVISIBILITY_ABSTRACT // nope cant see this shit
+ anchored = TRUE
/obj/effect/step_trigger/proc/Trigger(var/atom/movable/A)
- return 0
+ return FALSE
-/obj/effect/step_trigger/Crossed(H as mob|obj)
- ..()
+/obj/effect/step_trigger/Crossed(var/H, oldloc)
+ . = ..()
if(!H)
return
- if(istype(H, /mob/dead/observer) && !affect_ghosts)
+ if(isobserver(H) && !affect_ghosts)
+ return
+ if(!ismob(H) && mobs_only)
return
Trigger(H)
+/obj/effect/step_trigger/singularity_act()
+ return
+/obj/effect/step_trigger/singularity_pull()
+ return
+
+/* Sends a message to mob when triggered*/
+
+/obj/effect/step_trigger/message
+ var/message //the message to give to the mob
+ var/once = 1
+ mobs_only = TRUE
+
+/obj/effect/step_trigger/message/Trigger(mob/M)
+ if(M.client)
+ to_chat(M, "[message]")
+ if(once)
+ qdel(src)
/* Tosses things in a certain direction */
@@ -30,57 +50,57 @@
var/nostop = 0 // if 1: will only be stopped by teleporters
var/list/affecting = list()
- Trigger(var/atom/A)
- if(!A || !istype(A, /atom/movable))
+/obj/effect/step_trigger/thrower/Trigger(atom/A)
+ if(!A || !ismovableatom(A))
+ return
+ var/atom/movable/AM = A
+ var/curtiles = 0
+ var/stopthrow = 0
+ for(var/obj/effect/step_trigger/thrower/T in orange(2, src))
+ if(AM in T.affecting)
return
- var/atom/movable/AM = A
- var/curtiles = 0
- var/stopthrow = 0
- for(var/obj/effect/step_trigger/thrower/T in orange(2, src))
- if(AM in T.affecting)
- return
- if(ismob(AM))
- var/mob/M = AM
- if(immobilize)
- M.canmove = 0
+ if(isliving(AM))
+ var/mob/living/M = AM
+ if(immobilize)
+ M.canmove = FALSE
- affecting.Add(AM)
- while(AM && !stopthrow)
- if(tiles)
- if(curtiles >= tiles)
- break
- if(AM.z != src.z)
+ affecting.Add(AM)
+ while(AM && !stopthrow)
+ if(tiles)
+ if(curtiles >= tiles)
break
+ if(AM.z != src.z)
+ break
- curtiles++
+ curtiles++
- sleep(speed)
+ sleep(speed)
- // Calculate if we should stop the process
- if(!nostop)
- for(var/obj/effect/step_trigger/T in get_step(AM, direction))
- if(T.stopper && T != src)
- stopthrow = 1
- else
- for(var/obj/effect/step_trigger/teleporter/T in get_step(AM, direction))
- if(T.stopper)
- stopthrow = 1
+ // Calculate if we should stop the process
+ if(!nostop)
+ for(var/obj/effect/step_trigger/T in get_step(AM, direction))
+ if(T.stopper && T != src)
+ stopthrow = 1
+ else
+ for(var/obj/effect/step_trigger/teleporter/T in get_step(AM, direction))
+ if(T.stopper)
+ stopthrow = 1
- if(AM)
- var/predir = AM.dir
- step(AM, direction)
- if(!facedir)
- AM.dir = predir
+ if(AM)
+ var/predir = AM.dir
+ step(AM, direction)
+ if(!facedir)
+ AM.setDir(predir)
- affecting.Remove(AM)
+ affecting.Remove(AM)
- if(ismob(AM))
- var/mob/M = AM
- if(immobilize)
- M.canmove = 1
+ if(isliving(AM))
+ var/mob/living/M = AM
+ if(immobilize)
+ M.canmove = TRUE
/* Stops things thrown by a thrower, doesn't do anything */
@@ -93,12 +113,11 @@
var/teleport_y = 0
var/teleport_z = 0
- Trigger(var/atom/movable/A)
- if(teleport_x && teleport_y && teleport_z)
+/obj/effect/step_trigger/teleporter/Trigger(atom/movable/A)
+ if(teleport_x && teleport_y && teleport_z)
- A.x = teleport_x
- A.y = teleport_y
- A.z = teleport_z
+ var/turf/T = locate(teleport_x, teleport_y, teleport_z)
+ A.forceMove(T)
/* Random teleporter, teleports atoms to locations ranging from teleport_x - teleport_x_offset, etc */
@@ -107,11 +126,73 @@
var/teleport_y_offset = 0
var/teleport_z_offset = 0
- Trigger(var/atom/movable/A)
- if(teleport_x && teleport_y && teleport_z)
- if(teleport_x_offset && teleport_y_offset && teleport_z_offset)
+/obj/effect/step_trigger/teleporter/random/Trigger(atom/movable/A)
+ if(teleport_x && teleport_y && teleport_z)
+ if(teleport_x_offset && teleport_y_offset && teleport_z_offset)
- A.x = rand(teleport_x, teleport_x_offset)
- A.y = rand(teleport_y, teleport_y_offset)
- A.z = rand(teleport_z, teleport_z_offset)
+ var/turf/T = locate(rand(teleport_x, teleport_x_offset), rand(teleport_y, teleport_y_offset), rand(teleport_z, teleport_z_offset))
+ if (T)
+ A.forceMove(T)
+/* Fancy teleporter, creates sparks and smokes when used */
+
+/obj/effect/step_trigger/teleport_fancy
+ var/locationx
+ var/locationy
+ var/uses = 1 //0 for infinite uses
+ var/entersparks = 0
+ var/exitsparks = 0
+ var/entersmoke = 0
+ var/exitsmoke = 0
+
+/obj/effect/step_trigger/teleport_fancy/Trigger(mob/M)
+ var/dest = locate(locationx, locationy, z)
+ M.Move(dest)
+
+ if(entersparks)
+ var/datum/effect_system/spark_spread/s = new
+ s.set_up(4, 1, src)
+ s.start()
+ if(exitsparks)
+ var/datum/effect_system/spark_spread/s = new
+ s.set_up(4, 1, dest)
+ s.start()
+
+ if(entersmoke)
+ var/datum/effect_system/smoke_spread/s = new
+ s.set_up(4, 1, src, 0)
+ s.start()
+ if(exitsmoke)
+ var/datum/effect_system/smoke_spread/s = new
+ s.set_up(4, 1, dest, 0)
+ s.start()
+
+ uses--
+ if(uses == 0)
+ qdel(src)
+
+/* Simple sound player, Mapper friendly! */
+
+/obj/effect/step_trigger/sound_effect
+ var/sound //eg. path to the sound, inside '' eg: 'growl.ogg'
+ var/volume = 100
+ var/freq_vary = 1 //Should the frequency of the sound vary?
+ var/extra_range = 0 // eg World.view = 7, extra_range = 1, 7+1 = 8, 8 turfs radius
+ var/happens_once = 0
+ var/triggerer_only = 0 //Whether the triggerer is the only person who hears this
+
+
+/obj/effect/step_trigger/sound_effect/Trigger(atom/movable/A)
+ var/turf/T = get_turf(A)
+
+ if(!T)
+ return
+
+ if(triggerer_only && ismob(A))
+ var/mob/B = A
+ B.playsound_local(T, sound, volume, freq_vary)
+ else
+ playsound(T, sound, volume, freq_vary, extra_range)
+
+ if(happens_once)
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/objects/effects/temporary_visuals/clockcult.dm b/code/game/objects/effects/temporary_visuals/clockcult.dm
index f6b654ccbbe..1dc126faa6c 100644
--- a/code/game/objects/effects/temporary_visuals/clockcult.dm
+++ b/code/game/objects/effects/temporary_visuals/clockcult.dm
@@ -6,6 +6,10 @@
randomdir = 0
layer = ABOVE_NORMAL_TURF_LAYER
+/obj/effect/temp_visual/ratvar/door
+ icon_state = "ratvardoorglow"
+ layer = CLOSED_DOOR_LAYER //above closed doors
+
/obj/effect/temp_visual/ratvar/door/window
icon_state = "ratvarwindoorglow"
layer = ABOVE_WINDOW_LAYER
@@ -16,9 +20,27 @@
/obj/effect/temp_visual/ratvar/beam/grille
layer = BELOW_OBJ_LAYER
+/obj/effect/temp_visual/ratvar/beam/itemconsume
+ layer = HIGH_OBJ_LAYER
+
+/obj/effect/temp_visual/ratvar/beam/falsewall
+ layer = OBJ_LAYER
+
+/obj/effect/temp_visual/ratvar/beam/catwalk
+ layer = LATTICE_LAYER
+
+/obj/effect/temp_visual/ratvar/wall
+ icon_state = "ratvarwallglow"
+
+/obj/effect/temp_visual/ratvar/wall/false
+ layer = OBJ_LAYER
+
/obj/effect/temp_visual/ratvar/floor
icon_state = "ratvarfloorglow"
+/obj/effect/temp_visual/ratvar/floor/catwalk
+ layer = LATTICE_LAYER
+
/obj/effect/temp_visual/ratvar/window
icon_state = "ratvarwindowglow"
layer = ABOVE_OBJ_LAYER
@@ -26,6 +48,10 @@
/obj/effect/temp_visual/ratvar/window/single
icon_state = "ratvarwindowglow_s"
+/obj/effect/temp_visual/ratvar/gear
+ icon_state = "ratvargearglow"
+ layer = BELOW_OBJ_LAYER
+
/obj/effect/temp_visual/ratvar/grille
icon_state = "ratvargrilleglow"
layer = BELOW_OBJ_LAYER
diff --git a/code/game/objects/effects/temporary_visuals/cult.dm b/code/game/objects/effects/temporary_visuals/cult.dm
index 8edb88a7e79..7a12caf6b10 100644
--- a/code/game/objects/effects/temporary_visuals/cult.dm
+++ b/code/game/objects/effects/temporary_visuals/cult.dm
@@ -37,4 +37,5 @@
/obj/effect/temp_visual/cult/turf/open/floor
icon_state = "floorglow"
- duration = 5
\ No newline at end of file
+ duration = 5
+ plane = FLOOR_PLANE
\ No newline at end of file
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 880043c8be6..8fd1c061c32 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -228,4 +228,65 @@
randomdir = FALSE
pixel_y = -16
pixel_x = -16
- duration = 20
\ No newline at end of file
+ duration = 20
+
+/obj/effect/temp_visual/bleed
+ name = "bleed"
+ icon = 'icons/effects/bleed.dmi'
+ icon_state = "bleed0"
+ duration = 10
+ var/shrink = TRUE
+
+/obj/effect/temp_visual/bleed/Initialize(mapload, atom/size_calc_target)
+ . = ..()
+ var/size_matrix = matrix()
+ if(size_calc_target)
+ layer = size_calc_target.layer + 0.01
+ var/icon/I = icon(size_calc_target.icon, size_calc_target.icon_state, size_calc_target.dir)
+ size_matrix = matrix() * (I.Height()/world.icon_size)
+ transform = size_matrix //scale the bleed overlay's size based on the target's icon size
+ var/matrix/M = transform
+ if(shrink)
+ M = size_matrix * 0.1
+ else
+ M = size_matrix * 2
+ animate(src, alpha = 20, transform = M, time = duration, flags = ANIMATION_PARALLEL)
+
+/obj/effect/temp_visual/bleed/explode
+ icon_state = "bleed10"
+ duration = 12
+ shrink = FALSE
+
+/obj/effect/temp_visual/small_smoke
+ icon_state = "smoke"
+ duration = 50
+
+/obj/effect/temp_visual/small_smoke/halfsecond
+ duration = 5
+
+/obj/effect/temp_visual/dir_setting/firing_effect
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "firing_effect"
+ duration = 2
+
+/obj/effect/temp_visual/dir_setting/firing_effect/setDir(newdir)
+ switch(newdir)
+ if(NORTH)
+ layer = BELOW_MOB_LAYER
+ pixel_x = rand(-3,3)
+ pixel_y = rand(4,6)
+ if(SOUTH)
+ pixel_x = rand(-3,3)
+ pixel_y = rand(-1,1)
+ else
+ pixel_x = rand(-1,1)
+ pixel_y = rand(-1,1)
+ ..()
+
+/obj/effect/temp_visual/dir_setting/firing_effect/energy
+ icon_state = "firing_effect_energy"
+ duration = 3
+
+/obj/effect/temp_visual/dir_setting/firing_effect/magic
+ icon_state = "shieldsparkles"
+ duration = 3
\ No newline at end of file
diff --git a/code/game/objects/effects/temporary_visuals/temporary_visual.dm b/code/game/objects/effects/temporary_visuals/temporary_visual.dm
index bb6cca92644..23b1aaa0d2e 100644
--- a/code/game/objects/effects/temporary_visuals/temporary_visual.dm
+++ b/code/game/objects/effects/temporary_visuals/temporary_visual.dm
@@ -1,16 +1,23 @@
//temporary visual effects
/obj/effect/temp_visual
- anchored = 1
+ icon_state = "nothing"
+ anchored = TRUE
layer = ABOVE_MOB_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- var/duration = 10
+ var/duration = 10 //in deciseconds
var/randomdir = TRUE
+ var/timerid
-/obj/effect/temp_visual/New()
+/obj/effect/temp_visual/Initialize(mapload)
+ . = ..()
if(randomdir)
setDir(pick(cardinal))
- QDEL_IN(src, duration)
+ timerid = QDEL_IN(src, duration)
+
+/obj/effect/temp_visual/Destroy()
+ . = ..()
+ deltimer(timerid)
/obj/effect/temp_visual/singularity_act()
return
@@ -24,7 +31,7 @@
/obj/effect/temp_visual/dir_setting
randomdir = FALSE
-/obj/effect/temp_visual/dir_setting/New(loc, set_dir)
+/obj/effect/temp_visual/dir_setting/Initialize(mapload, set_dir)
if(set_dir)
setDir(set_dir)
- ..()
\ No newline at end of file
+ . = ..()
diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm
index 1e026e90e02..cec5b6e1fc8 100644
--- a/code/game/objects/empulse.dm
+++ b/code/game/objects/empulse.dm
@@ -5,8 +5,8 @@
epicenter = get_turf(epicenter.loc)
if(log)
- message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])": ] [ADMIN_COORDJMP(epicenter)]")
- log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ] [COORD(epicenter)]")
+ message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])": ""] [ADMIN_COORDJMP(epicenter)]")
+ log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ""] [COORD(epicenter)]")
if(heavy_range > 1)
new/obj/effect/temp_visual/emp/pulse(epicenter)
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index 9c457e43b6a..87f489513d2 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -1,6 +1,6 @@
//TODO: Flash range does nothing currently
-/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0 ,silent = 0, smoke = 1, cause = null, breach = TRUE)
+/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0, silent = 0, smoke = 1, cause = null, breach = TRUE)
src = null //so we don't abort once src is deleted
epicenter = get_turf(epicenter)
@@ -25,8 +25,8 @@
var/list/cached_exp_block = list()
if(adminlog)
- message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ] [ADMIN_COORDJMP(epicenter)] ")
- log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ] [COORD(epicenter)] ")
+ message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ""] [ADMIN_COORDJMP(epicenter)] ")
+ log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ""] [COORD(epicenter)] ")
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
// Stereo users will also hear the direction of the explosion!
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 3d8548ad11c..9dbb02553ca 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -16,6 +16,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
var/inhand_y_dimension = 32
can_be_hit = FALSE
+ suicidal_hands = TRUE
var/r_speed = 1.0
var/health = null
@@ -88,7 +89,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
var/list/sprite_sheets = null
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
var/sprite_sheets_obj = null //Used to override hardcoded clothing inventory object dmis in human clothing proc.
- var/list/species_fit = null //This object has a different appearance when worn by these species
var/trip_verb = TV_TRIP
var/trip_chance = 0
@@ -99,6 +99,10 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
var/trip_walksafe = TRUE
var/trip_tiles = 0
+ //Tooltip vars
+ var/in_inventory = FALSE //is this item equipped into an inventory slot or hand of a mob?
+ var/tip_timer = 0
+
/obj/item/New()
..()
for(var/path in actions_types)
@@ -145,15 +149,9 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
/obj/item/blob_act()
qdel(src)
-//user: The mob that is suiciding
-//damagetype: The type of damage the item will inflict on the user
-//BRUTELOSS = 1
-//FIRELOSS = 2
-//TOXLOSS = 4
-//OXYLOSS = 8
-//Output a creative message and then return the damagetype done
-/obj/item/proc/suicide_act(mob/user)
- return
+/obj/item/water_act(volume, temperature, source, method = TOUCH)
+ . = ..()
+ extinguish()
/obj/item/verb/move_to_top()
set name = "Move To Top"
@@ -258,7 +256,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
add_fingerprint(user)
if(pickup(user)) // Pickup succeeded
user.put_in_active_hand(src)
-
+
return 1
/obj/item/attack_alien(mob/user as mob)
@@ -349,11 +347,13 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
A.Remove(user)
if(flags & DROPDEL)
qdel(src)
+ in_inventory = FALSE
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user)
// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
+ in_inventory = TRUE
return TRUE
// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
@@ -383,6 +383,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
var/datum/action/A = X
if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
+ in_inventory = TRUE
/obj/item/proc/item_action_slot_check(slot, mob/user)
return 1
@@ -541,6 +542,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
if(callback) //call the original callback
. = callback.Invoke()
throw_speed = initial(throw_speed) //explosions change this.
+ in_inventory = FALSE
/obj/item/proc/pwr_drain()
return 0 // Process Kill
@@ -576,7 +578,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
/obj/item/proc/is_equivalent(obj/item/I)
return I == src
-/obj/item/Crossed(atom/movable/AM)
+/obj/item/Crossed(atom/movable/AM, oldloc)
. = ..()
if(prob(trip_chance) && ishuman(AM))
var/mob/living/carbon/human/H = AM
@@ -589,9 +591,46 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
/obj/item/attack_hulk(mob/living/carbon/human/user)
return FALSE
-/obj/item/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user) //handles block for CQC
- if(target.check_block())
- target.visible_message("[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!",
- "You block the attack!")
- user.Stun(2)
- return TRUE
+/obj/item/proc/openTip(location, control, params, user)
+ openToolTip(user, src, params, title = name, content = "[desc]", theme = "")
+
+/obj/item/MouseEntered(location, control, params)
+ if(in_inventory)
+ var/timedelay = 8
+ var/user = usr
+ tip_timer = addtimer(CALLBACK(src, .proc/openTip, location, control, params, user), timedelay, TIMER_STOPPABLE)
+
+/obj/item/MouseExited()
+ deltimer(tip_timer) //delete any in-progress timer if the mouse is moved off the item before it finishes
+ closeToolTip(usr)
+
+/obj/item/proc/update_slot_icon()
+ if(!ismob(loc))
+ return
+ var/mob/owner = loc
+ var/flags = slot_flags
+ if(flags & SLOT_OCLOTHING)
+ owner.update_inv_wear_suit()
+ if(flags & SLOT_ICLOTHING)
+ owner.update_inv_w_uniform()
+ if(flags & SLOT_GLOVES)
+ owner.update_inv_gloves()
+ if(flags & SLOT_EYES)
+ owner.update_inv_glasses()
+ if(flags & SLOT_EARS)
+ owner.update_inv_ears()
+ if(flags & SLOT_MASK)
+ owner.update_inv_wear_mask()
+ if(flags & SLOT_HEAD)
+ owner.update_inv_head()
+ if(flags & SLOT_FEET)
+ owner.update_inv_shoes()
+ if(flags & SLOT_ID)
+ owner.update_inv_wear_id()
+ if(flags & SLOT_BELT)
+ owner.update_inv_belt()
+ if(flags & SLOT_BACK)
+ owner.update_inv_back()
+ if(flags & SLOT_PDA)
+ owner.update_inv_wear_pda()
+
diff --git a/code/game/objects/items/ashtray.dm b/code/game/objects/items/ashtray.dm
index b32176cb155..8e85709ef97 100644
--- a/code/game/objects/items/ashtray.dm
+++ b/code/game/objects/items/ashtray.dm
@@ -28,7 +28,6 @@
var/obj/item/clothing/mask/cigarette/cig = W
if(cig.lit == 1)
src.visible_message("[user] crushes [cig] in [src], putting it out.")
- processing_objects.Remove(cig)
var/obj/item/butt = new cig.type_butt(src)
cig.transfer_fingerprints_to(butt)
qdel(cig)
diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm
index 3ce114bde9b..a566f208082 100644
--- a/code/game/objects/items/blueprints.dm
+++ b/code/game/objects/items/blueprints.dm
@@ -65,8 +65,8 @@
/obj/item/areaeditor/permit/create_area()
- ..()
- qdel(src)
+ if(..())
+ qdel(src)
//free golem blueprints, like permit but can claim as much as needed
@@ -174,14 +174,10 @@
var/list/SPECIALS = list(
/area/shuttle,
/area/admin,
- /area/arrival,
/area/centcom,
/area/asteroid,
/area/tdome,
- /area/syndicate_station,
- /area/wizard_station,
- /area/prison
- // /area/derelict //commented out, all hail derelict-rebuilders!
+ /area/wizard_station
)
for(var/type in SPECIALS)
if( istype(A,type) )
@@ -190,43 +186,43 @@
/obj/item/areaeditor/proc/create_area()
+ var/area_created = FALSE
var/res = detect_room(get_turf(usr))
if(!istype(res,/list))
switch(res)
if(ROOM_ERR_SPACE)
to_chat(usr, "The new area must be completely airtight.")
- return
+ return area_created
if(ROOM_ERR_TOOLARGE)
to_chat(usr, "The new area is too large.")
- return
+ return area_created
else
to_chat(usr, "Error! Please notify administration.")
- return
+ return area_created
var/list/turf/turfs = res
var/str = trim(stripped_input(usr,"New area name:", "Blueprint Editing", "", MAX_NAME_LEN))
if(!str || !length(str)) //cancel
- return
+ return area_created
if(length(str) > 50)
to_chat(usr, "The given name is too long. The area remains undefined.")
- return
+ return area_created
var/area/A = new
A.name = str
- //var/ma
- //ma = A.master ? "[A.master]" : "(null)"
-// to_chat(world, "DEBUG: create_area: A.name=[A.name] A.tag=[A.tag] A.master=[ma]")
- A.power_equip = 0
- A.power_light = 0
- A.power_environ = 0
- A.always_unpowered = 0
- move_turfs_to_area(turfs, A)
+ A.power_equip = FALSE
+ A.power_light = FALSE
+ A.power_environ = FALSE
+ A.always_unpowered = FALSE
+ A.set_dynamic_lighting()
+
+ for(var/i in 1 to turfs.len)
+ var/turf/thing = turfs[i]
+ var/area/old_area = thing.loc
+ A.contents += thing
+ thing.change_area(old_area, A)
interact()
- return
-
-
-/obj/item/areaeditor/proc/move_turfs_to_area(var/list/turf/turfs, var/area/A)
- A.contents.Add(turfs)
-
+ area_created = TRUE
+ return area_created
/obj/item/areaeditor/proc/edit_area()
var/area/A = get_area()
diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm
index 85780484264..5ea13308de5 100644
--- a/code/game/objects/items/candle.dm
+++ b/code/game/objects/items/candle.dm
@@ -18,7 +18,7 @@
light(show_message = 0)
/obj/item/candle/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/candle/update_icon()
@@ -62,7 +62,7 @@
if(show_message)
usr.visible_message(show_message)
set_light(CANDLE_LUM)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
update_icon()
diff --git a/code/game/objects/items/contraband.dm b/code/game/objects/items/contraband.dm
index 7ce7b07193d..77aef9bb71d 100644
--- a/code/game/objects/items/contraband.dm
+++ b/code/game/objects/items/contraband.dm
@@ -4,6 +4,7 @@
/obj/item/storage/pill_bottle/happy
name = "Happy pills"
desc = "Highly illegal drug. When you want to see the rainbow."
+ wrapper_color = COLOR_PINK
/obj/item/storage/pill_bottle/happy/New()
..()
@@ -18,6 +19,7 @@
/obj/item/storage/pill_bottle/zoom
name = "Zoom pills"
desc = "Highly illegal drug. Trade brain for speed."
+ wrapper_color = COLOR_BLUE
/obj/item/storage/pill_bottle/zoom/New()
..()
@@ -49,15 +51,12 @@
adulterants--
reagents.add_reagent(pick_list("chemistry_tools.json", "CYBERPUNK_drug_adulterants"), 3)
-
-
/obj/item/storage/pill_bottle/random_drug_bottle
name = "pill bottle (???)"
desc = "Huh."
+ allow_wrap = FALSE
/obj/item/storage/pill_bottle/random_drug_bottle/New()
..()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/food/pill/random_drugs(src)
-
-
diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm
index 05d9d4389ad..a80352c01ba 100644
--- a/code/game/objects/items/control_wand.dm
+++ b/code/game/objects/items/control_wand.dm
@@ -50,6 +50,7 @@
to_chat(user, "[D]'s ID scan is disabled!")
return
if(D.check_access(src.ID))
+ D.add_hiddenprint(user)
switch(mode)
if(WAND_OPEN)
if(D.density)
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index b4dd66e3be5..926da3d28cb 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -23,7 +23,7 @@
/obj/item/toy/crayon/suicide_act(mob/user)
user.visible_message("[user] is jamming the [name] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide.")
- return (BRUTELOSS|OXYLOSS)
+ return BRUTELOSS|OXYLOSS
/obj/item/toy/crayon/New()
..()
diff --git a/code/game/objects/items/dehy_carp.dm b/code/game/objects/items/dehy_carp.dm
index 3125c24837a..fb59b24aeda 100644
--- a/code/game/objects/items/dehy_carp.dm
+++ b/code/game/objects/items/dehy_carp.dm
@@ -22,6 +22,10 @@
owned = 0
return ..()
+/obj/item/toy/carpplushie/dehy_carp/water_act(volume, temperature, source, method = TOUCH)
+ . = ..()
+ if(volume >= 1)
+ Swell()
/obj/item/toy/carpplushie/dehy_carp/afterattack(obj/O, mob/user,proximity)
if(!proximity) return
@@ -37,7 +41,7 @@
visible_message("[src] swells up!")
// Animation
- icon = 'icons/mob/animal.dmi'
+ icon = 'icons/mob/carp.dmi'
flick("carp_swell", src)
// Wait for animation to end
sleep(6)
diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm
index 575ce0cb6d6..7bf80244072 100644
--- a/code/game/objects/items/devices/camera_bug.dm
+++ b/code/game/objects/items/devices/camera_bug.dm
@@ -32,7 +32,7 @@
/obj/item/camera_bug/New()
..()
- processing_objects += src
+ START_PROCESSING(SSobj, src)
/obj/item/camera_bug/Destroy()
get_cameras()
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index 27132b75346..5fa2bd692e0 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -227,7 +227,7 @@
return PROCESS_KILL
/obj/item/borg_chameleon/proc/activate(mob/living/silicon/robot/syndicate/saboteur/user)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
S = user
user.base_icon = disguise
user.icon_state = disguise
@@ -236,7 +236,7 @@
user.update_icons()
/obj/item/borg_chameleon/proc/deactivate(mob/living/silicon/robot/syndicate/saboteur/user)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
S = user
user.base_icon = initial(user.base_icon)
user.icon_state = initial(user.icon_state)
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index d0b8637b280..a618383a819 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -155,14 +155,14 @@
/obj/item/flash/proc/terrible_conversion_proc(mob/M, mob/user)
if(ishuman(M) && ishuman(user) && M.stat != DEAD)
- if(user.mind && (user.mind in ticker.mode.head_revolutionaries))
+ if(user.mind && (user.mind in SSticker.mode.head_revolutionaries))
if(M.client)
if(M.stat == CONSCIOUS)
M.mind_initialize() //give them a mind datum if they don't have one.
var/resisted
if(!ismindshielded(M))
- if(user.mind in ticker.mode.head_revolutionaries)
- if(ticker.mode.add_revolutionary(M.mind))
+ if(user.mind in SSticker.mode.head_revolutionaries)
+ if(SSticker.mode.add_revolutionary(M.mind))
times_used -- //Flashes less likely to burn out for headrevs when used for conversion
else
resisted = 1
@@ -207,10 +207,10 @@
/obj/item/flash/cameraflash/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/flash/cameraflash/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/flash/cameraflash/process() //this and the two parts above are part of the charge system.
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 24c8cbcd3b7..74f98a9384a 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -51,7 +51,7 @@
if(((CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly
return ..() //just hit them in the head
- if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") //don't have dexterity
+ if(!(istype(user, /mob/living/carbon/human) || SSticker) && SSticker.mode.name != "monkey") //don't have dexterity
to_chat(user, "You don't have the dexterity to do this!")
return
@@ -76,7 +76,7 @@
var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes)
if(M.stat == DEAD || !eyes || M.disabilities & BLIND) //mob is dead or fully blind
to_chat(user, "[M]'s pupils are unresponsive to the light!")
- else if((XRAY in M.mutations) || eyes.get_dark_view() >= 8) //The mob's either got the X-RAY vision or has a tapetum lucidum (extreme nightvision, i.e. Vulp/Tajara with COLOURBLIND & their monkey forms).
+ else if((XRAY in M.mutations) || eyes.see_in_dark >= 8) //The mob's either got the X-RAY vision or has a tapetum lucidum (extreme nightvision, i.e. Vulp/Tajara with COLOURBLIND & their monkey forms).
to_chat(user, "[M]'s pupils glow eerily!")
else //they're okay!
if(M.flash_eyes(visual = 1))
@@ -183,10 +183,10 @@
turn_off()
if(!fuel)
src.icon_state = "[initial(icon_state)]-empty"
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
/obj/item/flashlight/flare/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/flashlight/flare/proc/turn_off()
@@ -222,7 +222,7 @@
user.visible_message("[user] activates [src].", "You activate [src].")
src.force = on_damage
src.damtype = "fire"
- processing_objects += src
+ START_PROCESSING(SSobj, src)
// GLOWSTICKS
@@ -292,10 +292,10 @@
color = null
/obj/item/flashlight/flare/glowstick/random/Initialize()
- ..()
+ . = ..()
var/T = pick(typesof(/obj/item/flashlight/flare/glowstick) - /obj/item/flashlight/flare/glowstick/random - /obj/item/flashlight/flare/glowstick/emergency)
new T(loc)
- return INITIALIZE_HINT_QDEL
+ qdel(src) // return INITIALIZE_HINT_QDEL <-- Doesn't work
/obj/item/flashlight/flare/extinguish_light()
visible_message("[src] dims slightly before scattering the shadows around it.")
@@ -307,6 +307,9 @@
brightness_on = 7
icon_state = "torch"
item_state = "torch"
+ lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/items_righthand.dmi'
+ light_color = LIGHT_COLOR_ORANGE
on_damage = 10
/obj/item/flashlight/slime
@@ -344,10 +347,10 @@
/obj/item/flashlight/emp/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/flashlight/emp/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/flashlight/emp/process()
diff --git a/code/game/objects/items/devices/handheld_defib.dm b/code/game/objects/items/devices/handheld_defib.dm
new file mode 100644
index 00000000000..199aaf43737
--- /dev/null
+++ b/code/game/objects/items/devices/handheld_defib.dm
@@ -0,0 +1,91 @@
+/obj/item/handheld_defibrillator
+ name = "handheld defibrillator"
+ desc = "Used to restart stopped hearts."
+ icon = 'icons/goonstation/objects/objects.dmi'
+ lefthand_file = 'icons/goonstation/mob/inhands/items_lefthand.dmi'
+ righthand_file = 'icons/goonstation/mob/inhands/items_righthand.dmi'
+ icon_state = "defib-on"
+ item_state = "defib"
+
+ var/icon_base = "defib"
+ var/cooldown = FALSE
+ var/charge_time = 100
+ var/emagged = FALSE
+
+/obj/item/handheld_defibrillator/emag_act(mob/user)
+ if(!emagged)
+ emagged = TRUE
+ desc += " The screen only shows the word KILL flashing over and over."
+ if(user)
+ to_chat(user, "you short out the safeties on [src]")
+ else
+ emagged = FALSE
+ desc = "Used to restart stopped hearts."
+ if(user)
+ to_chat(user, "You restore the safeties on [src]")
+
+/obj/item/handheld_defibrillator/emp_act(severity)
+ if(emagged)
+ emagged = FALSE
+ desc = "Used to restart stopped hearts."
+ visible_message("[src] beeps: Safety protocols enabled!")
+ playsound(get_turf(src), 'sound/machines/defib_saftyon.ogg', 50, 0)
+ else
+ emagged = TRUE
+ desc += " The screen only shows the word KILL flashing over and over."
+ visible_message("[src] beeps: Safety protocols disabled!")
+ playsound(get_turf(src), 'sound/machines/defib_saftyoff.ogg', 50, 0)
+
+/obj/item/handheld_defibrillator/attack(mob/living/carbon/human/H, mob/user)
+ if(!istype(H))
+ return ..()
+
+ if(cooldown)
+ to_chat(user, "[src] is still charging!")
+ return
+
+ if(emagged || (H.health <= HEALTH_THRESHOLD_CRIT) || (H.undergoing_cardiac_arrest()))
+ user.visible_message("[user] shocks [H] with [src].", "You shock [H] with [src].")
+ add_attack_logs(user, H, "defibrillated with [src]")
+ playsound(user.loc, "sound/weapons/Egloves.ogg", 75, 1)
+
+ if(H.stat == DEAD)
+ to_chat(user, "[H] doesn't respond at all!")
+ else
+ H.set_heartattack(FALSE)
+ var/total_damage = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss()
+ if(H.health <= HEALTH_THRESHOLD_CRIT)
+ if(total_damage >= 90)
+ to_chat(user, "[H] looks horribly injured. Resuscitation alone may not help revive them.")
+ if(prob(66))
+ to_chat(user, "[H] inhales deeply!")
+ H.adjustOxyLoss(-50)
+ else
+ to_chat(user, "[H] doesn't respond!")
+
+ H.AdjustParalysis(3)
+ H.AdjustStunned(5)
+ H.AdjustWeakened(5)
+ H.AdjustStuttering(10)
+ to_chat(H, "You feel a powerful jolt!")
+ H.shock_internal_organs(100)
+
+ if(emagged && prob(10))
+ to_chat(user, "[src]'s on board scanner indicates that the target is undergoing a cardiac arrest!")
+ H.set_heartattack(TRUE)
+
+ cooldown = TRUE
+ icon_state = "[icon_base]-shock"
+ addtimer(CALLBACK(src, .proc/short_charge), 10)
+ addtimer(CALLBACK(src, .proc/recharge), charge_time)
+
+ else
+ to_chat(user, "[src]'s on board medical scanner indicates that no shock is required.")
+
+/obj/item/handheld_defibrillator/proc/short_charge()
+ icon_state = "[icon_base]-off"
+
+/obj/item/handheld_defibrillator/proc/recharge()
+ cooldown = FALSE
+ icon_state = "[icon_base]-on"
+ playsound(loc, "sound/weapons/flash.ogg", 75, 1)
\ No newline at end of file
diff --git a/code/game/objects/items/devices/instruments.dm b/code/game/objects/items/devices/instruments.dm
index 840d5e64395..6d3a1c2b49d 100644
--- a/code/game/objects/items/devices/instruments.dm
+++ b/code/game/objects/items/devices/instruments.dm
@@ -19,7 +19,7 @@
/obj/item/instrument/suicide_act(mob/user)
user.visible_message("[user] begins to play 'Gloomy Sunday'! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/instrument/Initialize(mapload)
song.tempo = song.sanitize_tempo(song.tempo) // tick_lag isn't set when the map is loaded
diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm
index 32b548c38aa..43b22eb4979 100644
--- a/code/game/objects/items/devices/laserpointer.dm
+++ b/code/game/objects/items/devices/laserpointer.dm
@@ -167,7 +167,7 @@
if(energy <= max_energy)
if(!recharging)
recharging = 1
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
if(energy <= 0)
to_chat(user, "You've overused the battery of [src], now it needs time to recharge!")
recharge_locked = 1
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 59a7a650383..941e90a31ef 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -35,7 +35,7 @@
return
if(H.mind)
span = H.mind.speech_span
- if((COMIC in H.mutations) || H.get_int_organ(/obj/item/organ/internal/cyberimp/brain/clown_voice) || istype(H.get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown))
+ if((COMIC in H.mutations) || H.get_int_organ(/obj/item/organ/internal/cyberimp/brain/clown_voice))
span = "sans"
if(spamcheck)
to_chat(user, "\The [src] needs to recharge!")
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index d142136ed23..62fc36863fc 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -47,10 +47,10 @@
/obj/item/multitool/ai_detect/New()
..()
- processing_objects += src
+ START_PROCESSING(SSobj, src)
/obj/item/multitool/ai_detect/Destroy()
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/multitool/ai_detect/process()
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index 0d0475df8ee..562800c2ce0 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -1,3 +1,7 @@
+#define DISCONNECTED 0
+#define CLAMPED_OFF 1
+#define OPERATING 2
+
// Powersink - used to drain station power
/obj/item/powersink
@@ -13,28 +17,55 @@
throw_range = 2
materials = list(MAT_METAL=750)
origin_tech = "powerstorage=5;syndicate=5"
- var/drain_rate = 1600000 // amount of power to drain per tick
- var/apc_drain_rate = 50 // Max. amount drained from single APC. In Watts.
- var/dissipation_rate = 20000 // Passive dissipation of drained power. In Watts.
- var/power_drained = 0 // Amount of power drained.
- var/max_power = 1e10 // Detonation point.
- var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
- var/drained_this_tick = 0 // This is unfortunately necessary to ensure we process powersinks BEFORE other machinery such as APCs.
- var/admins_warned = 0 // stop spam, only warn the admins once that we are about to go boom
+ var/drain_rate = 2000000 // amount of power to drain per tick
+ var/power_drained = 0 // has drained this much power
+ var/max_power = 6e8 // maximum power that can be drained before exploding
+ var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
+ var/admins_warned = FALSE // stop spam, only warn the admins once that we are about to boom
- var/datum/powernet/PN // Our powernet
var/obj/structure/cable/attached // the attached cable
/obj/item/powersink/Destroy()
- processing_objects.Remove(src)
- GLOB.processing_power_items.Remove(src)
- PN = null
+ STOP_PROCESSING(SSobj, src)
attached = null
return ..()
-/obj/item/powersink/attackby(var/obj/item/I, var/mob/user)
- if(istype(I, /obj/item/screwdriver))
- if(mode == 0)
+/obj/item/powersink/update_icon()
+ icon_state = "powersink[mode == OPERATING]"
+
+/obj/item/powersink/proc/set_mode(value)
+ if(value == mode)
+ return
+ switch(value)
+ if(DISCONNECTED)
+ attached = null
+ if(mode == OPERATING)
+ STOP_PROCESSING(SSobj, src)
+ anchored = FALSE
+ density = FALSE
+
+ if(CLAMPED_OFF)
+ if(!attached)
+ return
+ if(mode == OPERATING)
+ STOP_PROCESSING(SSobj, src)
+ anchored = TRUE
+ density = TRUE
+
+ if(OPERATING)
+ if(!attached)
+ return
+ START_PROCESSING(SSobj, src)
+ anchored = TRUE
+ density = TRUE
+
+ mode = value
+ update_icon()
+ set_light(0)
+
+/obj/item/powersink/attackby(obj/item/I, mob/user)
+ if(isscrewdriver(I))
+ if(mode == DISCONNECTED)
var/turf/T = loc
if(isturf(T) && !T.intact)
attached = locate() in T
@@ -42,98 +73,81 @@
to_chat(user, "No exposed cable here to attach to.")
return
else
- anchored = 1
- mode = 1
- src.visible_message("[user] attaches [src] to the cable!")
+ set_mode(CLAMPED_OFF)
+ visible_message("[user] attaches [src] to the cable!")
message_admins("Power sink activated by [key_name_admin(user)] at ([x],[y],[z] - JMP)")
log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])")
- return
else
to_chat(user, "Device must be placed over an exposed cable to attach to it.")
- return
else
- if(mode == 2)
- processing_objects.Remove(src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite
- GLOB.processing_power_items.Remove(src)
- anchored = 0
- mode = 0
+ set_mode(DISCONNECTED)
src.visible_message("[user] detaches [src] from the cable!")
- set_light(0)
- icon_state = "powersink0"
-
- return
else
- ..()
+ return ..()
/obj/item/powersink/attack_ai()
return
/obj/item/powersink/attack_hand(var/mob/user)
switch(mode)
- if(0)
+ if(DISCONNECTED)
..()
- if(1)
- src.visible_message("[user] activates [src]!")
- mode = 2
- icon_state = "powersink1"
- processing_objects.Add(src)
- GLOB.processing_power_items.Add(src)
- if(2) //This switch option wasn't originally included. It exists now. --NeoFite
- src.visible_message("[user] deactivates [src]!")
- mode = 1
- set_light(0)
- icon_state = "powersink0"
- processing_objects.Remove(src)
- GLOB.processing_power_items.Remove(src)
-
-/obj/item/powersink/pwr_drain()
- if(!attached)
- return 0
-
- if(drained_this_tick)
- return 1
- drained_this_tick = 1
-
- var/drained = 0
-
- if(!PN)
- return 1
-
- set_light(12)
- PN.trigger_warning()
- // found a powernet, so drain up to max power from it
- drained = PN.draw_power(drain_rate)
- // if tried to drain more than available on powernet
- // now look for APCs and drain their cells
- if(drained < drain_rate)
- for(var/obj/machinery/power/terminal/T in PN.nodes)
- // Enough power drained this tick, no need to torture more APCs
- if(drained >= drain_rate)
- break
- if(istype(T.master, /obj/machinery/power/apc))
- var/obj/machinery/power/apc/A = T.master
- if(A.operating && A.cell)
- A.cell.charge = max(0, A.cell.charge - apc_drain_rate)
- drained += apc_drain_rate
- if(A.charging == 2) // If the cell was full
- A.charging = 1 // It's no longer full
- power_drained += drained
- return 1
+ if(CLAMPED_OFF)
+ user.visible_message( \
+ "[user] activates \the [src]!", \
+ "You activate \the [src].",
+ "You hear a click.")
+ message_admins("Power sink activated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_VERBOSEJMP(src)]")
+ log_game("Power sink activated by [key_name(user)] at [AREACOORD(src)]")
+ set_mode(OPERATING)
+ if(OPERATING)
+ user.visible_message( \
+ "[user] deactivates \the [src]!", \
+ "You deactivate \the [src].",
+ "You hear a click.")
+ set_mode(CLAMPED_OFF)
/obj/item/powersink/process()
- drained_this_tick = 0
- power_drained -= min(dissipation_rate, power_drained)
+ if(!attached)
+ set_mode(DISCONNECTED)
+ return
+
+ var/datum/powernet/PN = attached.powernet
+ if(PN)
+ set_light(5)
+
+ // found a powernet, so drain up to max power from it
+
+ var/drained = min (drain_rate, attached.newavail())
+ attached.add_delayedload(drained)
+ power_drained += drained
+
+ // if tried to drain more than available on powernet
+ // now look for APCs and drain their cells
+ if(drained < drain_rate)
+ for(var/obj/machinery/power/terminal/T in PN.nodes)
+ if(istype(T.master, /obj/machinery/power/apc))
+ var/obj/machinery/power/apc/A = T.master
+ if(A.operating && A.cell)
+ A.cell.charge = max(0, A.cell.charge - 50)
+ power_drained += 50
+ if(A.charging == 2) // If the cell was full
+ A.charging = 1 // It's no longer full
+ if(drained >= drain_rate)
+ break
+
if(power_drained > max_power * 0.98)
- if(!admins_warned)
- admins_warned = 1
+ if (!admins_warned)
+ admins_warned = TRUE
message_admins("Power sink at ([x],[y],[z] - JMP) is 95% full. Explosion imminent.")
playsound(src, 'sound/effects/screech.ogg', 100, 1, 1)
+
if(power_drained >= max_power)
+ STOP_PROCESSING(SSobj, src)
explosion(src.loc, 4,8,16,32)
qdel(src)
- return
- if(attached && attached.powernet)
- PN = attached.powernet
- else
- PN = null
+
+#undef DISCONNECTED
+#undef CLAMPED_OFF
+#undef OPERATING
\ No newline at end of file
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index b98e6d9acfc..610c257b03f 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -315,7 +315,7 @@
if(keyslot1 || keyslot2)
for(var/ch_name in channels)
- radio_controller.remove_object(src, radiochannels[ch_name])
+ SSradio.remove_object(src, SSradio.radiochannels[ch_name])
secure_radio_connections[ch_name] = null
if(keyslot1)
@@ -392,11 +392,11 @@
for(var/ch_name in channels)
- if(!radio_controller)
+ if(!SSradio)
name = "broken radio headset"
return
- secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
+ secure_radio_connections[ch_name] = SSradio.add_object(src, SSradio.radiochannels[ch_name], RADIO_CHAT)
if(setDescription)
setupRadioDescription()
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 287c7b44c30..3064b0ae3c8 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -49,7 +49,7 @@
..()
buildstage = building
if(buildstage)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
else
if(ndir)
pixel_x = (ndir & EAST|WEST) ? (ndir == EAST ? 28 : -28) : 0
@@ -105,7 +105,7 @@
)
/obj/item/radio/intercom/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
GLOB.global_intercoms.Remove(src)
return ..()
@@ -128,7 +128,7 @@
// TODO: Integrate radio with the space manager
if(isnull(position) || !(position.z in level))
return -1
- if(freq in ANTAG_FREQS)
+ if(freq in SSradio.ANTAG_FREQS)
if(!(syndiekey))
return -1//Prevents broadcast of messages over devices lacking the encryption
@@ -150,7 +150,7 @@
b_stat = 1
buildstage = 1
update_icon()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return 1
else return ..()
if(2)
@@ -163,7 +163,7 @@
buildstage = 3
to_chat(user, "You secure the electronics!")
update_icon()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
for(var/i, i<= 5, i++)
wires.UpdateCut(i,1)
return 1
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index e01b1a2a61a..00efc83668b 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -59,9 +59,9 @@ var/global/list/default_medbay_channels = list(
/obj/item/radio/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
+ SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_CHAT)
/obj/item/radio/New()
@@ -73,10 +73,10 @@ var/global/list/default_medbay_channels = list(
/obj/item/radio/Destroy()
QDEL_NULL(wires)
- if(radio_controller)
- radio_controller.remove_object(src, frequency)
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
for(var/ch_name in channels)
- radio_controller.remove_object(src, radiochannels[ch_name])
+ SSradio.remove_object(src, SSradio.radiochannels[ch_name])
radio_connection = null
GLOB.global_radios -= src
follow_target = null
@@ -90,7 +90,7 @@ var/global/list/default_medbay_channels = list(
set_frequency(frequency)
for(var/ch_name in channels)
- secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
+ secure_radio_connections[ch_name] = SSradio.add_object(src, SSradio.radiochannels[ch_name], RADIO_CHAT)
/obj/item/radio/attack_ghost(mob/user)
return interact(user)
@@ -147,7 +147,7 @@ var/global/list/default_medbay_channels = list(
var/chan_stat = channels[ch_name]
var/listening = !!(chan_stat & FREQ_LISTENING) != 0
- dat.Add(list(list("chan" = ch_name, "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = !listening, "chan_span" = frequency_span_class(radiochannels[ch_name]))))
+ dat.Add(list(list("chan" = ch_name, "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = !listening, "chan_span" = SSradio.frequency_span_class(SSradio.radiochannels[ch_name]))))
return dat
@@ -155,7 +155,7 @@ var/global/list/default_medbay_channels = list(
var/dat[0]
for(var/internal_chan in internal_channels)
if(has_channel_access(user, internal_chan))
- dat.Add(list(list("chan" = internal_chan, "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = frequency_span_class(text2num(internal_chan)))))
+ dat.Add(list(list("chan" = internal_chan, "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = SSradio.frequency_span_class(text2num(internal_chan)))))
return dat
@@ -397,7 +397,6 @@ var/global/list/default_medbay_channels = list(
var/mob/living/carbon/human/H = M
displayname = H.voice
if(H.voice != real_name)
- jobname = "Unknown"
voicemask = TRUE
if(syndiekey && syndiekey.change_voice && connection.frequency == SYND_FREQ)
@@ -555,7 +554,7 @@ var/global/list/default_medbay_channels = list(
var/turf/position = get_turf(src)
if(!position || !(position.z in level))
return -1
- if(freq in ANTAG_FREQS)
+ if(freq in SSradio.ANTAG_FREQS)
if(!(syndiekey))//Checks to see if it's allowed on that frequency, based on the encryption keys
return -1
if(!freq) //recieved on main frequency
@@ -699,7 +698,7 @@ var/global/list/default_medbay_channels = list(
for(var/ch_name in channels)
- radio_controller.remove_object(src, radiochannels[ch_name])
+ SSradio.remove_object(src, SSradio.radiochannels[ch_name])
secure_radio_connections[ch_name] = null
@@ -752,13 +751,13 @@ var/global/list/default_medbay_channels = list(
for(var/ch_name in channels)
- if(!radio_controller)
- sleep(30) // Waiting for the radio_controller to be created.
- if(!radio_controller)
+ if(!SSradio)
+ sleep(30) // Waiting for SSradio to be created.
+ if(!SSradio)
name = "broken radio"
return
- secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
+ secure_radio_connections[ch_name] = SSradio.add_object(src, SSradio.radiochannels[ch_name], RADIO_CHAT)
return
@@ -829,14 +828,14 @@ var/global/list/default_medbay_channels = list(
return data
/obj/item/radio/proc/config(op)
- if(radio_controller)
+ if(SSradio)
for(var/ch_name in channels)
- radio_controller.remove_object(src, radiochannels[ch_name])
+ SSradio.remove_object(src, SSradio.radiochannels[ch_name])
secure_radio_connections = new
channels = op
- if(radio_controller)
+ if(SSradio)
for(var/ch_name in op)
- secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
+ secure_radio_connections[ch_name] = SSradio.add_object(src, SSradio.radiochannels[ch_name], RADIO_CHAT)
return
/obj/item/radio/off
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 8ad7fae6d2d..cad4ae25ac8 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -34,7 +34,7 @@ REAGENT SCANNER
/obj/item/t_scanner/Destroy()
if(on)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/t_scanner/attack_self(mob/user)
@@ -43,12 +43,12 @@ REAGENT SCANNER
icon_state = copytext(icon_state, 1, length(icon_state))+"[on]"
if(on)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/t_scanner/process()
if(!on)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return null
scan()
@@ -125,8 +125,8 @@ REAGENT SCANNER
var/mode = 1;
-/obj/item/healthanalyzer/attack(mob/living/M as mob, mob/living/user as mob)
- if(( (CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50))
+/obj/item/healthanalyzer/attack(mob/living/M, mob/living/user)
+ if(((CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50))
to_chat(user, text("You try to analyze the floor's vitals!"))
for(var/mob/O in viewers(M, null))
O.show_message(text("[user] has analyzed the floor's vitals!"), 1)
@@ -137,7 +137,7 @@ REAGENT SCANNER
return
user.visible_message("[user] has analyzed [M]'s vitals."," You have analyzed [M]'s vitals.")
- if(!istype(M,/mob/living/carbon/human) || M.isSynthetic())
+ if(!ishuman(M) || M.isSynthetic())
//these sensors are designed for organic life
user.show_message("Analyzing Results for ERROR:\n\t Overall Status: ERROR")
user.show_message("\t Key: Suffocation/Toxin/Burns/Brute", 1)
@@ -147,122 +147,132 @@ REAGENT SCANNER
user.show_message("Subject's pulse: -- bpm.")
return
- var/fake_oxy = max(rand(1,40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss())))
- var/OX = M.getOxyLoss() > 50 ? "[M.getOxyLoss()]" : M.getOxyLoss()
- var/TX = M.getToxLoss() > 50 ? "[M.getToxLoss()]" : M.getToxLoss()
- var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss()
- var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss()
- if(M.status_flags & FAKEDEATH)
+ var/mob/living/carbon/human/H = M
+ var/fake_oxy = max(rand(1,40), H.getOxyLoss(), (300 - (H.getToxLoss() + H.getFireLoss() + H.getBruteLoss())))
+ var/OX = H.getOxyLoss() > 50 ? "[H.getOxyLoss()]" : H.getOxyLoss()
+ var/TX = H.getToxLoss() > 50 ? "[H.getToxLoss()]" : H.getToxLoss()
+ var/BU = H.getFireLoss() > 50 ? "[H.getFireLoss()]" : H.getFireLoss()
+ var/BR = H.getBruteLoss() > 50 ? "[H.getBruteLoss()]" : H.getBruteLoss()
+ if(H.status_flags & FAKEDEATH)
OX = fake_oxy > 50 ? "[fake_oxy]" : fake_oxy
- user.show_message("Analyzing Results for [M]:\n\t Overall Status: dead")
+ user.show_message("Analyzing Results for [H]:\n\t Overall Status: dead")
else
- user.show_message("Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[M.health]% healthy"]")
+ user.show_message("Analyzing Results for [H]:\n\t Overall Status: [H.stat > 1 ? "dead" : "[H.health]% healthy"]")
user.show_message("\t Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message("\t Damage Specifics: [OX] - [TX] - [BU] - [BR]")
- user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
- if(M.timeofdeath && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
- user.show_message("Time of Death: [station_time_timestamp("hh:mm:ss", M.timeofdeath)]")
- var/tdelta = round(world.time - M.timeofdeath)
+ user.show_message("Body Temperature: [H.bodytemperature-T0C]°C ([H.bodytemperature*1.8-459.67]°F)", 1)
+ if(H.timeofdeath && (H.stat == DEAD || (H.status_flags & FAKEDEATH)))
+ user.show_message("Time of Death: [station_time_timestamp("hh:mm:ss", H.timeofdeath)]")
+ var/tdelta = round(world.time - H.timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
user.show_message("Subject died [DisplayTimeText(tdelta)] ago, defibrillation may be possible!")
- if(istype(M, /mob/living/carbon/human) && mode == 1)
- var/mob/living/carbon/human/H = M
+ if(mode == 1)
var/list/damaged = H.get_damaged_organs(1,1)
user.show_message("Localized Damage, Brute/Burn:",1)
if(length(damaged) > 0)
for(var/obj/item/organ/external/org in damaged)
user.show_message("\t\t[capitalize(org.name)]: [(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]-[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]")
- OX = M.getOxyLoss() > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal"
- TX = M.getToxLoss() > 50 ? "Dangerous amount of toxins detected" : "Subject bloodstream toxin level minimal"
- BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status O.K"
- BR = M.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute-force injury status O.K"
- if(M.status_flags & FAKEDEATH)
+ OX = H.getOxyLoss() > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal"
+ TX = H.getToxLoss() > 50 ? "Dangerous amount of toxins detected" : "Subject bloodstream toxin level minimal"
+ BU = H.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status O.K"
+ BR = H.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute-force injury status O.K"
+ if(H.status_flags & FAKEDEATH)
OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal"
user.show_message("[OX] | [TX] | [BU] | [BR]")
- if(istype(M, /mob/living/carbon))
- if(upgraded)
- chemscan(user, M)
- for(var/thing in M.viruses)
- var/datum/disease/D = thing
- if(!(D.visibility_flags & HIDDEN_SCANNER))
- user.show_message("Warning: [D.form] detected\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]")
- if(M.getStaminaLoss())
+
+ if(upgraded)
+ chemscan(user, H)
+ for(var/thing in H.viruses)
+ var/datum/disease/D = thing
+ if(!(D.visibility_flags & HIDDEN_SCANNER))
+ user.show_message("Warning: [D.form] detected\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]")
+ if(H.undergoing_cardiac_arrest())
+ var/obj/item/organ/internal/heart/heart = H.get_int_organ(/obj/item/organ/internal/heart)
+ if(heart && !(heart.status & ORGAN_DEAD))
+ user.show_message("Warning: Medical Emergency detected\nName: Cardiac Arrest.\nType: The patient's heart has stopped.\nStage: 1/1.\nPossible Cure: Electric Shock")
+ else if(heart && (heart.status & ORGAN_DEAD))
+ user.show_message("Subject's heart is necrotic.")
+ else if(!heart)
+ user.show_message("Subject has no heart.")
+
+ if(H.getStaminaLoss())
user.show_message("Subject appears to be suffering from fatigue.")
- if(M.getCloneLoss())
- user.show_message("Subject appears to have [M.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.")
- if(M.has_brain_worms())
+ if(H.getCloneLoss())
+ user.show_message("Subject appears to have [H.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.")
+ if(H.has_brain_worms())
user.show_message("Subject suffering from aberrant brain activity. Recommend further scanning.")
- else if(M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && !M.get_int_organ(/obj/item/organ/internal/brain))
- user.show_message("Subject is brain dead.")
- else if(M.getBrainLoss() >= 60)
- user.show_message("Severe brain damage detected. Subject likely to have mental retardation.")
- else if(M.getBrainLoss() >= 10)
- user.show_message("Significant brain damage detected. Subject may have had a concussion.")
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- for(var/name in H.bodyparts_by_name)
- var/obj/item/organ/external/e = H.bodyparts_by_name[name]
- if(!e)
- continue
- var/limb = e.name
- if(e.status & ORGAN_BROKEN)
- if((e.limb_name in list("l_arm", "r_arm", "l_hand", "r_hand", "l_leg", "r_leg", "l_foot", "r_foot")) && !(e.status & ORGAN_SPLINTED))
- user.show_message("Unsecured fracture in subject [limb]. Splinting recommended for transport.")
- if(e.has_infected_wound())
- user.show_message("Infected wound detected in subject [limb]. Disinfection recommended.")
- for(var/name in H.bodyparts_by_name)
- var/obj/item/organ/external/e = H.bodyparts_by_name[name]
- if(!e)
- continue
- if(e.status & ORGAN_BROKEN)
- user.show_message(text("Bone fractures detected. Advanced scanner required for location."), 1)
- break
- for(var/obj/item/organ/external/e in H.bodyparts)
- if(e.internal_bleeding)
- user.show_message(text("Internal bleeding detected. Advanced scanner required for location."), 1)
- break
- var/blood_id = H.get_blood_id()
- if(blood_id)
- if(H.bleed_rate)
- user.show_message("Subject is bleeding!")
- var/blood_percent = round((H.blood_volume / BLOOD_VOLUME_NORMAL)*100)
- var/blood_type = H.b_type
- if(blood_id != "blood")//special blood substance
- var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
- if(R)
- blood_type = R.name
- else
- blood_type = blood_id
- if(H.blood_volume <= BLOOD_VOLUME_SAFE && H.blood_volume > BLOOD_VOLUME_OKAY)
- user.show_message("LOW blood level [blood_percent] %, [H.blood_volume] cl,type: [blood_type]")
- else if(H.blood_volume <= BLOOD_VOLUME_OKAY)
- user.show_message("CRITICAL blood level [blood_percent] %, [H.blood_volume] cl,type: [blood_type]")
+ if(H.get_int_organ(/obj/item/organ/internal/brain))
+ if(H.getBrainLoss() >= 100)
+ user.show_message("Subject is brain dead.")
+ else if(H.getBrainLoss() >= 60)
+ user.show_message("Severe brain damage detected. Subject likely to have mental retardation.")
+ else if(H.getBrainLoss() >= 10)
+ user.show_message("Significant brain damage detected. Subject may have had a concussion.")
+ else
+ user.show_message("Subject has no brain.")
+
+ for(var/name in H.bodyparts_by_name)
+ var/obj/item/organ/external/e = H.bodyparts_by_name[name]
+ if(!e)
+ continue
+ var/limb = e.name
+ if(e.status & ORGAN_BROKEN)
+ if((e.limb_name in list("l_arm", "r_arm", "l_hand", "r_hand", "l_leg", "r_leg", "l_foot", "r_foot")) && !(e.status & ORGAN_SPLINTED))
+ user.show_message("Unsecured fracture in subject [limb]. Splinting recommended for transport.")
+ if(e.has_infected_wound())
+ user.show_message("Infected wound detected in subject [limb]. Disinfection recommended.")
+
+ for(var/name in H.bodyparts_by_name)
+ var/obj/item/organ/external/e = H.bodyparts_by_name[name]
+ if(!e)
+ continue
+ if(e.status & ORGAN_BROKEN)
+ user.show_message(text("Bone fractures detected. Advanced scanner required for location."), 1)
+ break
+ for(var/obj/item/organ/external/e in H.bodyparts)
+ if(e.internal_bleeding)
+ user.show_message(text("Internal bleeding detected. Advanced scanner required for location."), 1)
+ break
+ var/blood_id = H.get_blood_id()
+ if(blood_id)
+ if(H.bleed_rate)
+ user.show_message("Subject is bleeding!")
+ var/blood_percent = round((H.blood_volume / BLOOD_VOLUME_NORMAL)*100)
+ var/blood_type = H.b_type
+ if(blood_id != "blood")//special blood substance
+ var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
+ if(R)
+ blood_type = R.name
else
- user.show_message("Blood level [blood_percent] %, [H.blood_volume] cl, type: [blood_type]")
-
- if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
- user.show_message("Subject suffering from heart attack: Apply defibrillator immediately.")
- user.show_message("Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.")
- var/implant_detect
- for(var/obj/item/organ/internal/cyberimp/CI in H.internal_organs)
- if(CI.is_robotic())
- implant_detect += "[H.name] is modified with a [CI.name]. "
- if(implant_detect)
- user.show_message("Detected cybernetic modifications:")
- user.show_message("[implant_detect]")
- if(H.gene_stability < 40)
- user.show_message("Subject's genes are quickly breaking down!")
- else if(H.gene_stability < 70)
- user.show_message("Subject's genes are showing signs of spontaneous breakdown.")
- else if(H.gene_stability < 85)
- user.show_message("Subject's genes are showing minor signs of instability.")
+ blood_type = blood_id
+ if(H.blood_volume <= BLOOD_VOLUME_SAFE && H.blood_volume > BLOOD_VOLUME_OKAY)
+ user.show_message("LOW blood level [blood_percent] %, [H.blood_volume] cl,type: [blood_type]")
+ else if(H.blood_volume <= BLOOD_VOLUME_OKAY)
+ user.show_message("CRITICAL blood level [blood_percent] %, [H.blood_volume] cl,type: [blood_type]")
else
- user.show_message("Subject's genes are stable.")
- src.add_fingerprint(user)
- return
+ user.show_message("Blood level [blood_percent] %, [H.blood_volume] cl, type: [blood_type]")
+
+ user.show_message("Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.")
+ var/implant_detect
+ for(var/obj/item/organ/internal/cyberimp/CI in H.internal_organs)
+ if(CI.is_robotic())
+ implant_detect += "[H.name] is modified with a [CI.name]. "
+ if(implant_detect)
+ user.show_message("Detected cybernetic modifications:")
+ user.show_message("[implant_detect]")
+ if(H.gene_stability < 40)
+ user.show_message("Subject's genes are quickly breaking down!")
+ else if(H.gene_stability < 70)
+ user.show_message("Subject's genes are showing signs of spontaneous breakdown.")
+ else if(H.gene_stability < 85)
+ user.show_message("Subject's genes are showing minor signs of instability.")
+ else
+ user.show_message("Subject's genes are stable.")
+ add_fingerprint(user)
+
/obj/item/healthanalyzer/verb/toggle_mode()
set name = "Switch Verbosity"
@@ -275,19 +285,21 @@ REAGENT SCANNER
if(0)
to_chat(usr, "The scanner no longer shows limb damage.")
-/obj/item/healthanalyzer/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/healthupgrade))
+/obj/item/healthanalyzer/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/healthupgrade))
if(upgraded)
to_chat(user, "You have already installed an upgraded in the [src].")
else
to_chat(user, "You install the upgrade in the [src].")
overlays += "advanced"
- playsound(loc, W.usesound, 50, 1)
- upgraded = 1
- qdel(W)
+ playsound(loc, I.usesound, 50, 1)
+ upgraded = TRUE
+ qdel(I)
+ return
+ return ..()
/obj/item/healthanalyzer/advanced
- upgraded = 1
+ upgraded = TRUE
/obj/item/healthanalyzer/advanced/New()
overlays += "advanced"
@@ -579,6 +591,9 @@ REAGENT SCANNER
var/scan_time = 10 SECONDS //how long does it take to scan
var/scan_cd = 60 SECONDS //how long before we can scan again
+/obj/item/bodyanalyzer/get_cell()
+ return power_supply
+
/obj/item/bodyanalyzer/advanced
cell_type = /obj/item/stock_parts/cell/upgraded/plus
@@ -834,4 +849,4 @@ REAGENT SCANNER
if(target.disabilities & NEARSIGHTED)
dat += "Retinal misalignment detected. "
- return dat
+ return dat
\ No newline at end of file
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index 247b5fb1a0d..c6cfe03a151 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -23,7 +23,6 @@ var/list/world_uplinks = list()
var/used_TC = 0
var/job = null
- var/show_descriptions = 0
var/temp_category
var/uplink_type = "traitor"
@@ -32,8 +31,8 @@ var/list/world_uplinks = list()
/obj/item/uplink/New()
..()
- welcome = ticker.mode.uplink_welcome
- uses = ticker.mode.uplink_uses
+ welcome = SSticker.mode.uplink_welcome
+ uses = SSticker.mode.uplink_uses
uplink_items = get_uplink_items()
world_uplinks += src
@@ -72,7 +71,10 @@ var/list/world_uplinks = list()
if(I.job && I.job.len)
if(!(I.job.Find(job)))
continue
- dat += "[I.name] ([I.cost]) "
+ dat += "[I.name] ([I.cost])"
+ if(I.hijack_only)
+ dat += " (HIJACK ONLY)"
+ dat += " "
category_items++
dat += "Random Item (??) "
@@ -95,7 +97,7 @@ var/list/world_uplinks = list()
if(I.job && I.job.len)
if(!(I.job.Find(job)))
continue
- nano[nano.len]["items"] += list(list("Name" = sanitize(I.name), "Description" = sanitize(I.description()),"Cost" = I.cost, "obj_path" = I.reference))
+ nano[nano.len]["items"] += list(list("Name" = sanitize(I.name), "Description" = sanitize(I.description()),"Cost" = I.cost, "hijack_only" = I.hijack_only, "obj_path" = I.reference))
reference[I.reference] = I
var/datum/nano_item_lists/result = new
@@ -231,7 +233,6 @@ var/list/world_uplinks = list()
data["welcome"] = welcome
data["crystals"] = uses
data["menu"] = nanoui_menu
- data["descriptions"] = show_descriptions
if(!nanoui_items)
generate_items(user)
data["nano_items"] = nanoui_items
@@ -266,12 +267,6 @@ var/list/world_uplinks = list()
if(href_list["menu"])
nanoui_menu = text2num(href_list["menu"])
update_nano_data(href_list["id"])
- if(href_list["menu"])
- nanoui_menu = text2num(href_list["menu"])
- update_nano_data(href_list["id"])
- if(href_list["descriptions"])
- show_descriptions = !show_descriptions
- update_nano_data()
if(href_list["category"])
temp_category = href_list["category"]
update_nano_data()
diff --git a/code/game/objects/items/devices/voice.dm b/code/game/objects/items/devices/voice.dm
new file mode 100644
index 00000000000..38bcd16f01e
--- /dev/null
+++ b/code/game/objects/items/devices/voice.dm
@@ -0,0 +1,44 @@
+/obj/item/voice_changer
+ name = "voice changer"
+ desc = "A voice scrambling module."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "voice_changer_off"
+
+ actions_types = list(/datum/action/item_action/voice_changer/toggle, /datum/action/item_action/voice_changer/voice)
+
+ var/obj/item/parent
+
+ var/voice
+ var/active
+
+/obj/item/voice_changer/New()
+ . = ..()
+
+ if(isitem(loc))
+ parent = loc
+ parent.actions |= actions
+
+/obj/item/voice_changer/Destroy()
+ if(isitem(parent))
+ parent.actions -= actions
+
+ return ..()
+
+/obj/item/voice_changer/attack_self(mob/user)
+ active = !active
+ icon_state = "voice_changer_[active ? "on" : "off"]"
+ to_chat(user, "You toggle [src] [active ? "on" : "off"].")
+
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
+
+/obj/item/voice_changer/proc/set_voice(mob/user)
+ var/chosen_voice = clean_input("What voice would you like to mimic? Leave this empty to use the voice on your ID card.", "Set Voice Changer", voice, user)
+ if(!chosen_voice)
+ voice = null
+ to_chat(user, "You are now mimicking the voice on your ID card.")
+ return
+
+ voice = sanitize(copytext(chosen_voice, 1, MAX_MESSAGE_LEN))
+ to_chat(user, "You are now mimicking [voice].")
\ No newline at end of file
diff --git a/code/game/objects/items/documents.dm b/code/game/objects/items/documents.dm
index eeb3355c50c..8c4144f7c68 100644
--- a/code/game/objects/items/documents.dm
+++ b/code/game/objects/items/documents.dm
@@ -39,6 +39,9 @@
var/poison_dose = 20
var/poison_total = 60
+/obj/item/documents/syndicate/mining
+ desc = "\"Top Secret\" documents detailing Syndicate plasma mining operations."
+
/obj/item/documents/syndicate/yellow/trapped/pickup(user)
if(ishuman(user) && poison_total > 0)
var/mob/living/carbon/human/H = user
diff --git a/code/game/objects/items/flag.dm b/code/game/objects/items/flag.dm
index 3ba466b7eec..121b0214b5a 100644
--- a/code/game/objects/items/flag.dm
+++ b/code/game/objects/items/flag.dm
@@ -64,11 +64,6 @@
desc = "The banner of the glorious revolutionary forces fighting the oppressors on Clown Planet."
icon_state = "mimeflag"
-/obj/item/flag/pony
- name = "Equestria flag"
- desc = "The flag of the independent, sovereign nation of Equestria, whatever the fuck that is."
- icon_state = "ponyflag"
-
/obj/item/flag/ian
name = "Ian flag"
desc = "The banner of Ian, because SQUEEEEE."
@@ -170,8 +165,8 @@
icon_state = "atmosflag"
/obj/item/flag/command
- name = "Commandzikstan flag"
- desc = "The flag of the independent, sovereign nation of Commandzikstan."
+ name = "Command flag"
+ desc = "The flag of the independent, sovereign nation of Command."
icon_state = "ntflag"
//Antags
diff --git a/code/game/objects/items/random_items.dm b/code/game/objects/items/random_items.dm
index 587b1d27d14..e51bac10005 100644
--- a/code/game/objects/items/random_items.dm
+++ b/code/game/objects/items/random_items.dm
@@ -123,6 +123,7 @@
/obj/item/storage/pill_bottle/random_meds
name = "unlabelled pillbottle"
desc = "The sheer recklessness of this bottle's existence astounds you."
+ allow_wrap = FALSE
var/labelled = FALSE
/obj/item/storage/pill_bottle/random_meds/New()
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 65f504b4ae0..6ce10294940 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -245,7 +245,7 @@
to_chat(user, "Sticking a dead [M] into the frame would sort of defeat the purpose.")
return
- if(M.brainmob.mind in ticker.mode.head_revolutionaries)
+ if(M.brainmob.mind in SSticker.mode.head_revolutionaries)
to_chat(user, "The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the [M].")
return
@@ -306,7 +306,6 @@
O.Namepick()
feedback_inc("cyborg_birth",1)
- callHook("borgify", list(O))
forceMove(O)
O.robot_suit = src
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 064b66b78f4..a13bce6fb61 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -31,31 +31,9 @@
if(..())
return
- R.notify_ai(2)
+ R.reset_module()
- R.uneq_all()
- R.sight_mode = null
- R.hands.icon_state = "nomod"
- R.icon_state = "robot"
- R.module.remove_subsystems_and_actions(R)
- QDEL_NULL(R.module)
-
- R.camera.network.Remove(list("Engineering", "Medical", "Mining Outpost"))
- R.rename_character(R.real_name, R.get_default_name("Default"))
- R.languages = list()
- R.speech_synthesizer_langs = list()
-
- R.update_icons()
- R.update_headlamp()
-
- R.speed = 0 // Remove upgrades.
- R.ionpulse = 0
- R.magpulse = 0
- R.add_language("Robot Talk", 1)
-
- R.status_flags |= CANPUSH
-
- return 1
+ return TRUE
/obj/item/borg/upgrade/rename
name = "cyborg reclassification board"
@@ -256,7 +234,7 @@
/obj/item/borg/upgrade/selfrepair/Destroy()
cyborg = null
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
on = 0
return ..()
@@ -264,10 +242,10 @@
on = !on
if(on)
to_chat(cyborg, "You activate the self-repair module.")
- processing_objects |= src
+ START_PROCESSING(SSobj, src)
else
to_chat(cyborg, "You deactivate the self-repair module.")
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
update_icon()
/obj/item/borg/upgrade/selfrepair/update_icon()
@@ -280,7 +258,7 @@
icon_state = "cyborg_upgrade5"
/obj/item/borg/upgrade/selfrepair/proc/deactivate()
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
on = 0
update_icon()
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 0bdc88c5b52..0e95f509463 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -195,8 +195,6 @@
heal_burn = 25
//Medical Herbs//
-
-
/obj/item/stack/medical/bruise_pack/comfrey
name = "\improper Comfrey leaf"
singular_name = "Comfrey leaf"
@@ -217,48 +215,55 @@
color = "#4CC5C7"
heal_burn = 12
-
-//Splints//
-
-
+// Splints
/obj/item/stack/medical/splint
name = "medical splints"
singular_name = "medical splint"
icon_state = "splint"
- unique_handling = 1
+ unique_handling = TRUE
self_delay = 100
+ var/other_delay = 0
/obj/item/stack/medical/splint/attack(mob/living/M, mob/user)
if(..())
- return 1
+ return TRUE
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
var/limb = affecting.name
+
if(!(affecting.limb_name in list("l_arm", "r_arm", "l_hand", "r_hand", "l_leg", "r_leg", "l_foot", "r_foot")))
to_chat(user, "You can't apply a splint there!")
- return
+ return TRUE
+
if(affecting.status & ORGAN_SPLINTED)
to_chat(user, "[H]'s [limb] is already splinted!")
- if(alert(user, "Would you like to remove the splint from [H]'s [limb]?", "Removing.", "Yes", "No") == "Yes")
+ if(alert(user, "Would you like to remove the splint from [H]'s [limb]?", "Splint removal.", "Yes", "No") == "Yes")
affecting.status &= ~ORGAN_SPLINTED
H.handle_splints()
to_chat(user, "You remove the splint from [H]'s [limb].")
- return
- if(M == user)
- user.visible_message("[user] starts to apply [src] to [user.p_their()] [limb].", \
- "You start to apply [src] to your [limb].", \
- "You hear something being wrapped.")
- if(!do_mob(user, H, self_delay))
- return
- else
- user.visible_message("[user] applies [src] to [H]'s [limb].", \
- "You apply [src] to [H]'s [limb].", \
- "You hear something being wrapped.")
+ return TRUE
+
+ if((M == user && self_delay > 0) || (M != user && other_delay > 0))
+ user.visible_message("[user] starts to apply [src] to [H]'s [limb].", \
+ "You start to apply [src] to [H]'s [limb].", \
+ "You hear something being wrapped.")
+
+ if(M == user && !do_mob(user, H, self_delay))
+ return TRUE
+ else if(!do_mob(user, H, other_delay))
+ return TRUE
+
+ user.visible_message("[user] applies [src] to [H]'s [limb].", \
+ "You apply [src] to [H]'s [limb].")
affecting.status |= ORGAN_SPLINTED
affecting.splinted_count = H.step_count
H.handle_splints()
-
use(1)
+
+/obj/item/stack/medical/splint/tribal
+ name = "tribal splints"
+ icon_state = "tribal_splint"
+ other_delay = 50
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index 176efe55c7c..f3716459f18 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -25,6 +25,15 @@ var/global/list/datum/stack_recipe/rod_recipes = list ( \
/obj/item/stack/rods/cyborg
materials = list()
+/obj/item/stack/rods/ten
+ amount = 10
+
+/obj/item/stack/rods/twentyfive
+ amount = 25
+
+/obj/item/stack/rods/fifty
+ amount = 50
+
/obj/item/stack/rods/New(loc, amount=null)
..()
recipes = rod_recipes
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index dfb756d8c25..def012e2663 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
created_window = /obj/structure/window/basic
full_window = /obj/structure/window/full/basic
merge_type = /obj/item/stack/sheet/glass
+ point_value = 1
/obj/item/stack/sheet/glass/fifty
amount = 50
@@ -90,6 +91,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
created_window = /obj/structure/window/reinforced
full_window = /obj/structure/window/full/reinforced
merge_type = /obj/item/stack/sheet/rglass
+ point_value = 4
/obj/item/stack/sheet/rglass/cyborg
materials = list()
@@ -113,6 +115,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
origin_tech = "plasmatech=2;materials=2"
created_window = /obj/structure/window/plasmabasic
full_window = /obj/structure/window/full/plasmabasic
+ point_value = 19
/obj/item/stack/sheet/plasmaglass/New(loc, amount)
recipes = GLOB.pglass_recipes
@@ -154,6 +157,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
created_window = /obj/structure/window/plasmareinforced
full_window = /obj/structure/window/full/plasmareinforced
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0)
+ point_value = 23
/obj/item/stack/sheet/plasmarglass/New(loc, amount)
recipes = GLOB.prglass_recipes
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index bed2f200633..db7c08b1863 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -125,6 +125,55 @@ var/global/list/datum/stack_recipe/sinew_recipes = list ( \
flags = NOBLUDGEON
w_class = WEIGHT_CLASS_NORMAL
layer = MOB_LAYER
+ var/static/list/can_strengthen_clothing
+
+/obj/item/stack/sheet/animalhide/goliath_hide/Initialize(mapload)
+ . = ..()
+ if(!can_strengthen_clothing)
+ can_strengthen_clothing = typecacheof(list(
+ /obj/item/clothing/suit/space/hardsuit/mining,
+ /obj/item/clothing/head/helmet/space/hardsuit/mining,
+ /obj/item/clothing/suit/space/eva/plasmaman/miner,
+ /obj/item/clothing/head/helmet/space/eva/plasmaman/miner,
+ /obj/item/clothing/suit/hooded/explorer,
+ /obj/item/clothing/head/hooded/explorer,
+ /obj/item/clothing/suit/space/eva/plasmaman/explorer,
+ /obj/item/clothing/head/helmet/space/eva/plasmaman/explorer
+ ))
+
+/obj/item/stack/sheet/animalhide/goliath_hide/afterattack(atom/target, mob/user, proximity_flag)
+ if(proximity_flag)
+ if(is_type_in_typecache(target, can_strengthen_clothing))
+ var/obj/item/clothing/C = target
+ var/current_armor = C.armor
+ if(current_armor["melee"] < 60)
+ current_armor["melee"] = min(current_armor["melee"] + 10, 60)
+ to_chat(user, "You strengthen [target], improving its resistance against melee attacks.")
+ use(1)
+ else
+ to_chat(user, "You can't improve [C] any further.")
+ return
+ if(istype(target, /obj/mecha/working/ripley))
+ var/obj/mecha/D = target
+ if(D.icon_state != "ripley-open")
+ to_chat(user, "You can't add armour onto the mech while someone is inside!")
+ return
+ var/list/damage_absorption = D.damage_absorption
+ if(damage_absorption["brute"] > 0.3)
+ damage_absorption["brute"] = max(damage_absorption["brute"] - 0.1, 0.3)
+ damage_absorption["bullet"] = damage_absorption["bullet"] - 0.05
+ damage_absorption["fire"] = damage_absorption["fire"] - 0.05
+ damage_absorption["laser"] = damage_absorption["laser"] - 0.025
+ to_chat(user, "You strengthen [target], improving its resistance against melee attacks.")
+ use(1)
+ D.overlays += image("icon"="mecha.dmi", "icon_state"="ripley-g-open")
+ D.desc = "Autonomous Power Loader Unit. Its armour is enhanced with some goliath hide plates."
+ if(damage_absorption["brute"] == 0.3)
+ D.overlays += image("icon"="mecha.dmi", "icon_state"="ripley-g-full-open")
+ D.desc = "Autonomous Power Loader Unit. It's wearing a fearsome carapace entirely composed of goliath hide plates - the pilot must be an experienced monster hunter."
+ else
+ to_chat(user, "You can't improve [D] any further!")
+ return
/obj/item/stack/sheet/animalhide/ashdrake
name = "ash drake hide"
@@ -156,7 +205,12 @@ var/global/list/datum/stack_recipe/sinew_recipes = list ( \
else
..()
-//Step two - washing..... it's actually in washing machine code.
+//Step two - washing (also handled by water reagent code and washing machine code)
+/obj/item/stack/sheet/hairlesshide/water_act(volume, temperature, source, method = TOUCH)
+ . = ..()
+ if(volume >= 10)
+ new /obj/item/stack/sheet/wetleather(get_turf(src), amount)
+ qdel(src)
//Step three - drying
/obj/item/stack/sheet/wetleather/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index c7a27b5650e..8c60bcefa11 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -108,6 +108,11 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
new /datum/stack_recipe("incomplete servant golem shell", /obj/item/golem_shell/servant, req_amount = 1, res_amount = 1), \
)
+var/global/list/datum/stack_recipe/snow_recipes = list(
+ new/datum/stack_recipe("snowman", /obj/structure/snowman, 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("Snowball", /obj/item/snowball, 1)
+ )
+
/obj/item/stack/sheet/mineral
force = 5
throwforce = 5
@@ -139,6 +144,7 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
origin_tech = "materials=6"
sheettype = "diamond"
materials = list(MAT_DIAMOND=MINERAL_MATERIAL_AMOUNT)
+ point_value = 25
/obj/item/stack/sheet/mineral/diamond/New()
..()
@@ -151,6 +157,7 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
origin_tech = "materials=5"
sheettype = "uranium"
materials = list(MAT_URANIUM=MINERAL_MATERIAL_AMOUNT)
+ point_value = 20
/obj/item/stack/sheet/mineral/uranium/New()
..()
@@ -165,6 +172,7 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT)
burn_state = FLAMMABLE
burntime = 5
+ point_value = 20
/obj/item/stack/sheet/mineral/plasma/New()
..()
@@ -191,6 +199,7 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
origin_tech = "materials=4"
sheettype = "gold"
materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT)
+ point_value = 20
/obj/item/stack/sheet/mineral/gold/New()
..()
@@ -203,6 +212,7 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
origin_tech = "materials=4"
sheettype = "silver"
materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT)
+ point_value = 20
/obj/item/stack/sheet/mineral/silver/New()
..()
@@ -215,6 +225,7 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
origin_tech = "materials=4"
sheettype = "bananium"
materials = list(MAT_BANANIUM=MINERAL_MATERIAL_AMOUNT)
+ point_value = 50
/obj/item/stack/sheet/mineral/bananium/New(loc, amount=null)
..()
@@ -228,6 +239,7 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
sheettype = "tranquillite"
materials = list(MAT_TRANQUILLITE=MINERAL_MATERIAL_AMOUNT)
wall_allowed = FALSE //no tranquilite walls in code
+ point_value = 50
/obj/item/stack/sheet/mineral/tranquillite/New(loc, amount=null)
..()
@@ -248,6 +260,7 @@ var/global/list/datum/stack_recipe/adamantine_recipes = list(
throw_range = 3
sheettype = "titanium"
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT)
+ point_value = 20
var/global/list/datum/stack_recipe/titanium_recipes = list (
new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20),
@@ -277,6 +290,7 @@ var/global/list/datum/stack_recipe/titanium_recipes = list (
throw_range = 3
sheettype = "plastitanium"
materials = list(MAT_TITANIUM=2000, MAT_PLASMA=2000)
+ point_value = 45
var/global/list/datum/stack_recipe/plastitanium_recipes = list (
new/datum/stack_recipe("plas-titanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20),
@@ -321,3 +335,19 @@ var/global/list/datum/stack_recipe/plastitanium_recipes = list (
/obj/item/stack/sheet/mineral/adamantine/New(loc, amount = null)
recipes = adamantine_recipes
..()
+
+/*
+ * Snow
+ */
+/obj/item/stack/sheet/mineral/snow
+ name = "snow"
+ icon_state = "sheet-snow"
+ item_state = "sheet-snow"
+ singular_name = "snow block"
+ force = 1
+ throwforce = 2
+ merge_type = /obj/item/stack/sheet/mineral/snow
+
+/obj/item/stack/sheet/mineral/snow/New(loc, amount = null)
+ recipes = snow_recipes
+ ..()
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index abc328a8bf1..9ec921fef92 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -16,6 +16,7 @@
var/global/list/datum/stack_recipe/metal_recipes = list(
new /datum/stack_recipe("stool", /obj/structure/chair/stool, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("chair", /obj/structure/chair, one_per_turf = 1, on_floor = 1),
+ new /datum/stack_recipe("shuttle seat", /obj/structure/chair/comfy/shuttle, 2, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("sofa (middle)", /obj/structure/chair/sofa, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("sofa (left)", /obj/structure/chair/sofa/left, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("sofa (right)", /obj/structure/chair/sofa/right, one_per_turf = 1, on_floor = 1),
@@ -105,6 +106,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list(
flags = CONDUCT
origin_tech = "materials=1"
merge_type = /obj/item/stack/sheet/metal
+ point_value = 2
/obj/item/stack/sheet/metal/cyborg
materials = list()
@@ -151,6 +153,7 @@ var/global/list/datum/stack_recipe/plasteel_recipes = list(
flags = CONDUCT
origin_tech = "materials=2"
merge_type = /obj/item/stack/sheet/plasteel
+ point_value = 23
/obj/item/stack/sheet/plasteel/New(var/loc, var/amount=null)
recipes = plasteel_recipes
@@ -214,6 +217,8 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \
null, \
new/datum/stack_recipe("fingerless gloves", /obj/item/clothing/gloves/fingerless, 1), \
new/datum/stack_recipe("black gloves", /obj/item/clothing/gloves/color/black, 3), \
+ null, \
+ new/datum/stack_recipe("blindfold", /obj/item/clothing/glasses/sunglasses/blindfold, 3), \
)
/obj/item/stack/sheet/cloth
@@ -240,6 +245,7 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \
var/global/list/datum/stack_recipe/cardboard_recipes = list (
new /datum/stack_recipe("box", /obj/item/storage/box),
new /datum/stack_recipe("large box", /obj/item/storage/box/large, 4),
+ new /datum/stack_recipe("patch pack", /obj/item/storage/pill_bottle/patch_pack, 2),
new /datum/stack_recipe("light tubes", /obj/item/storage/box/lights/tubes),
new /datum/stack_recipe("light bulbs", /obj/item/storage/box/lights/bulbs),
new /datum/stack_recipe("mouse traps", /obj/item/storage/box/mousetraps),
@@ -332,10 +338,13 @@ var/global/list/datum/stack_recipe/cult = list ( \
* Brass
*/
var/global/list/datum/stack_recipe/brass_recipes = list (\
+ new/datum/stack_recipe("wall gear", /obj/structure/clockwork/wall_gear, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
+ null,
new/datum/stack_recipe/window("brass windoor", /obj/machinery/door/window/clockwork, 2, time = 30, on_floor = TRUE, window_checks = TRUE), \
null,
new/datum/stack_recipe/window("directional brass window", /obj/structure/window/reinforced/clockwork, time = 0, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe/window("fulltile brass window", /obj/structure/window/reinforced/clockwork/fulltile, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
+ new/datum/stack_recipe("brass chair", /obj/structure/chair/brass, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = TRUE, on_floor = TRUE), \
)
@@ -384,8 +393,8 @@ var/global/list/datum/stack_recipe/brass_recipes = list (\
GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = 1, on_floor = 1, time = 40), \
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2), \
- new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/food/drinks/waterbottle/empty), \
- new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/food/drinks/waterbottle/large/empty,3), \
+ new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \
+ new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \
new /datum/stack_recipe("plastic crate", /obj/structure/closet/crate/plastic, 10, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("plastic ashtray", /obj/item/ashtray/plastic, 2, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("plastic fork", /obj/item/kitchen/utensil/pfork, 1, on_floor = 1), \
diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm
index 100704ed658..13774b0db4b 100644
--- a/code/game/objects/items/stacks/sheets/sheets.dm
+++ b/code/game/objects/items/stacks/sheets/sheets.dm
@@ -9,22 +9,10 @@
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed")
var/perunit = MINERAL_MATERIAL_AMOUNT
var/sheettype = null //this is used for girders in the creation of walls/false walls
+ var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity.
+
var/created_window = null //apparently glass sheets don't share a base type for glass specifically, so each had to define these vars individually
var/full_window = null //moving the var declaration to here so this can be checked cleaner until someone is willing to make them share a base type properly
usesound = 'sound/items/deconstruct.ogg'
toolspeed = 1
var/wall_allowed = TRUE //determines if sheet can be used in wall construction or not.
-
-
-// Since the sheetsnatcher was consolidated into weapon/storage/bag we now use
-// item/attackby() properly, making this unnecessary
-
-/*/obj/item/stack/sheet/attackby(obj/item/W as obj, mob/user as mob, params)
- if(istype(W, /obj/item/storage/bag/sheetsnatcher))
- var/obj/item/storage/bag/sheetsnatcher/S = W
- if(!S.mode)
- S.add(src,user)
- else
- for(var/obj/item/stack/sheet/stack in locate(src.x,src.y,src.z))
- S.add(stack,user)
- ..()*/
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 5cab26e062b..f0830f34c40 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -31,7 +31,7 @@
if(S.merge_type == merge_type)
merge(S)
-/obj/item/stack/Crossed(obj/O)
+/obj/item/stack/Crossed(obj/O, oldloc)
if(amount >= max_amount || ismob(loc)) // Prevents unnecessary call. Also prevents merging stack automatically in a mob's inventory
return
if(istype(O, merge_type) && !O.throwing)
@@ -54,7 +54,7 @@
to_chat(user, "There are [amount] [singular_name]\s in the stack.")
else
to_chat(user, "There are [amount] [name]\s in the stack.")
- to_chat(user,"Ctrl-Shift-click to take a custom amount.")
+ to_chat(user,"Alt-click to take a custom amount.")
/obj/item/stack/proc/add(newamount)
amount += newamount
@@ -111,16 +111,11 @@
if(istype(E, /datum/stack_recipe))
var/datum/stack_recipe/R = E
- var/max_multiplier = round(src.amount / R.req_amount)
+ var/max_multiplier = round(amount / R.req_amount)
var/title
var/can_build = 1
can_build = can_build && (max_multiplier > 0)
- /*
- if(R.one_per_turf)
- can_build = can_build && !(locate(R.result_type) in usr.loc)
- if(R.on_floor)
- can_build = can_build && istype(usr.loc, /turf/simulated/floor)
- */
+
if(R.res_amount > 1)
title += "[R.res_amount]x [R.title]\s"
else
@@ -131,12 +126,13 @@
else
t1 += "[title]"
continue
- if(R.max_res_amount>1 && max_multiplier>1)
+ if(R.max_res_amount > 1 && max_multiplier > 1)
max_multiplier = min(max_multiplier, round(R.max_res_amount / R.res_amount))
t1 += " |"
- var/list/multipliers = list(5,10,25)
+
+ var/list/multipliers = list(5, 10, 25)
for(var/n in multipliers)
- if(max_multiplier>=n)
+ if(max_multiplier >= n)
t1 += " [n * R.res_amount]x"
if(!(max_multiplier in multipliers))
t1 += " [max_multiplier * R.res_amount]x"
@@ -165,7 +161,7 @@
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
var/multiplier = text2num(href_list["multiplier"])
- if(!multiplier)
+ if(!multiplier || multiplier <= 0 || multiplier > 50) // Href exploit checks
multiplier = 1
if(amount < R.req_amount * multiplier)
@@ -263,7 +259,7 @@
else
..()
-/obj/item/stack/CtrlShiftClick(mob/living/user)
+/obj/item/stack/AltClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "You can't do that right now!")
return
@@ -276,7 +272,7 @@
//get amount from user
var/min = 0
var/max = get_amount()
- var/stackmaterial = round(input(user, "How many sheets do you wish to take out of this stack? (Maximum: [max])") as num)
+ var/stackmaterial = round(input(user, "How many sheets do you wish to take out of this stack? (Maximum: [max])") as null|num)
if(stackmaterial == null || stackmaterial <= min || stackmaterial > get_amount())
return
change_stack(user,stackmaterial)
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index aa3f23f99b7..fcbb277edd5 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -170,6 +170,20 @@
icon_state = "tile_pod"
turf_type = /turf/simulated/floor/pod
+/obj/item/stack/tile/pod/light
+ name = "light pod floor tile"
+ singular_name = "light pod floor tile"
+ desc = "A lightly colored grooved floor tile."
+ icon_state = "tile_podlight"
+ turf_type = /turf/simulated/floor/pod
+
+/obj/item/stack/tile/pod/dark
+ name = "dark pod floor tile"
+ singular_name = "dark pod floor tile"
+ desc = "A darkly colored grooved floor tile."
+ icon_state = "tile_poddark"
+ turf_type = /turf/simulated/floor/pod/dark
+
/obj/item/stack/tile/arcade_carpet
name = "arcade carpet"
singular_name = "arcade carpet"
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index d4d5f4aa213..a8ddcf6d315 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -208,6 +208,7 @@
origin_tech = null
attack_verb = list("attacked", "struck", "hit")
brightness_on = 0
+ sharp_when_wielded = FALSE // It's a toy
/obj/item/twohanded/dualsaber/toy/hit_reaction()
return 0
@@ -231,7 +232,7 @@
/obj/item/toy/katana/suicide_act(mob/user)
var/dmsg = pick("[user] tries to stab \the [src] into [user.p_their()] abdomen, but it shatters! [user.p_they(TRUE)] look[user.p_s()] as if [user.p_they()] might die from the shame.","[user] tries to stab \the [src] into [user.p_their()] abdomen, but \the [src] bends and breaks in half! [user.p_they(TRUE)] look[user.p_s()] as if [user.p_they()] might die from the shame.","[user] tries to slice [user.p_their()] own throat, but the plastic blade has no sharpness, causing [user.p_them()] to lose [user.p_their()] balance, slip over, and break [user.p_their()] neck with a loud snap!")
user.visible_message("[dmsg] It looks like [user.p_theyre()] trying to commit suicide.")
- return (BRUTELOSS)
+ return BRUTELOSS
/*
@@ -283,7 +284,7 @@
..()
pop_burst()
-/obj/item/toy/snappop/Crossed(H as mob|obj)
+/obj/item/toy/snappop/Crossed(H as mob|obj, oldloc)
if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off
var/mob/living/carbon/M = H
if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN)
@@ -1066,6 +1067,32 @@ obj/item/toy/cards/deck/syndicate/black
name = "tuxedo cat plushie"
icon_state = "tuxedocat"
+//New generation TG plushies
+
+/obj/item/toy/plushie/lizardplushie
+ name = "lizard plushie"
+ desc = "An adorable stuffed toy that resembles a lizardperson."
+ icon_state = "plushie_lizard"
+ item_state = "plushie_lizard"
+
+/obj/item/toy/plushie/snakeplushie
+ name = "snake plushie"
+ desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing."
+ icon_state = "plushie_snake"
+ item_state = "plushie_snake"
+
+/obj/item/toy/plushie/nukeplushie
+ name = "operative plushie"
+ desc = "An stuffed toy that resembles a syndicate nuclear operative. The tag claims operatives to be purely fictitious."
+ icon_state = "plushie_nuke"
+ item_state = "plushie_nuke"
+
+/obj/item/toy/plushie/slimeplushie
+ name = "slime plushie"
+ desc = "An adorable stuffed toy that resembles a slime. It is practically just a hacky sack."
+ icon_state = "plushie_slime"
+ item_state = "plushie_slime"
+
/*
* Foam Armblade
*/
@@ -1372,54 +1399,84 @@ obj/item/toy/cards/deck/syndicate/black
force = 5
origin_tech = "combat=1"
attack_verb = list("struck", "hit", "bashed")
- var/bullet_position = 1
+ var/bullets_left = 0
+ var/max_shots = 6
/obj/item/toy/russian_revolver/suicide_act(mob/user)
user.visible_message("[user] quickly loads six bullets into [src]'s cylinder and points it at [user.p_their()] head before pulling the trigger! It looks like [user.p_theyre()] trying to commit suicide.")
playsound(loc, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/toy/russian_revolver/New()
- spin_cylinder()
..()
-
+ spin_cylinder()
/obj/item/toy/russian_revolver/attack_self(mob/user)
- if(!bullet_position)
- user.visible_message("[user] loads a bullet into [src]'s cylinder.")
- bullet_position = 1
- else
+ if(!bullets_left)
+ user.visible_message("[user] loads a bullet into [src]'s cylinder before spinning it.")
spin_cylinder()
- user.visible_message("[user] spins the cylinder on [src]!")
-
-/obj/item/toy/russian_revolver/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
- if(M != user) //can't use this on other people
- return ..()
- if(!bullet_position)
- to_chat(user, "[src] is empty.")
- return
- if(!(user.has_organ("head"))) //For sanity
- to_chat(user, "Playing this game without a head would be classed as cheating.")
- return
- user.visible_message("[user] points [src] at [user.p_their()] head, ready to pull the trigger!")
- if(do_after(user, 30, target = user))
- if(bullet_position > 1)
- user.visible_message("*click*")
- playsound(src, 'sound/weapons/empty.ogg', 100, 1)
- bullet_position--
- return
- else
- bullet_position = null
- playsound(src, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1)
- user.visible_message("[src] goes off!")
- user.apply_damage(200, BRUTE, "head", sharp = 1, used_weapon = "Self-inflicted gunshot wound to the head.")
- user.death()
else
- user.visible_message("[user] lowers [src] from [user.p_their()] head.")
+ user.visible_message("[user] spins the cylinder on [src]!")
+ spin_cylinder()
+
+/obj/item/toy/russian_revolver/attack(mob/M, mob/living/user)
+ return
+
+/obj/item/toy/russian_revolver/afterattack(atom/target, mob/user, flag, params)
+ if(flag)
+ if(target in user.contents)
+ return
+ if(!ismob(target))
+ return
+ shoot_gun(user)
/obj/item/toy/russian_revolver/proc/spin_cylinder()
- bullet_position = rand(1,6)
+ bullets_left = rand(1, max_shots)
+/obj/item/toy/russian_revolver/proc/post_shot(mob/user)
+ return
+
+/obj/item/toy/russian_revolver/proc/shoot_gun(mob/living/carbon/human/user)
+ if(bullets_left > 1)
+ bullets_left--
+ user.visible_message("*click*")
+ playsound(src, 'sound/weapons/empty.ogg', 100, 1)
+ return FALSE
+ if(bullets_left == 1)
+ bullets_left = 0
+ var/zone = "head"
+ if(!(user.has_organ(zone))) // If they somehow don't have a head.
+ zone = "chest"
+ playsound(src, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1)
+ user.visible_message("[src] goes off!")
+ post_shot(user)
+ user.apply_damage(300, BRUTE, zone, sharp = TRUE, used_weapon = "Self-inflicted gunshot wound to the [zone].")
+ user.bleed(BLOOD_VOLUME_NORMAL)
+ user.death() // Just in case
+ return TRUE
+ else
+ to_chat(user, "[src] needs to be reloaded.")
+ return FALSE
+
+/obj/item/toy/russian_revolver/trick_revolver
+ name = "\improper .357 revolver"
+ desc = "A suspicious revolver. Uses .357 ammo."
+ icon_state = "revolver"
+ max_shots = 1
+ var/fake_bullets = 0
+
+/obj/item/toy/russian_revolver/trick_revolver/New()
+ ..()
+ fake_bullets = rand(2, 7)
+
+/obj/item/toy/russian_revolver/trick_revolver/examine(mob/user) //Sneaky sneaky
+ ..()
+ to_chat(user, "Has [fake_bullets] round\s remaining.")
+ to_chat(user, "[fake_bullets] of those are live rounds.")
+
+/obj/item/toy/russian_revolver/trick_revolver/post_shot(user)
+ to_chat(user, "[src] did look pretty dodgey!")
+ SEND_SOUND(user, 'sound/misc/sadtrombone.ogg') //HONK
/*
* Rubber Chainsaw
*/
@@ -1440,6 +1497,18 @@ obj/item/toy/cards/deck/syndicate/black
else
icon_state = "chainsaw0"
+/*
+ * Cat Toy
+ */
+/obj/item/toy/cattoy
+ name = "toy mouse"
+ desc = "A colorful toy mouse!"
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "toy_mouse"
+ w_class = WEIGHT_CLASS_SMALL
+ resistance_flags = FLAMMABLE
+ var/cooldown = 0
+
/*
* Action Figures
*/
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index 109697c3520..ec916a4a228 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -333,7 +333,7 @@ GLOBAL_LIST_INIT(rcd_door_types, list(
return FALSE
playsound(loc, usesound, 50, 1)
var/turf/AT = A
- AT.ChangeTurf(/turf/space)
+ AT.ChangeTurf(AT.baseturf)
return TRUE
return FALSE
to_chat(user, "ERROR! Not enough matter in unit to deconstruct this floor!")
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 150b21692f2..917bf7f032c 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -98,6 +98,8 @@
//alt titles are handled a bit weirdly in order to unobtrusively integrate into existing ID system
var/assignment = null //can be alt title or the actual job
var/rank = null //actual job
+ var/owner_uid
+ var/owner_ckey
var/dorm = 0 // determines if this ID has claimed a dorm already
var/sex
@@ -195,6 +197,19 @@
jobnamedata += " (" + assignment + ")"
return jobnamedata
+/obj/item/card/id/proc/getPlayer()
+ if(owner_uid)
+ var/mob/living/carbon/human/H = locateUID(owner_uid)
+ if(istype(H) && H.ckey == owner_ckey)
+ return H
+ owner_uid = null
+ if(owner_ckey)
+ for(var/mob/M in GLOB.player_list)
+ if(M.ckey && M.ckey == owner_ckey)
+ owner_uid = M.UID()
+ return M
+ owner_ckey = null
+
/obj/item/card/id/proc/is_untrackable()
return untrackable
@@ -310,6 +325,10 @@
origin_tech = "syndicate=1"
var/registered_user = null
untrackable = 1
+ var/anyone = FALSE //Can anyone forge the ID or just syndicate?
+
+/obj/item/card/id/syndicate/anyone
+ anyone = TRUE
/obj/item/card/id/syndicate/New()
access = initial_access.Copy()
@@ -329,7 +348,7 @@
if(istype(O, /obj/item/card/id))
var/obj/item/card/id/I = O
if(istype(user, /mob/living) && user.mind)
- if(user.mind.special_role)
+ if(user.mind.special_role || anyone)
to_chat(usr, "The card's microscanners activate as you pass it over \the [I], copying its access.")
src.access |= I.access //Don't copy access if user isn't an antag -- to prevent metagaming
diff --git a/code/game/objects/items/weapons/caution.dm b/code/game/objects/items/weapons/caution.dm
index a4599a2e79f..b1b573f77ad 100644
--- a/code/game/objects/items/weapons/caution.dm
+++ b/code/game/objects/items/weapons/caution.dm
@@ -26,7 +26,7 @@
return
timing = !timing
if(timing)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
else
armed = 0
timepassed = 0
@@ -34,7 +34,7 @@
/obj/item/caution/proximity_sign/process()
if(!timing)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
timepassed++
if(timepassed >= 15 && !armed)
armed = 1
diff --git a/code/game/objects/items/weapons/chrono_eraser.dm b/code/game/objects/items/weapons/chrono_eraser.dm
index 58c2dd2594f..7e7f1642e3a 100644
--- a/code/game/objects/items/weapons/chrono_eraser.dm
+++ b/code/game/objects/items/weapons/chrono_eraser.dm
@@ -177,7 +177,7 @@
update_icon()
desc = initial(desc) + " It appears to contain [target.name]."
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/effect/chrono_field/Destroy()
if(gun && gun.field_check(src))
diff --git a/code/game/objects/items/weapons/cigs.dm b/code/game/objects/items/weapons/cigs.dm
index 1378b5c004d..fa4b90e0e37 100644
--- a/code/game/objects/items/weapons/cigs.dm
+++ b/code/game/objects/items/weapons/cigs.dm
@@ -31,7 +31,6 @@ LIGHTERS ARE IN LIGHTERS.DM
var/lastHolder = null
var/smoketime = 300
var/chem_volume = 30
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
@@ -48,7 +47,7 @@ LIGHTERS ARE IN LIGHTERS.DM
/obj/item/clothing/mask/cigarette/Destroy()
QDEL_NULL(reagents)
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/clothing/mask/cigarette/attack(mob/living/M, mob/living/user, def_zone)
@@ -161,7 +160,7 @@ LIGHTERS ARE IN LIGHTERS.DM
var/turf/T = get_turf(src)
T.visible_message(flavor_text)
set_light(2, 0.25, "#E38F46")
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/clothing/mask/cigarette/process()
@@ -213,7 +212,7 @@ LIGHTERS ARE IN LIGHTERS.DM
var/mob/living/M = loc
to_chat(M, "Your [name] goes out.")
M.unEquip(src, 1) //Force the un-equip so the overlays update
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
qdel(src)
@@ -341,7 +340,7 @@ LIGHTERS ARE IN LIGHTERS.DM
if(flavor_text)
var/turf/T = get_turf(src)
T.visible_message(flavor_text)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/clothing/mask/cigarette/pipe/process()
var/turf/location = get_turf(src)
@@ -355,7 +354,7 @@ LIGHTERS ARE IN LIGHTERS.DM
icon_state = icon_off
item_state = icon_off
M.update_inv_wear_mask(0)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
smoke()
return
@@ -366,7 +365,7 @@ LIGHTERS ARE IN LIGHTERS.DM
lit = 0
icon_state = icon_off
item_state = icon_off
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
if(smoketime <= 0)
to_chat(user, "You refill the pipe with tobacco.")
diff --git a/code/game/objects/items/weapons/courtroom.dm b/code/game/objects/items/weapons/courtroom.dm
index d25b6f54d29..72bb3fceb11 100644
--- a/code/game/objects/items/weapons/courtroom.dm
+++ b/code/game/objects/items/weapons/courtroom.dm
@@ -16,7 +16,7 @@
/obj/item/gavelhammer/suicide_act(mob/user)
user.visible_message("[user] has sentenced [user.p_them()]self to death with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.")
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/gavelblock
name = "gavel block"
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 758e30947b0..fbdc403d758 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -11,7 +11,6 @@
w_class = WEIGHT_CLASS_BULKY
origin_tech = "biotech=4"
actions_types = list(/datum/action/item_action/toggle_paddles)
- species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/back.dmi'
)
@@ -23,6 +22,9 @@
var/obj/item/stock_parts/cell/high/bcell = null
var/combat = 0 //can we revive through space suits?
+/obj/item/defibrillator/get_cell()
+ return bcell
+
/obj/item/defibrillator/New() //starts without a cell for rnd
..()
paddles = make_paddles()
@@ -283,7 +285,7 @@
user.visible_message("[user] is putting the live paddles on [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide.")
defib.deductcharge(revivecost)
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/twohanded/shockpaddles/dropped(mob/user as mob)
if(user)
@@ -313,7 +315,7 @@
/obj/item/twohanded/shockpaddles/attack(mob/M, mob/user)
var/tobehealed
- var/threshold = -config.health_threshold_dead
+ var/threshold = -HEALTH_THRESHOLD_DEAD
var/mob/living/carbon/human/H = M
if(busy)
@@ -472,7 +474,7 @@
/obj/item/borg_defib/attack(mob/M, mob/user)
var/tobehealed
- var/threshold = -config.health_threshold_dead
+ var/threshold = -HEALTH_THRESHOLD_DEAD
var/mob/living/carbon/human/H = M
if(busy)
diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
index 666c14801d8..736ba1cc767 100644
--- a/code/game/objects/items/weapons/dice.dm
+++ b/code/game/objects/items/weapons/dice.dm
@@ -4,6 +4,7 @@
icon = 'icons/obj/dice.dmi'
icon_state = "dicebag"
can_hold = list(/obj/item/dice)
+ allow_wrap = FALSE
/obj/item/storage/pill_bottle/dice/New()
..()
@@ -25,20 +26,34 @@
if(special_die == "100")
new /obj/item/dice/d100(src)
+/obj/item/storage/pill_bottle/dice/suicide_act(mob/user)
+ user.visible_message("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!")
+ return (OXYLOSS)
+
/obj/item/dice //depreciated d6, use /obj/item/dice/d6 if you actually want a d6
name = "die"
desc = "A die with six sides. Basic and servicable."
icon = 'icons/obj/dice.dmi'
icon_state = "d6"
w_class = WEIGHT_CLASS_TINY
+
var/sides = 6
var/result = null
var/list/special_faces = list() //entries should match up to sides var if used
-/obj/item/dice/New()
- result = rand(1, sides)
+ var/rigged = DICE_NOT_RIGGED
+ var/rigged_value
+
+/obj/item/dice/Initialize(mapload)
+ . = ..()
+ if(!result)
+ result = roll(sides)
update_icon()
+/obj/item/dice/suicide_act(mob/user)
+ user.visible_message("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!")
+ return (OXYLOSS)
+
/obj/item/dice/d1
name = "d1"
desc = "A die with one side. Deterministic!"
@@ -112,17 +127,24 @@
/obj/item/dice/attack_self(mob/user as mob)
diceroll(user)
-/obj/item/dice/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
- if(!..())
- return
- diceroll(thrower)
+/obj/item/dice/throw_impact(atom/target)
+ diceroll(thrownby)
+ . = ..()
/obj/item/dice/proc/diceroll(mob/user)
- result = rand(1, sides)
- var/fake_result = rand(1, sides)//Daredevil isn't as good as he used to be
+ result = roll(sides)
+ if(rigged != DICE_NOT_RIGGED && result != rigged_value)
+ if(rigged == DICE_BASICALLY_RIGGED && prob(Clamp(1/(sides - 1) * 100, 25, 80)))
+ result = rigged_value
+ else if(rigged == DICE_TOTALLY_RIGGED)
+ result = rigged_value
+
+ . = result
+
+ var/fake_result = roll(sides)//Daredevil isn't as good as he used to be
var/comment = ""
if(sides == 20 && result == 20)
- comment = "Nat 20!"
+ comment = "NAT 20!"
else if(sides == 20 && result == 1)
comment = "Ouch, bad luck."
update_icon()
@@ -131,16 +153,18 @@
if(special_faces.len == sides)
result = special_faces[result]
if(user != null) //Dice was rolled in someone's hand
- user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \
+ user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \
"You throw [src]. It lands on [result]. [comment]", \
"You hear [src] rolling, it sounds like a [fake_result].")
- else if(!throwing) //Dice was thrown and is coming to rest
+ else if(!src.throwing) //Dice was thrown and is coming to rest
visible_message("[src] rolls to a stop, landing on [result]. [comment]")
/obj/item/dice/d20/e20/diceroll(mob/user as mob, thrown)
if(triggered)
return
- ..()
+
+ . = ..()
+
if(result == 1)
to_chat(user, "Rocks fall, you die.")
user.gib()
@@ -167,7 +191,7 @@
/obj/item/dice/update_icon()
overlays.Cut()
- overlays += "[src.icon_state][src.result]"
+ overlays += "[icon_state][result]"
/obj/item/storage/box/dice
name = "Box of dice"
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index d2f2ed2c54d..c7627688b5e 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -668,4 +668,27 @@
/obj/item/dnainjector/m2h/Initialize()
block = MONKEYBLOCK
+ ..()
+
+
+/obj/item/dnainjector/comic
+ name = "DNA-Injector (Comic)"
+ desc = "Honk!"
+ datatype = DNA2_BUF_SE
+ value = 0xFFF
+ forcedmutation = TRUE
+
+/obj/item/dnainjector/comic/Initialize()
+ block = COMICBLOCK
+ ..()
+
+/obj/item/dnainjector/anticomic
+ name = "DNA-Injector (Ant-Comic)"
+ desc = "Honk...?"
+ datatype = DNA2_BUF_SE
+ value = 0x001
+ forcedmutation = TRUE
+
+/obj/item/dnainjector/anticomic/Initialize()
+ block = COMICBLOCK
..()
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index be490d29065..c35eed4fae5 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -48,9 +48,9 @@
/obj/item/grenade/plastic/receive_signal()
prime()
-/obj/item/grenade/plastic/Crossed(atom/movable/AM)
+/obj/item/grenade/plastic/Crossed(atom/movable/AM, oldloc)
if(nadeassembly)
- nadeassembly.Crossed(AM)
+ nadeassembly.Crossed(AM, oldloc)
/obj/item/grenade/plastic/on_found(mob/finder)
if(nadeassembly)
@@ -116,6 +116,7 @@
sleep(10)
prime()
user.gib()
+ return OBLITERATION
/obj/item/grenade/plastic/update_icon()
if(nadeassembly)
diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm
index 75d29c7c6be..dd67d7c67a4 100644
--- a/code/game/objects/items/weapons/flamethrower.dm
+++ b/code/game/objects/items/weapons/flamethrower.dm
@@ -33,7 +33,7 @@
/obj/item/flamethrower/process()
if(!lit)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return null
var/turf/location = loc
if(istype(location, /mob/))
@@ -141,7 +141,7 @@
if(!status) return
lit = !lit
if(lit)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
if(href_list["remove"])
if(!ptank) return
usr.put_in_hands(ptank)
diff --git a/code/game/objects/items/weapons/garrote.dm b/code/game/objects/items/weapons/garrote.dm
index 03125313656..4bddaf551ea 100644
--- a/code/game/objects/items/weapons/garrote.dm
+++ b/code/game/objects/items/weapons/garrote.dm
@@ -44,7 +44,7 @@
strangling = null
update_icon()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
else
..()
@@ -97,7 +97,7 @@
M.AdjustSilence(1)
garrote_time = world.time + 10
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
strangling = M
update_icon()
@@ -113,14 +113,14 @@
if(!strangling)
// Our mark got gibbed or similar
update_icon()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
if(!istype(loc, /mob/living/carbon/human))
strangling = null
update_icon()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
var/mob/living/carbon/human/user = loc
@@ -138,7 +138,7 @@
strangling = null
update_icon()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
@@ -148,7 +148,7 @@
strangling = null
update_icon()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
@@ -168,4 +168,4 @@
/obj/item/twohanded/garrote/suicide_act(mob/user)
user.visible_message("[user] is wrapping the [src] around [user.p_their()] neck and pulling the handles! It looks like [user.p_theyre()] trying to commit suicide.")
playsound(src.loc, 'sound/weapons/cablecuff.ogg', 15, 1, -1)
- return (OXYLOSS)
+ return OXYLOSS
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index 7da978a35d1..3e313bcac33 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -239,9 +239,9 @@
if(nadeassembly)
nadeassembly.process_movement()
-/obj/item/grenade/chem_grenade/Crossed(atom/movable/AM)
+/obj/item/grenade/chem_grenade/Crossed(atom/movable/AM, oldloc)
if(nadeassembly)
- nadeassembly.Crossed(AM)
+ nadeassembly.Crossed(AM, oldloc)
/obj/item/grenade/chem_grenade/on_found(mob/finder)
if(nadeassembly)
@@ -289,7 +289,7 @@
var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
var/turf/T = get_turf(src)
var/area/A = get_area(T)
- message_admins("grenade primed by an assembly, attached by [key_name_admin(M)][ADMIN_QUE(M,"(?)")] ([admin_jump_link(M)]) and last touched by [key_name_admin(last)][ADMIN_QUE(last,"(?)")] ([admin_jump_link(last)]) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP). [contained]")
+ message_admins("grenade primed by an assembly, attached by [key_name_admin(M)] and last touched by [key_name_admin(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP). [contained]")
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z]) [contained]")
update_mob()
@@ -419,7 +419,7 @@
var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
var/turf/T = get_turf(src)
var/area/A = get_area(T)
- message_admins("grenade primed by an assembly, attached by [key_name_admin(M)][ADMIN_QUE(M,"(?)")] ([ADMIN_FLW(M,"FLW")]) and last touched by [key_name_admin(last)][ADMIN_QUE(last,"(?)")] ([ADMIN_FLW(last,"FLW")]) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
+ message_admins("grenade primed by an assembly, attached by [key_name_admin(M)] and last touched by [key_name_admin(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
else
addtimer(CALLBACK(src, .proc/prime), det_time)
@@ -446,6 +446,23 @@
update_icon()
+/obj/item/grenade/chem_grenade/firefighting
+ payload_name = "fire fighting grenade"
+ desc = "Can help to put out dangerous fires from a distance."
+ stage = READY
+
+/obj/item/grenade/chem_grenade/firefighting/New()
+ ..()
+ var/obj/item/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent("firefighting_foam", 30)
+ B2.reagents.add_reagent("firefighting_foam", 30)
+
+ beakers += B1
+ beakers += B2
+ update_icon()
+
/obj/item/grenade/chem_grenade/incendiary
payload_name = "incendiary"
desc = "Used for clearing rooms of living things."
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 2e7bacd4426..b0f89c6215b 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -6,6 +6,7 @@
light_power = 10
light_color = LIGHT_COLOR_WHITE
var/light_time = 2
+ var/range = 7
/obj/item/grenade/flashbang/prime()
update_mob()
@@ -15,60 +16,65 @@
set_light(7)
- for(var/mob/living/M in hearers(7, flashbang_turf))
- bang(get_turf(M), M)
+ do_sparks(rand(5, 9), FALSE, src)
+ playsound(flashbang_turf, 'sound/effects/bang.ogg', 25, 1)
+ bang(flashbang_turf, src, range)
- for(var/obj/structure/blob/B in hear(8,flashbang_turf)) //Blob damage here
- var/damage = round(30/(get_dist(B,get_turf(src))+1))
+ for(var/obj/structure/blob/B in hear(8, flashbang_turf)) //Blob damage here
+ var/damage = round(30 / (get_dist(B, get_turf(src)) + 1))
B.health -= damage
B.update_icon()
spawn(light_time)
qdel(src)
-/obj/item/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/M)
- M.show_message("BANG", 2)
- playsound(loc, 'sound/effects/bang.ogg', 25, 1)
+/proc/bang(turf/T, atom/A, range = 7, flash = TRUE, bang = TRUE)
+ for(var/mob/living/M in hearers(range, T))
+ if(M.stat == DEAD)
+ continue
+ M.show_message("BANG", 2)
-//Checking for protections
- var/ear_safety = M.check_ear_prot()
- var/distance = max(1,get_dist(src,T))
+ //Checking for protections
+ var/ear_safety = M.check_ear_prot()
+ var/distance = max(1, get_dist(get_turf(A), get_turf(M)))
-//Flash
- if(M.weakeyes)
- M.visible_message("[M] screams and collapses!")
- to_chat(M, "AAAAGH!")
- M.Weaken(15) //hella stunned
- M.Stun(15)
- if(ishuman(M))
- M.emote("scream")
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes)
- if(E)
- E.receive_damage(8, 1)
+ //Flash
+ if(flash)
+ if(M.weakeyes)
+ M.visible_message("[M] screams and collapses!")
+ to_chat(M, "AAAAGH!")
+ M.Weaken(15) //hella stunned
+ M.Stun(15)
+ if(ishuman(M))
+ M.emote("scream")
+ var/mob/living/carbon/human/H = M
+ var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes)
+ if(E)
+ E.receive_damage(8, 1)
- if(M.flash_eyes(affect_silicon = 1))
- M.Stun(max(10/distance, 3))
- M.Weaken(max(10/distance, 3))
+ if(M.flash_eyes(affect_silicon = TRUE))
+ M.Stun(max(10 / distance, 3))
+ M.Weaken(max(10 / distance, 3))
-//Bang
- if(get_turf(M) == get_turf(src))//Holding on person or being exactly where lies is significantly more dangerous and voids protection
- M.Stun(10)
- M.Weaken(10)
- if(!ear_safety)
- M.Stun(max(10/distance, 3))
- M.Weaken(max(10/distance, 3))
- M.AdjustEarDamage(rand(0, 5), 15)
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears)
- if(istype(ears))
- if(ears.ear_damage >= 15)
- to_chat(M, "Your ears start to ring badly!")
- if(prob(ears.ear_damage - 5))
- to_chat(M, "You can't hear anything!")
- M.BecomeDeaf()
- else
- if(ears.ear_damage >= 5)
- to_chat(M, "Your ears start to ring!")
+ //Bang
+ if(bang)
+ if(!distance || A.loc == M || A.loc == M.loc) //Holding on person or being exactly where lies is significantly more dangerous and voids protection
+ M.Stun(10)
+ M.Weaken(10)
+ if(!ear_safety)
+ M.Stun(max(10 / distance, 3))
+ M.Weaken(max(10 / distance, 3))
+ M.AdjustEarDamage(rand(0, 5), 15)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears)
+ if(istype(ears))
+ if(ears.ear_damage >= 15)
+ to_chat(M, "Your ears start to ring badly!")
+ if(prob(ears.ear_damage - 5))
+ to_chat(M, "You can't hear anything!")
+ M.BecomeDeaf()
+ else
+ if(ears.ear_damage >= 5)
+ to_chat(M, "Your ears start to ring!")
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 7c26e5c405e..28e73f29317 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -24,13 +24,21 @@
if(!istype(C))
return
+ if(flags & NODROP)
+ to_chat(user, "[src] is stuck to your hand!")
+ return
+
if((CLUMSY in user.mutations) && prob(50) && (!ignoresClumsy))
to_chat(user, "Uh... how do those things work?!")
- apply_cuffs(user,user)
-
+ apply_cuffs(user, user)
+ return
+
+ cuff(C, user)
+
+/obj/item/restraints/handcuffs/proc/cuff(mob/living/carbon/C, mob/user, remove_src = TRUE)
if(ishuman(C))
var/mob/living/carbon/human/H = C
- if(!H.has_left_hand() || !H.has_right_hand())
+ if(!(H.has_left_hand() || H.has_right_hand()))
to_chat(user, "How do you suggest handcuffing someone with no hands?")
return
@@ -40,26 +48,31 @@
playsound(loc, cuffsound, 30, 1, -2)
if(do_mob(user, C, 30))
- apply_cuffs(C,user)
+ apply_cuffs(C, user, remove_src)
to_chat(user, "You handcuff [C].")
if(istype(src, /obj/item/restraints/handcuffs/cable))
- feedback_add_details("handcuffs","C")
+ feedback_add_details("handcuffs", "C")
else
- feedback_add_details("handcuffs","H")
+ feedback_add_details("handcuffs", "H")
add_attack_logs(user, C, "Handcuffed ([src])")
else
to_chat(user, "You fail to handcuff [C].")
-/obj/item/restraints/handcuffs/proc/apply_cuffs(mob/living/carbon/target, mob/user)
+/obj/item/restraints/handcuffs/proc/apply_cuffs(mob/living/carbon/target, mob/user, remove_src = TRUE)
if(!target.handcuffed)
- user.drop_item()
+ if(remove_src)
+ user.drop_item()
if(trashtype)
target.handcuffed = new trashtype(target)
- qdel(src)
+ if(remove_src)
+ qdel(src)
else
- loc = target
- target.handcuffed = src
+ if(remove_src)
+ loc = target
+ target.handcuffed = src
+ else
+ target.handcuffed = new type(loc)
target.update_handcuffed()
return
@@ -170,23 +183,7 @@
/obj/item/restraints/handcuffs/cable/zipties/cyborg/attack(mob/living/carbon/C, mob/user)
if(isrobot(user))
- if(ishuman(C))
- var/mob/living/carbon/human/H = C
- if(!(H.get_organ("l_hand") || H.get_organ("r_hand")))
- to_chat(user, "How do you suggest handcuffing someone with no hands?")
- return
- if(!C.handcuffed)
- playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
- C.visible_message("[user] is trying to put zipties on [C]!", \
- "[user] is trying to put zipties on [C]!")
- if(do_mob(user, C, 30))
- if(!C.handcuffed)
- C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
- C.update_handcuffed()
- to_chat(user, "You handcuff [C].")
- add_attack_logs(user, C, "Handcuffed (ziptie-cuffed)")
- else
- to_chat(user, "You fail to handcuff [C].")
+ cuff(C, user, FALSE)
/obj/item/restraints/handcuffs/cable/zipties/used
desc = "A pair of broken zipties."
diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm
index 73ff4e5064d..68e731b8c44 100644
--- a/code/game/objects/items/weapons/holy_weapons.dm
+++ b/code/game/objects/items/weapons/holy_weapons.dm
@@ -15,7 +15,7 @@
/obj/item/nullrod/suicide_act(mob/user)
user.visible_message("[user] is killing [user.p_them()]self with \the [src.name]! It looks like [user.p_theyre()] trying to get closer to god!")
- return (BRUTELOSS|FIRELOSS)
+ return BRUTELOSS|FIRELOSS
/obj/item/nullrod/attack(mob/M, mob/living/carbon/user)
..()
@@ -402,10 +402,10 @@
/obj/item/nullrod/tribal_knife/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/nullrod/tribal_knife/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/nullrod/tribal_knife/process()
@@ -432,10 +432,10 @@
/obj/item/nullrod/rosary/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/nullrod/rosary/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/nullrod/rosary/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
@@ -443,15 +443,15 @@
return ..()
if(!user.mind || !user.mind.isholy)
- to_chat(user, "You are not close enough with [ticker.Bible_deity_name] to use [src].")
+ to_chat(user, "You are not close enough with [SSticker.Bible_deity_name] to use [src].")
return
if(praying)
to_chat(user, "You are already using [src].")
return
- user.visible_message("[user] kneels[M == user ? null : " next to [M]"] and begins to utter a prayer to [ticker.Bible_deity_name].", \
- "You kneel[M == user ? null : " next to [M]"] and begin a prayer to [ticker.Bible_deity_name].")
+ user.visible_message("[user] kneels[M == user ? null : " next to [M]"] and begins to utter a prayer to [SSticker.Bible_deity_name].", \
+ "You kneel[M == user ? null : " next to [M]"] and begin a prayer to [SSticker.Bible_deity_name].")
praying = 1
if(do_after(user, 150, target = M))
@@ -460,18 +460,18 @@
if(target.mind)
if(iscultist(target))
- ticker.mode.remove_cultist(target.mind) // This proc will handle message generation.
+ SSticker.mode.remove_cultist(target.mind) // This proc will handle message generation.
praying = 0
return
if(target.mind.vampire && !target.mind.vampire.get_ability(/datum/vampire_passive/full)) // Getting a full prayer off on a vampire will interrupt their powers for a large duration.
target.mind.vampire.nullified = max(120, target.mind.vampire.nullified + 120)
- to_chat(target, "[user]'s prayer to [ticker.Bible_deity_name] has interfered with your power!")
+ to_chat(target, "[user]'s prayer to [SSticker.Bible_deity_name] has interfered with your power!")
praying = 0
return
if(prob(25))
- to_chat(target, "[user]'s prayer to [ticker.Bible_deity_name] has eased your pain!")
+ to_chat(target, "[user]'s prayer to [SSticker.Bible_deity_name] has eased your pain!")
target.adjustToxLoss(-5)
target.adjustOxyLoss(-5)
target.adjustBruteLoss(-5)
@@ -480,7 +480,7 @@
praying = 0
else
- to_chat(user, "Your prayer to [ticker.Bible_deity_name] was interrupted.")
+ to_chat(user, "Your prayer to [SSticker.Bible_deity_name] was interrupted.")
praying = 0
/obj/item/nullrod/rosary/process()
@@ -506,13 +506,13 @@
/obj/item/nullrod/salt/attack_self(mob/user)
if(!user.mind || !user.mind.isholy)
- to_chat(user, "You are not close enough with [ticker.Bible_deity_name] to use [src].")
+ to_chat(user, "You are not close enough with [SSticker.Bible_deity_name] to use [src].")
return
if(!(ghostcall_CD > world.time))
ghostcall_CD = world.time + 3000 //deciseconds..5 minutes
- user.visible_message("[user] kneels and begins to utter a prayer to [ticker.Bible_deity_name] while drawing a circle with salt!", \
- "You kneel and begin a prayer to [ticker.Bible_deity_name] while drawing a circle!")
+ user.visible_message("[user] kneels and begins to utter a prayer to [SSticker.Bible_deity_name] while drawing a circle with salt!", \
+ "You kneel and begin a prayer to [SSticker.Bible_deity_name] while drawing a circle!")
notify_ghosts("The Chaplain is calling ghosts to [get_area(src)] with [name]!", source = src)
else
to_chat(user, "You need to wait before using [src] again.")
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 9a7c3f0e27c..88dc4ed6542 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -14,7 +14,7 @@
flags = DROPDEL
-/obj/item/implant/proc/trigger(emote, mob/source)
+/obj/item/implant/proc/trigger(emote, mob/source, force)
return
/obj/item/implant/proc/activate()
diff --git a/code/game/objects/items/weapons/implants/implant_abductor.dm b/code/game/objects/items/weapons/implants/implant_abductor.dm
index a86545f8722..64bb7345f7a 100644
--- a/code/game/objects/items/weapons/implants/implant_abductor.dm
+++ b/code/game/objects/items/weapons/implants/implant_abductor.dm
@@ -13,7 +13,7 @@
if(cooldown == total_cooldown)
home.Retrieve(imp_in,1)
cooldown = 0
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
else
to_chat(imp_in, "You must wait [(total_cooldown - cooldown)*2] seconds to use [src] again!")
@@ -21,7 +21,7 @@
if(cooldown < total_cooldown)
cooldown++
if(cooldown == total_cooldown)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
/obj/item/implant/abductor/implant(mob/source, mob/user)
if(..())
diff --git a/code/game/objects/items/weapons/implants/implant_chem.dm b/code/game/objects/items/weapons/implants/implant_chem.dm
index 5f0fea79da9..f1c4dd4126b 100644
--- a/code/game/objects/items/weapons/implants/implant_chem.dm
+++ b/code/game/objects/items/weapons/implants/implant_chem.dm
@@ -33,8 +33,8 @@
-/obj/item/implant/chem/trigger(emote, mob/source)
- if(emote == "deathgasp")
+/obj/item/implant/chem/trigger(emote, mob/source, force)
+ if(force && emote == "deathgasp")
activate(reagents.total_volume)
/obj/item/implant/chem/activate(cause)
diff --git a/code/game/objects/items/weapons/implants/implant_death_alarm.dm b/code/game/objects/items/weapons/implants/implant_death_alarm.dm
index dea34b2ba91..d27d6dd5f7e 100644
--- a/code/game/objects/items/weapons/implants/implant_death_alarm.dm
+++ b/code/game/objects/items/weapons/implants/implant_death_alarm.dm
@@ -3,7 +3,7 @@
desc = "An alarm which monitors host vital signs and transmits a radio message upon death."
var/mobname = "Will Robinson"
activated = 0
- var/static/list/stealth_areas = typecacheof(list(/area/syndicate_station, /area/syndicate_mothership, /area/shuttle/syndicate_elite))
+ var/static/list/stealth_areas = typecacheof(list(/area/syndicate_mothership, /area/shuttle/syndicate_elite))
/obj/item/implant/death_alarm/get_data()
var/dat = {"Implant Specifications:
@@ -18,7 +18,7 @@
return dat
/obj/item/implant/death_alarm/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/implant/death_alarm/process()
@@ -61,12 +61,12 @@
/obj/item/implant/death_alarm/implant(mob/target)
if(..())
mobname = target.real_name
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
return 1
return 0
/obj/item/implant/death_alarm/removed(mob/target)
if(..())
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return 1
return 0
diff --git a/code/game/objects/items/weapons/implants/implant_explosive.dm b/code/game/objects/items/weapons/implants/implant_explosive.dm
index 30113ea4e96..f37e148bee6 100644
--- a/code/game/objects/items/weapons/implants/implant_explosive.dm
+++ b/code/game/objects/items/weapons/implants/implant_explosive.dm
@@ -20,8 +20,8 @@
"}
return dat
-/obj/item/implant/explosive/trigger(emote, mob/source)
- if(emote == "deathgasp")
+/obj/item/implant/explosive/trigger(emote, mob/source, force)
+ if(force && emote == "deathgasp")
activate("death")
/obj/item/implant/explosive/activate(cause)
@@ -148,8 +148,8 @@
"}
return dat
-/obj/item/implant/dust/trigger(emote, mob/source)
- if(emote == "deathgasp")
+/obj/item/implant/dust/trigger(emote, mob/source, force)
+ if(force && emote == "deathgasp")
activate("death")
/obj/item/implant/dust/activate(cause)
diff --git a/code/game/objects/items/weapons/implants/implant_mindshield.dm b/code/game/objects/items/weapons/implants/implant_mindshield.dm
index 739fe2827e4..bc942b73d81 100644
--- a/code/game/objects/items/weapons/implants/implant_mindshield.dm
+++ b/code/game/objects/items/weapons/implants/implant_mindshield.dm
@@ -19,14 +19,14 @@
/obj/item/implant/mindshield/implant(mob/target)
if(..())
- if(target.mind in ticker.mode.head_revolutionaries || is_shadow_or_thrall(target))
+ if(target.mind in SSticker.mode.head_revolutionaries || is_shadow_or_thrall(target))
target.visible_message("[target] seems to resist the implant!", "You feel the corporate tendrils of Nanotrasen try to invade your mind!")
removed(target, 1)
qdel(src)
return -1
- if(target.mind in ticker.mode.revolutionaries)
- ticker.mode.remove_revolutionary(target.mind)
- if(target.mind in ticker.mode.cult)
+ if(target.mind in SSticker.mode.revolutionaries)
+ SSticker.mode.remove_revolutionary(target.mind)
+ if(target.mind in SSticker.mode.cult)
to_chat(target, "You feel the corporate tendrils of Nanotrasen try to invade your mind!")
else
to_chat(target, "Your mind feels hardened - more resistant to brainwashing.")
diff --git a/code/game/objects/items/weapons/implants/implant_traitor.dm b/code/game/objects/items/weapons/implants/implant_traitor.dm
index 58f78a7be4e..16d8943567d 100644
--- a/code/game/objects/items/weapons/implants/implant_traitor.dm
+++ b/code/game/objects/items/weapons/implants/implant_traitor.dm
@@ -45,15 +45,15 @@
return -1
H.implanting = 1
to_chat(H, "You feel completely loyal to [user.name].")
- if(!(user.mind in ticker.mode.implanter))
- ticker.mode.implanter[ref] = list()
- implanters = ticker.mode.implanter[ref]
+ if(!(user.mind in SSticker.mode.implanter))
+ SSticker.mode.implanter[ref] = list()
+ implanters = SSticker.mode.implanter[ref]
implanters.Add(H.mind)
- ticker.mode.implanted.Add(H.mind)
- ticker.mode.implanted[H.mind] = user.mind
- //ticker.mode.implanter[user.mind] += H.mind
- ticker.mode.implanter[ref] = implanters
- ticker.mode.traitors += H.mind
+ SSticker.mode.implanted.Add(H.mind)
+ SSticker.mode.implanted[H.mind] = user.mind
+ //SSticker.mode.implanter[user.mind] += H.mind
+ SSticker.mode.implanter[ref] = implanters
+ SSticker.mode.traitors += H.mind
H.mind.special_role = SPECIAL_ROLE_TRAITOR
to_chat(H, "You're now completely loyal to [user.name]! You now must lay down your life to protect [user.p_them()] and assist in [user.p_their()] goals at any cost.")
var/datum/objective/protect/mindslave/MS = new
@@ -64,8 +64,8 @@
for(var/datum/objective/objective in H.mind.objectives)
to_chat(H, "Objective #1: [objective.explanation_text]")
- ticker.mode.update_traitor_icons_added(user.mind)
- ticker.mode.update_traitor_icons_added(H.mind)//handles datahuds/observerhuds
+ SSticker.mode.update_traitor_icons_added(user.mind)
+ SSticker.mode.update_traitor_icons_added(H.mind)//handles datahuds/observerhuds
if(user.mind.som)//do not add if not a traitor..and you just picked up an implanter in the hall...
var/datum/mindslaves/slaved = user.mind.som
@@ -77,12 +77,12 @@
log_admin("[key_name(user)] has mind-slaved [key_name(H)].")
activated = 1
if(jobban_isbanned(M, ROLE_SYNDICATE))
- ticker.mode.replace_jobbanned_player(M, ROLE_SYNDICATE)
+ SSticker.mode.replace_jobbanned_player(M, ROLE_SYNDICATE)
return 1
return 0
/obj/item/implant/traitor/removed(mob/target)
if(..())
- ticker.mode.remove_traitor_mind(target.mind)
+ SSticker.mode.remove_traitor_mind(target.mind)
return 1
return 0
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm
index a0810a0b96c..4f94a6b8a1b 100644
--- a/code/game/objects/items/weapons/kitchen.dm
+++ b/code/game/objects/items/weapons/kitchen.dm
@@ -121,7 +121,7 @@
user.visible_message(pick("[user] is slitting [user.p_their()] wrists with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.", \
"[user] is slitting [user.p_their()] throat with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.", \
"[user] is slitting [user.p_their()] stomach open with the [name]! It looks like [user.p_theyre()] trying to commit seppuku."))
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/kitchen/knife/plastic
name = "plastic knife"
@@ -165,6 +165,22 @@
origin_tech = "materials=3;combat=4"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
+/obj/item/kitchen/knife/combat/survival
+ name = "survival knife"
+ icon_state = "survivalknife"
+ desc = "A hunting grade survival knife."
+ force = 15
+ throwforce = 15
+
+/obj/item/kitchen/knife/combat/survival/bone
+ name = "bone dagger"
+ item_state = "bone_dagger"
+ icon_state = "bone_dagger"
+ lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/items_righthand.dmi'
+ desc = "A sharpened bone. The bare minimum in survival."
+ materials = list()
+
/obj/item/kitchen/knife/combat/cyborg
name = "cyborg knife"
icon = 'icons/obj/items_cyborg.dmi'
diff --git a/code/game/objects/items/weapons/legcuffs.dm b/code/game/objects/items/weapons/legcuffs.dm
index 3391687f20a..77ae8fc73bb 100644
--- a/code/game/objects/items/weapons/legcuffs.dm
+++ b/code/game/objects/items/weapons/legcuffs.dm
@@ -35,7 +35,7 @@
/obj/item/restraints/legcuffs/beartrap/suicide_act(mob/user)
user.visible_message("[user] is sticking [user.p_their()] head in the [name]! It looks like [user.p_theyre()] trying to commit suicide.")
playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/restraints/legcuffs/beartrap/attack_self(mob/user)
..()
@@ -87,7 +87,7 @@
return
..()
-/obj/item/restraints/legcuffs/beartrap/Crossed(AM as mob|obj)
+/obj/item/restraints/legcuffs/beartrap/Crossed(AM as mob|obj, oldloc)
if(armed && isturf(src.loc))
if( (iscarbon(AM) || isanimal(AM)) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/hostile/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator))
var/mob/living/L = AM
@@ -152,8 +152,14 @@
breakouttime = 35//easy to apply, easy to break out of
gender = NEUTER
origin_tech = "engineering=3;combat=1"
+ hitsound = 'sound/effects/snap.ogg'
var/weaken = 0
+/obj/item/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
+ playsound(loc,'sound/weapons/bolathrow.ogg', 50, TRUE)
+ if(!..())
+ return
+
/obj/item/restraints/legcuffs/bola/throw_impact(atom/hit_atom)
if(..() || !iscarbon(hit_atom))//if it gets caught or the target can't be cuffed,
return//abort
@@ -166,6 +172,7 @@
feedback_add_details("handcuffs","B")
to_chat(C, "[src] ensnares you!")
C.Weaken(weaken)
+ playsound(loc, hitsound, 50, TRUE)
/obj/item/restraints/legcuffs/bola/tactical //traitor variant
name = "reinforced bola"
@@ -186,6 +193,6 @@
/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom)
if(iscarbon(hit_atom))
var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom))
- B.Crossed(hit_atom)
+ B.Crossed(hit_atom, null)
qdel(src)
..()
diff --git a/code/game/objects/items/weapons/lighters.dm b/code/game/objects/items/weapons/lighters.dm
index a2d8b03da84..ab946de5f0f 100644
--- a/code/game/objects/items/weapons/lighters.dm
+++ b/code/game/objects/items/weapons/lighters.dm
@@ -58,7 +58,7 @@
user.visible_message("After a few attempts, [user] manages to light the [src], [user.p_they()] however burn[user.p_s()] [user.p_their()] finger in the process.")
set_light(2)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
else
lit = 0
w_class = WEIGHT_CLASS_TINY
@@ -74,7 +74,7 @@
user.visible_message("[user] quietly shuts off the [src].")
set_light(0)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
else
return ..()
return
@@ -181,7 +181,7 @@
name = "lit match"
desc = "A match. This one is lit."
attack_verb = list("burnt","singed")
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
update_icon()
return TRUE
@@ -196,7 +196,7 @@
name = "burnt match"
desc = "A match. This one has seen better days."
attack_verb = list("flicked")
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return TRUE
/obj/item/match/dropped(mob/user)
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 8ad283a77da..5e8d170f50b 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -2,6 +2,8 @@
var/active = 0
var/force_on = 30 //force when active
var/throwforce_on = 20
+ var/faction_bonus_force = 0 //Bonus force dealt against certain factions
+ var/list/nemesis_factions //Any mob with a faction that exists in this list will take bonus damage/effects
w_class = WEIGHT_CLASS_SMALL
var/w_class_on = WEIGHT_CLASS_BULKY
var/icon_state_on = "axe1"
@@ -13,10 +15,23 @@
var/brightness_on = 2
var/colormap = list(red=LIGHT_COLOR_RED, blue=LIGHT_COLOR_LIGHTBLUE, green=LIGHT_COLOR_GREEN, purple=LIGHT_COLOR_PURPLE, rainbow=LIGHT_COLOR_WHITE)
+/obj/item/melee/energy/attack(mob/living/target, mob/living/carbon/human/user)
+ var/nemesis_faction = FALSE
+ if(LAZYLEN(nemesis_factions))
+ for(var/F in target.faction)
+ if(F in nemesis_factions)
+ nemesis_faction = TRUE
+ force += faction_bonus_force
+ nemesis_effects(user, target)
+ break
+ . = ..()
+ if(nemesis_faction)
+ force -= faction_bonus_force
+
/obj/item/melee/energy/suicide_act(mob/user)
user.visible_message(pick("[user] is slitting [user.p_their()] stomach open with the [name]! It looks like [user.p_theyre()] trying to commit seppuku.", \
"[user] is falling on the [name]! It looks like [user.p_theyre()] trying to commit suicide."))
- return (BRUTELOSS|FIRELOSS)
+ return BRUTELOSS|FIRELOSS
/obj/item/melee/energy/attack_self(mob/living/carbon/user)
if(user.disabilities & CLUMSY && prob(50))
@@ -81,7 +96,7 @@
/obj/item/melee/energy/axe/suicide_act(mob/user)
user.visible_message("[user] swings the [name] towards [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide.")
- return (BRUTELOSS|FIRELOSS)
+ return BRUTELOSS|FIRELOSS
/obj/item/melee/energy/sword
name = "energy sword"
@@ -225,3 +240,127 @@
desc = "An extremely sharp blade made out of hard light. Packs quite a punch."
icon_state = "lightblade"
item_state = "lightblade"
+
+/obj/item/melee/energy/proc/nemesis_effects(mob/living/user, mob/living/target)
+ return
+
+/obj/item/melee/energy/cleaving_saw
+ name = "cleaving saw"
+ desc = "This saw, effective at drawing the blood of beasts, transforms into a long cleaver that makes use of centrifugal force."
+ force = 12
+ force_on = 20 //force when active
+ throwforce = 20
+ throwforce_on = 20
+ icon = 'icons/obj/lavaland/artefacts.dmi'
+ lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
+ inhand_x_dimension = 64
+ inhand_y_dimension = 64
+ icon_state = "cleaving_saw"
+ icon_state_on = "cleaving_saw_open"
+ slot_flags = SLOT_BELT
+ var/attack_verb_off = list("attacked", "sawed", "sliced", "torn", "ripped", "diced", "cut")
+ attack_verb_on = list("cleaved", "swiped", "slashed", "chopped")
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ w_class = WEIGHT_CLASS_BULKY
+ sharp = TRUE
+ faction_bonus_force = 30
+ nemesis_factions = list("mining", "boss")
+ var/transform_cooldown
+ var/swiping = FALSE
+
+/obj/item/melee/energy/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target)
+ var/datum/status_effect/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED)
+ if(!B)
+ if(!active) //This isn't in the above if-check so that the else doesn't care about active
+ target.apply_status_effect(STATUS_EFFECT_SAWBLEED)
+ else
+ B.add_bleed(B.bleed_buildup)
+
+/obj/item/melee/energy/cleaving_saw/attack_self(mob/living/carbon/user)
+ transform_weapon(user)
+
+/obj/item/melee/energy/cleaving_saw/proc/transform_weapon(mob/living/user, supress_message_text)
+ if(transform_cooldown > world.time)
+ return FALSE
+
+ transform_cooldown = world.time + (CLICK_CD_MELEE * 0.5)
+ user.changeNext_move(CLICK_CD_MELEE * 0.25)
+
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.disabilities & CLUMSY && prob(50))
+ to_chat(H, "You accidentally cut yourself with [src], like a doofus!")
+ H.take_organ_damage(10,10)
+ active = !active
+ if(active)
+ force = force_on
+ throwforce = throwforce_on
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ throw_speed = 4
+ if(attack_verb_on.len)
+ attack_verb = attack_verb_on
+ if(!item_color)
+ icon_state = icon_state_on
+ set_light(brightness_on)
+ else
+ icon_state = "sword[item_color]"
+ set_light(brightness_on, l_color=colormap[item_color])
+ w_class = w_class_on
+ playsound(user, 'sound/magic/fellowship_armory.ogg', 35, TRUE, frequency = 90000 - (active * 30000))
+ to_chat(user, "You open [src]. It will now cleave enemies in a wide arc and deal additional damage to fauna.")
+ else
+ force = initial(force)
+ throwforce = initial(throwforce)
+ hitsound = initial(hitsound)
+ throw_speed = initial(throw_speed)
+ if(attack_verb_on.len)
+ attack_verb = list()
+ icon_state = initial(icon_state)
+ w_class = initial(w_class)
+ playsound(user, 'sound/magic/fellowship_armory.ogg', 35, 1) //changed it from 50% volume to 35% because deafness
+ set_light(0)
+ to_chat(user, "You close [src]. It will now attack rapidly and cause fauna to bleed.")
+
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ H.update_inv_l_hand()
+ H.update_inv_r_hand()
+
+ add_fingerprint(user)
+
+/obj/item/melee/energy/cleaving_saw/examine(mob/user)
+ ..()
+ to_chat(user, "It is [active ? "open, will cleave enemies in a wide arc and deal additional damage to fauna":"closed, and can be used for rapid consecutive attacks that cause fauna to bleed"]. \
+ Both modes will build up existing bleed effects, doing a burst of high damage if the bleed is built up high enough. \
+ Transforming it immediately after an attack causes the next attack to come out faster.")
+
+/obj/item/melee/energy/cleaving_saw/suicide_act(mob/user)
+ user.visible_message("[user] is [active ? "closing [src] on [user.p_their()] neck" : "opening [src] into [user.p_their()] chest"]! It looks like [user.p_theyre()] trying to commit suicide!")
+ transform_cooldown = 0
+ transform_weapon(user, TRUE)
+ return BRUTELOSS
+
+/obj/item/melee/energy/cleaving_saw/melee_attack_chain(mob/user, atom/target, params)
+ ..()
+ if(!active)
+ user.changeNext_move(CLICK_CD_MELEE * 0.5) //when closed, it attacks very rapidly
+
+/obj/item/melee/energy/cleaving_saw/attack(mob/living/target, mob/living/carbon/human/user)
+ if(!active || swiping || !target.density || get_turf(target) == get_turf(user))
+ if(!active)
+ faction_bonus_force = 0
+ ..()
+ if(!active)
+ faction_bonus_force = initial(faction_bonus_force)
+ else
+ var/turf/user_turf = get_turf(user)
+ var/dir_to_target = get_dir(user_turf, get_turf(target))
+ swiping = TRUE
+ var/static/list/cleaving_saw_cleave_angles = list(0, -45, 45) //so that the animation animates towards the target clicked and not towards a side target
+ for(var/i in cleaving_saw_cleave_angles)
+ var/turf/T = get_step(user_turf, turn(dir_to_target, i))
+ for(var/mob/living/L in T)
+ if(user.Adjacent(L) && L.density)
+ melee_attack_chain(user, L)
+ swiping = FALSE
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm
index a19df11e790..943d20e9699 100644
--- a/code/game/objects/items/weapons/melee/misc.dm
+++ b/code/game/objects/items/weapons/melee/misc.dm
@@ -1,6 +1,13 @@
/obj/item/melee
needs_permit = 1
+/obj/item/melee/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user)
+ if(target.check_block())
+ target.visible_message("[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!",
+ "You block the attack!")
+ user.Stun(2)
+ return TRUE
+
/obj/item/melee/chainofcommand
name = "chain of command"
desc = "A tool used by great men to placate the frothing masses."
@@ -17,8 +24,8 @@
/obj/item/melee/chainofcommand/suicide_act(mob/user)
- to_chat(viewers(user), "[user] is strangling [user.p_them()]self with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.")
- return (OXYLOSS)
+ to_chat(viewers(user), "[user] is strangling [user.p_them()]self with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.")
+ return OXYLOSS
/obj/item/melee/rapier
name = "captain's rapier"
@@ -60,4 +67,38 @@
force = 10
throwforce = 7
w_class = WEIGHT_CLASS_NORMAL
- attack_verb = list("slashed", "stabbed", "sliced", "caned")
\ No newline at end of file
+ attack_verb = list("slashed", "stabbed", "sliced", "caned")
+
+/obj/item/melee/flyswatter
+ name = "flyswatter"
+ desc = "Useful for killing insects of all sizes."
+ icon_state = "flyswatter"
+ item_state = "flyswatter"
+ force = 1
+ throwforce = 1
+ attack_verb = list("swatted", "smacked")
+ hitsound = 'sound/effects/snap.ogg'
+ w_class = WEIGHT_CLASS_SMALL
+ //Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc.
+ var/list/strong_against
+
+/obj/item/melee/flyswatter/Initialize(mapload)
+ . = ..()
+ strong_against = typecacheof(list(
+ /mob/living/simple_animal/hostile/poison/bees/,
+ /mob/living/simple_animal/butterfly,
+ /mob/living/simple_animal/cockroach,
+ /obj/item/queen_bee
+ ))
+
+/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag)
+ . = ..()
+ if(proximity_flag)
+ if(is_type_in_typecache(target, strong_against))
+ new /obj/effect/decal/cleanable/insectguts(target.drop_location())
+ to_chat(user, "You easily splat the [target].")
+ if(istype(target, /mob/living/))
+ var/mob/living/bug = target
+ bug.death(1)
+ else
+ qdel(target)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm
index e642e3b994a..7c5c6f9421f 100644
--- a/code/game/objects/items/weapons/mop.dm
+++ b/code/game/objects/items/weapons/mop.dm
@@ -89,14 +89,14 @@
/obj/item/mop/advanced/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/mop/advanced/attack_self(mob/user)
refill_enabled = !refill_enabled
if(refill_enabled)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
else
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
to_chat(user, "You set the condenser switch to the '[refill_enabled ? "ON" : "OFF"]' position.")
playsound(user, 'sound/machines/click.ogg', 30, 1)
@@ -111,7 +111,7 @@
/obj/item/mop/advanced/Destroy()
if(refill_enabled)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm
index 63a3ffef0c5..4381c4295c7 100644
--- a/code/game/objects/items/weapons/rpd.dm
+++ b/code/game/objects/items/weapons/rpd.dm
@@ -4,6 +4,9 @@
#define RPD_COOLDOWN_TIME 4 //How long should we have to wait between dispensing pipes?
#define RPD_WALLBUILD_TIME 40 //How long should drilling into a wall take?
+#define RPD_MENU_ROTATE "Rotate pipes" //Stuff for radial menu
+#define RPD_MENU_FLIP "Flip pipes" //Stuff for radial menu
+#define RPD_MENU_DELETE "Delete pipes" //Stuff for radial menu
/obj/item/rpd
name = "rapid pipe dispenser"
@@ -172,6 +175,9 @@ var/list/pipemenu = list(
ui.open()
ui.set_auto_update(1)
+/obj/item/rpd/AltClick(mob/user)
+ radial_menu(user)
+
/obj/item/rpd/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state)
var/data[0]
data["iconrotation"] = iconrotation
@@ -200,6 +206,44 @@ var/list/pipemenu = list(
return
SSnanoui.update_uis(src)
+//RPD radial menu
+
+/obj/item/rpd/proc/check_menu(mob/living/user)
+ if(!istype(user))
+ return
+ if(user.incapacitated())
+ return
+ if(loc != user)
+ return
+ return TRUE
+
+/obj/item/rpd/proc/radial_menu(mob/user)
+ if(!check_menu(user))
+ to_chat(user, "You can't do that right now!")
+ return
+ var/list/choices = list(
+ RPD_MENU_ROTATE = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_rotate"),
+ RPD_MENU_FLIP = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_flip"),
+ RPD_MENU_DELETE = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_delete"),
+ "UI" = image(icon = 'icons/obj/interface.dmi', icon_state = "ui_interact")
+ )
+ var/selected_mode = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user))
+ if(!check_menu(user))
+ return
+ if(selected_mode == "UI")
+ ui_interact(user)
+ else
+ switch(selected_mode)
+ if(RPD_MENU_ROTATE)
+ mode = RPD_ROTATE_MODE
+ if(RPD_MENU_FLIP)
+ mode = RPD_FLIP_MODE
+ if(RPD_MENU_DELETE)
+ mode = RPD_DELETE_MODE
+ else
+ return //Either nothing was selected, or an invalid mode was selected
+ to_chat(user, "You set [src]'s mode.")
+
/obj/item/rpd/afterattack(atom/target, mob/user, proximity)
..()
if(loc != user)
@@ -236,3 +280,6 @@ var/list/pipemenu = list(
#undef RPD_COOLDOWN_TIME
#undef RPD_WALLBUILD_TIME
+#undef RPD_MENU_ROTATE
+#undef RPD_MENU_FLIP
+#undef RPD_MENU_DELETE
diff --git a/code/game/objects/items/weapons/scrolls.dm b/code/game/objects/items/weapons/scrolls.dm
index 8f6ffc96e1c..ccee6c18feb 100644
--- a/code/game/objects/items/weapons/scrolls.dm
+++ b/code/game/objects/items/weapons/scrolls.dm
@@ -47,7 +47,11 @@
var/A
- A = input(user, "Area to jump to", "BOOYEA", A) in teleportlocs
+ A = input(user, "Area to jump to", "BOOYEA", A) as null|anything in teleportlocs
+
+ if(!A)
+ return
+
var/area/thearea = teleportlocs[A]
if(user.stat || user.restrained())
diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm
index 88de9de1b11..4c8697da247 100644
--- a/code/game/objects/items/weapons/shards.dm
+++ b/code/game/objects/items/weapons/shards.dm
@@ -18,7 +18,7 @@
/obj/item/shard/suicide_act(mob/user)
to_chat(viewers(user), pick("[user] is slitting [user.p_their()] wrists with [src]! It looks like [user.p_theyre()] trying to commit suicide.",
"[user] is slitting [user.p_their()] throat with [src]! It looks like [user.p_theyre()] trying to commit suicide."))
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/shard/New()
..()
@@ -67,7 +67,7 @@
else
return ..()
-/obj/item/shard/Crossed(AM as mob|obj)
+/obj/item/shard/Crossed(AM as mob|obj, oldloc)
if(isliving(AM))
var/mob/living/M = AM
if(M.incorporeal_move || M.flying || M.throwing)//you are incorporal or flying or being thrown ..no shard stepping!
diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm
index 742f5b3d0c0..912212d19c7 100644
--- a/code/game/objects/items/weapons/soap.dm
+++ b/code/game/objects/items/weapons/soap.dm
@@ -4,6 +4,8 @@
gender = PLURAL
icon = 'icons/obj/items.dmi'
icon_state = "soap"
+ lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
w_class = WEIGHT_CLASS_TINY
throwforce = 0
throw_speed = 4
diff --git a/code/game/objects/items/weapons/staff.dm b/code/game/objects/items/weapons/staff.dm
index 54ef5f06f85..15b0b914391 100644
--- a/code/game/objects/items/weapons/staff.dm
+++ b/code/game/objects/items/weapons/staff.dm
@@ -27,7 +27,7 @@
if(user)
user.update_inv_l_hand()
user.update_inv_r_hand()
- if(user.mind in ticker.mode.wizards)
+ if(user.mind in SSticker.mode.wizards)
user.flying = wielded ? 1 : 0
if(wielded)
to_chat(user, "You hold \the [src] between your legs.")
diff --git a/code/game/objects/items/weapons/storage/artistic_toolbox.dm b/code/game/objects/items/weapons/storage/artistic_toolbox.dm
index 4293c0a6167..0d8613cce4a 100644
--- a/code/game/objects/items/weapons/storage/artistic_toolbox.dm
+++ b/code/game/objects/items/weapons/storage/artistic_toolbox.dm
@@ -176,10 +176,6 @@
affected_mob.SetSleeping(0)
affected_mob.SetSlowed(0)
affected_mob.SetConfused(0)
- if(ishuman(affected_mob))
- var/mob/living/carbon/human/H = affected_mob
- if(H.traumatic_shock < 100)
- H.shock_stage = 0
stage = 1
switch(progenitor.hunger)
if(10 to 60)
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index 8df4b17251d..3f638d44918 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -17,7 +17,6 @@
storage_slots = 21
burn_state = FLAMMABLE
burntime = 20
- species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/back.dmi'
)
@@ -52,6 +51,7 @@
desc = "A backpack that opens into a localized pocket of Blue Space."
origin_tech = "bluespace=5;materials=4;engineering=4;plasmatech=5"
icon_state = "holdingpack"
+ item_state = "holdingpack"
max_w_class = WEIGHT_CLASS_HUGE
max_combined_w_class = 35
burn_state = FIRE_PROOF
@@ -112,7 +112,7 @@
..()
new /obj/item/clothing/under/rank/clown(src)
new /obj/item/clothing/shoes/magboots/clown(src)
- new /obj/item/clothing/mask/gas/voice/clown(src)
+ new /obj/item/clothing/mask/chameleon(src)
new /obj/item/radio/headset/headset_service(src)
new /obj/item/pda/clown(src)
new /obj/item/storage/box/survival(src)
@@ -124,6 +124,7 @@
new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(src)
new /obj/item/instrument/bikehorn(src)
new /obj/item/bikehorn(src)
+ new /obj/item/dnainjector/comic(src)
/obj/item/storage/backpack/mime
name = "Parcel Parceaux"
@@ -157,6 +158,12 @@
item_state = "engiepack"
burn_state = FIRE_PROOF
+/obj/item/storage/backpack/explorer
+ name = "explorer bag"
+ desc = "A robust backpack for stashing your loot."
+ icon_state = "explorerpack"
+ item_state = "explorerpack"
+
/obj/item/storage/backpack/botany
name = "botany backpack"
desc = "It's a backpack made of all-natural fibers."
@@ -234,6 +241,12 @@
icon_state = "satchel-eng"
burn_state = FIRE_PROOF
+/obj/item/storage/backpack/satchel/explorer
+ name = "explorer satchel"
+ desc = "A robust satchel for stashing your loot."
+ icon_state = "satchel-explorer"
+ item_state = "securitypack"
+
/obj/item/storage/backpack/satchel_med
name = "medical satchel"
desc = "A sterile satchel used in medical departments."
@@ -315,7 +328,7 @@
/obj/item/storage/backpack/duffel/syndie
name = "suspicious looking duffelbag"
desc = "A large duffelbag for holding extra tactical supplies."
- icon_state = "duffel-syndi"
+ icon_state = "duffel-syndie"
item_state = "duffel-syndimed"
origin_tech = "syndicate=1"
silent = 1
@@ -333,21 +346,79 @@
icon_state = "duffel-syndiammo"
item_state = "duffel-syndiammo"
-/obj/item/storage/backpack/duffel/syndie/ammo/loaded
+/obj/item/storage/backpack/duffel/syndie/ammo/shotgun
desc = "A large duffelbag, packed to the brim with Bulldog shotgun ammo."
-/obj/item/storage/backpack/duffel/syndie/ammo/loaded/New()
+/obj/item/storage/backpack/duffel/syndie/ammo/shotgun/New()
..()
- new /obj/item/ammo_box/magazine/m12g(src)
- new /obj/item/ammo_box/magazine/m12g(src)
- new /obj/item/ammo_box/magazine/m12g(src)
- new /obj/item/ammo_box/magazine/m12g(src)
- new /obj/item/ammo_box/magazine/m12g(src)
- new /obj/item/ammo_box/magazine/m12g(src)
+ for(var/i in 1 to 6)
+ new /obj/item/ammo_box/magazine/m12g(src)
+ new /obj/item/ammo_box/magazine/m12g/buckshot(src)
new /obj/item/ammo_box/magazine/m12g/buckshot(src)
- new /obj/item/ammo_box/magazine/m12g/stun(src)
new /obj/item/ammo_box/magazine/m12g/dragon(src)
+/obj/item/storage/backpack/duffel/mining_conscript/noid
+ name = "mining conscription kit"
+ desc = "A kit containing everything a crewmember needs to support a shaft miner in the field."
+
+/obj/item/storage/backpack/duffel/mining_conscript/noid/New()
+ ..()
+ new /obj/item/pickaxe(src)
+ new /obj/item/clothing/glasses/meson(src)
+ new /obj/item/t_scanner/adv_mining_scanner/lesser(src)
+ new /obj/item/storage/bag/ore(src)
+ new /obj/item/clothing/under/rank/miner/lavaland(src)
+ new /obj/item/encryptionkey/headset_cargo(src)
+ new /obj/item/clothing/mask/gas(src)
+
+
+/obj/item/storage/backpack/duffel/syndie/ammo/smg
+ desc = "A large duffel bag, packed to the brim with C-20r magazines."
+
+/obj/item/storage/backpack/duffel/syndie/ammo/smg/New()
+ ..()
+ for(var/i in 1 to 10)
+ new /obj/item/ammo_box/magazine/smgm45(src)
+
+/obj/item/storage/backpack/duffel/syndie/c20rbundle
+ desc = "A large duffel bag containing a C-20r, some magazines, and a cheap looking suppressor."
+
+/obj/item/storage/backpack/duffel/syndie/c20rbundle/New()
+ ..()
+ new /obj/item/ammo_box/magazine/smgm45(src)
+ new /obj/item/ammo_box/magazine/smgm45(src)
+ new /obj/item/gun/projectile/automatic/c20r(src)
+ new /obj/item/suppressor/specialoffer(src)
+
+/obj/item/storage/backpack/duffel/syndie/bulldogbundle
+ desc = "A large duffel bag containing a Bulldog, some drums, and a pair of thermal imaging glasses."
+
+/obj/item/storage/backpack/duffel/syndie/bulldogbundle/New()
+ ..()
+ new /obj/item/gun/projectile/automatic/shotgun/bulldog(src)
+ new /obj/item/ammo_box/magazine/m12g(src)
+ new /obj/item/ammo_box/magazine/m12g(src)
+ new /obj/item/clothing/glasses/chameleon/thermal(src)
+
+/obj/item/storage/backpack/duffel/syndie/med/medicalbundle
+ desc = "A large duffel bag containing a tactical medkit, a Donksoft machine gun and a big jumbo box of riot darts."
+
+/obj/item/storage/backpack/duffel/syndie/med/medicalbundle/New()
+ ..()
+ new /obj/item/storage/firstaid/tactical(src)
+ new /obj/item/gun/projectile/automatic/l6_saw/toy(src)
+ new /obj/item/ammo_box/foambox/riot(src)
+
+/obj/item/storage/backpack/duffel/syndie/c4/New()
+ ..()
+ for(var/i in 1 to 10)
+ new /obj/item/grenade/plastic/c4(src)
+
+/obj/item/storage/backpack/duffel/syndie/x4/New()
+ ..()
+ for(var/i in 1 to 3)
+ new /obj/item/grenade/plastic/x4(src)
+
/obj/item/storage/backpack/duffel/syndie/surgery
name = "surgery duffelbag"
desc = "A suspicious looking duffelbag for holding surgery tools."
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index 2fd7d774113..e8a181a197b 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -42,7 +42,7 @@
/obj/item/storage/bag/trash/suicide_act(mob/user)
user.visible_message("[user] puts the [name] over [user.p_their()] head and starts chomping at the insides! Disgusting!")
playsound(loc, 'sound/items/eatfood.ogg', 50, 1, -1)
- return (TOXLOSS)
+ return TOXLOSS
/obj/item/storage/bag/trash/update_icon()
if(contents.len == 0)
@@ -107,7 +107,7 @@
/obj/item/storage/bag/plasticbag/equipped(var/mob/user, var/slot)
if(slot==slot_head)
storage_slots = 0
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
return
/obj/item/storage/bag/plasticbag/process()
@@ -120,7 +120,7 @@
H.AdjustLoseBreath(1)
else
storage_slots = 7
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
// -----------------------------
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index c52d4db7e5b..7a66c250e94 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -4,23 +4,22 @@
icon = 'icons/obj/clothing/belts.dmi'
icon_state = "utilitybelt"
item_state = "utility"
+ lefthand_file = 'icons/mob/inhands/equipment/belt_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/belt_righthand.dmi'
slot_flags = SLOT_BELT
attack_verb = list("whipped", "lashed", "disciplined")
var/use_item_overlays = 0 // Do we have overlays for items held inside the belt?
-
/obj/item/storage/belt/update_icon()
if(use_item_overlays)
overlays.Cut()
for(var/obj/item/I in contents)
overlays += "[I.name]"
-
..()
/obj/item/storage/belt/proc/can_use()
return is_equipped()
-
/obj/item/storage/belt/MouseDrop(obj/over_object as obj, src_location, over_location)
var/mob/M = usr
if(!istype(over_object, /obj/screen))
@@ -68,7 +67,7 @@
new /obj/item/weldingtool(src)
new /obj/item/crowbar(src)
new /obj/item/wirecutters(src)
- new /obj/item/stack/cable_coil(src, 30, pick(COLOR_RED, COLOR_YELLOW, COLOR_ORANGE))
+ new /obj/item/stack/cable_coil/random(src, 30)
update_icon()
/obj/item/storage/belt/utility/full/multitool/New()
@@ -99,7 +98,7 @@
new /obj/item/crowbar/power(src)
new /obj/item/weldingtool/experimental(src)//This can be changed if this is too much
new /obj/item/multitool(src)
- new /obj/item/stack/cable_coil(src, 30, pick(COLOR_RED, COLOR_YELLOW, COLOR_ORANGE))
+ new /obj/item/stack/cable_coil/random(src, 30)
new /obj/item/extinguisher/mini(src)
new /obj/item/analyzer(src)
update_icon()
@@ -112,6 +111,7 @@
icon_state = "medicalbelt"
item_state = "medical"
use_item_overlays = 1
+ max_w_class = WEIGHT_CLASS_NORMAL
can_hold = list(
/obj/item/healthanalyzer,
/obj/item/dnainjector,
@@ -133,6 +133,7 @@
/obj/item/rad_laser,
/obj/item/sensor_device,
/obj/item/wrench/medical,
+ /obj/item/handheld_defibrillator
)
/obj/item/storage/belt/medical/surgery
@@ -182,7 +183,6 @@
new /obj/item/reagent_containers/food/pill/salicylic(src)
update_icon()
-
/obj/item/storage/belt/botany
name = "botanist belt"
desc = "Can hold various botanical supplies."
@@ -205,7 +205,6 @@
/obj/item/wrench,
)
-
/obj/item/storage/belt/security
name = "security belt"
desc = "Can hold security gear like handcuffs and flashes."
@@ -386,7 +385,8 @@
/obj/item/flashlight,
/obj/item/reagent_containers/spray,
/obj/item/soap,
- /obj/item/holosign_creator
+ /obj/item/holosign_creator,
+ /obj/item/melee/flyswatter,
)
/obj/item/storage/belt/janitor/full/New()
@@ -397,6 +397,7 @@
new /obj/item/soap(src)
new /obj/item/grenade/chem_grenade/cleaner(src)
new /obj/item/grenade/chem_grenade/cleaner(src)
+ new /obj/item/melee/flyswatter(src)
update_icon()
/obj/item/storage/belt/lazarus
@@ -470,7 +471,6 @@
..()
update_icon()
-
/obj/item/storage/belt/holster
name = "shoulder holster"
desc = "A holster to conceal a carried handgun. WARNING: Badasses only."
@@ -508,7 +508,6 @@
W.charges = W.max_charges
update_icon()
-
/obj/item/storage/belt/fannypack
name = "fannypack"
desc = "A dorky fannypack for keeping small items in."
@@ -597,7 +596,6 @@
// Bluespace Belt
// -------------------------------------
-
/obj/item/storage/belt/bluespace
name = "Belt of Holding"
desc = "The greatest in pants-supporting technology."
@@ -630,8 +628,6 @@
var/bolacount = 0
var/cooldown = 0
-
-
/obj/item/storage/belt/bluespace/owlman/New()
..()
new /obj/item/grenade/smokebomb(src)
@@ -640,9 +636,13 @@
new /obj/item/grenade/smokebomb(src)
new /obj/item/restraints/legcuffs/bola(src)
new /obj/item/restraints/legcuffs/bola(src)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
cooldown = world.time
+/obj/item/storage/belt/bluespace/owlman/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
/obj/item/storage/belt/bluespace/owlman/process()
if(cooldown < world.time - 600)
smokecount = 0
@@ -725,3 +725,52 @@
new /obj/item/analyzer(src)
new /obj/item/healthanalyzer(src)
+
+/obj/item/storage/belt/mining
+ name = "explorer's webbing"
+ desc = "A versatile chest rig, cherished by miners and hunters alike."
+ icon_state = "explorer1"
+ item_state = "explorer1"
+ storage_slots = 6
+ max_w_class = WEIGHT_CLASS_BULKY
+ use_item_overlays = 0
+ can_hold = list(
+ /obj/item/crowbar,
+ /obj/item/screwdriver,
+ /obj/item/weldingtool,
+ /obj/item/wirecutters,
+ /obj/item/wrench,
+ /obj/item/multitool,
+ /obj/item/flashlight,
+ /obj/item/stack/cable_coil,
+ /obj/item/analyzer,
+ /obj/item/extinguisher/mini,
+ /obj/item/radio,
+ /obj/item/clothing/gloves,
+ /obj/item/resonator,
+ /obj/item/mining_scanner,
+ /obj/item/pickaxe,
+ /obj/item/stack/sheet/animalhide,
+ /obj/item/stack/sheet/sinew,
+ /obj/item/stack/sheet/bone,
+ /obj/item/lighter,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/reagent_containers/food/drinks/bottle,
+ /obj/item/stack/medical,
+ /obj/item/kitchen/knife,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/gps,
+ /obj/item/storage/bag/ore,
+ /obj/item/survivalcapsule,
+ /obj/item/t_scanner/adv_mining_scanner,
+ /obj/item/reagent_containers/food/pill,
+ /obj/item/stack/ore,
+ /obj/item/reagent_containers/food/drinks,
+ /obj/item/organ/internal/hivelord_core,
+ /obj/item/wormhole_jaunter,
+ /obj/item/storage/bag/plants,
+ /obj/item/stack/marker_beacon)
+
+/obj/item/storage/belt/mining/New()
+ ..()
+ new /obj/item/survivalcapsule(src)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm
index 16ecd7cc72c..eb778b6a280 100644
--- a/code/game/objects/items/weapons/storage/bible.dm
+++ b/code/game/objects/items/weapons/storage/bible.dm
@@ -9,9 +9,10 @@
var/mob/affecting = null
var/deity_name = "Christ"
- suicide_act(mob/user)
- to_chat(viewers(user), "[user] stares into [src.name] and attempts to trascend understanding of the universe!")
- return (user.dust())
+/obj/item/storage/bible/suicide_act(mob/user)
+ to_chat(viewers(user), "[user] stares into [src.name] and attempts to transcend understanding of the universe!")
+ user.dust()
+ return OBLITERATION
/obj/item/storage/bible/booze
@@ -44,7 +45,7 @@
else
M.LAssailant = user
- if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ if(!(istype(user, /mob/living/carbon/human) || SSticker) && SSticker.mode.name != "monkey")
to_chat(user, "You don't have the dexterity to do this!")
return
if(!user.mind || !user.mind.isholy)
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index afe4bc1ce13..e7342774619 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -191,6 +191,15 @@
new /obj/item/reagent_containers/glass/beaker( src )
new /obj/item/reagent_containers/glass/beaker( src )
+/obj/item/storage/box/beakers/bluespace
+ name = "box of bluespace beakers"
+ icon_state = "beaker"
+
+/obj/item/storage/box/beakers/bluespace/New()
+ ..()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/glass/beaker/bluespace(src)
+
/obj/item/storage/box/iv_bags
name = "IV Bags"
desc = "A box full of empty IV bags."
@@ -536,6 +545,10 @@
for(var/i in 1 to 5)
new monkey_cube_type(src)
+/obj/item/storage/box/monkeycubes/syndicate
+ desc = "Waffle Co. brand monkey cubes. Just add water and a dash of subterfuge!"
+ monkey_cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/syndicate
+
/obj/item/storage/box/monkeycubes/farwacubes
name = "farwa cube box"
desc = "Drymate brand farwa cubes. Just add water!"
@@ -1044,6 +1057,56 @@
new /obj/item/circuitboard/circuit_imprinter(src)
new /obj/item/circuitboard/rdconsole/public(src)
+/obj/item/storage/box/stockparts/basic //for ruins where it's a bad idea to give access to an autolathe/protolathe, but still want to make stock parts accessible
+ name = "box of stock parts"
+ desc = "Contains a variety of basic stock parts."
+
+/obj/item/storage/box/stockparts/basic/New()
+ ..()
+ for(var/i in 1 to 3)
+ new /obj/item/stock_parts/capacitor(src)
+ new /obj/item/stock_parts/scanning_module(src)
+ new /obj/item/stock_parts/manipulator(src)
+ new /obj/item/stock_parts/micro_laser(src)
+ new /obj/item/stock_parts/matter_bin(src)
+
+/obj/item/storage/box/stockparts/deluxe
+ name = "box of deluxe stock parts"
+ desc = "Contains a variety of deluxe stock parts."
+
+/obj/item/storage/box/stockparts/deluxe/New()
+ for(var/i in 1 to 3)
+ new /obj/item/stock_parts/capacitor/quadratic(src)
+ new /obj/item/stock_parts/scanning_module/triphasic(src)
+ new /obj/item/stock_parts/manipulator/femto(src)
+ new /obj/item/stock_parts/micro_laser/quadultra(src)
+ new /obj/item/stock_parts/matter_bin/bluespace(src)
+
+/obj/item/storage/box/mininghardsuit
+ name = "Boxed Mining Hardsuit"
+ desc = "Contains a mining hardsuit and helmet. For mining."
+
+/obj/item/storage/box/mininghardsuit/New()
+ ..()
+ new /obj/item/clothing/suit/space/hardsuit/mining(src)
+ new /obj/item/clothing/head/helmet/space/hardsuit/mining(src)
+
+/obj/item/storage/box/hug
+ name = "box of hugs"
+ desc = "A special box for sensitive people."
+ icon_state = "hugbox"
+ foldable = null
+
+/obj/item/storage/box/hug/suicide_act(mob/user)
+ user.visible_message("[user] clamps the box of hugs on [user.p_their()] jugular! Guess it wasn't such a hugbox after all..")
+ return (BRUTELOSS)
+
+/obj/item/storage/box/hug/attack_self(mob/user)
+ ..()
+ user.changeNext_move(CLICK_CD_MELEE)
+ playsound(loc, "rustle", 50, 1, -5)
+ user.visible_message("[user] hugs \the [src].","You hug \the [src].")
+
#undef NODESIGN
#undef NANOTRASEN
#undef SYNDI
diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm
index b2637a9688e..2450648cded 100644
--- a/code/game/objects/items/weapons/storage/briefcase.dm
+++ b/code/game/objects/items/weapons/storage/briefcase.dm
@@ -15,5 +15,15 @@
burn_state = FLAMMABLE
burntime = 20
-/obj/item/storage/briefcase/New()
- ..()
+/obj/item/storage/briefcase/sniperbundle
+ desc = "Its label reads \"genuine hardened Captain leather\", but suspiciously has no other tags or branding. Smells like L'Air du Temps."
+ force = 10
+
+/obj/item/storage/briefcase/sniperbundle/New()
+ ..()
+ new /obj/item/gun/projectile/automatic/sniper_rifle/syndicate(src)
+ new /obj/item/clothing/accessory/red(src)
+ new /obj/item/clothing/under/syndicate/sniper(src)
+ new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
+ new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
+ new /obj/item/suppressor/specialoffer(src)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm
index 03b5ac86870..603a86b072b 100644
--- a/code/game/objects/items/weapons/storage/fancy.dm
+++ b/code/game/objects/items/weapons/storage/fancy.dm
@@ -62,6 +62,7 @@
/obj/item/storage/fancy/egg_box
icon_state = "eggbox"
icon_type = "egg"
+ item_state = "eggbox"
name = "egg box"
storage_slots = 12
can_hold = list(/obj/item/reagent_containers/food/snacks/egg)
diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm
index 5e81c320041..8d8cb77e597 100644
--- a/code/game/objects/items/weapons/storage/firstaid.dm
+++ b/code/game/objects/items/weapons/storage/firstaid.dm
@@ -254,10 +254,21 @@
var/applying_meds = FALSE //To Prevent spam clicking and generating runtimes from apply a deleting pill multiple times.
var/rapid_intake_message = "unscrews the cap on the pill bottle and begins dumping the entire contents down their throat!"
var/rapid_post_instake_message = "downs the entire bottle of pills in one go!"
+ var/allow_wrap = TRUE
+ var/wrapper_color = null
/obj/item/storage/pill_bottle/New()
..()
base_name = name
+ if(allow_wrap)
+ apply_wrap()
+
+/obj/item/storage/pill_bottle/proc/apply_wrap()
+ if(wrapper_color)
+ overlays.Cut()
+ var/image/I = image(icon, "pillbottle_wrap")
+ I.color = wrapper_color
+ overlays += I
/obj/item/storage/pill_bottle/attack(mob/M, mob/user)
if(iscarbon(M) && contents.len)
@@ -274,6 +285,9 @@
else
return ..()
+/obj/item/storage/pill_bottle/ert
+ wrapper_color = COLOR_MAROON
+
/obj/item/storage/pill_bottle/ert/New()
..()
new /obj/item/reagent_containers/food/pill/salicylic(src)
@@ -295,11 +309,11 @@
for(var/obj/item/reagent_containers/food/pill/P in contents)
P.attack(C, C)
C.visible_message("[C] [rapid_post_instake_message]")
- return
+ return
return ..()
-/obj/item/storage/pill_bottle/attackby(var/obj/item/I, mob/user as mob, params)
+/obj/item/storage/pill_bottle/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/pen) || istype(I, /obj/item/flashlight/pen))
var/tmp_label = sanitize(input(user, "Enter a label for [name]","Label",label_text))
if(length(tmp_label) > MAX_NAME_LEN)
@@ -319,15 +333,18 @@
/obj/item/storage/pill_bottle/patch_pack
name = "Patch Pack"
+ desc = "It's a container for storing medical patches."
icon_state = "patch_pack"
can_hold = list(/obj/item/reagent_containers/food/pill/patch)
cant_hold = list()
rapid_intake_message = "flips the lid of the Patch Pack open and begins rapidly stamping patches on themselves!"
rapid_post_instake_message = "stamps the entire contents of the Patch Pack all over their entire body!"
+ allow_wrap = FALSE
/obj/item/storage/pill_bottle/charcoal
name = "Pill bottle (Charcoal)"
desc = "Contains pills used to counter toxins."
+ wrapper_color = COLOR_GREEN
New()
..()
@@ -342,6 +359,7 @@
/obj/item/storage/pill_bottle/painkillers
name = "Pill Bottle (Salicylic Acid)"
desc = "Contains various pills for minor pain relief."
+ wrapper_color = COLOR_RED
/obj/item/storage/pill_bottle/painkillers/New()
..()
@@ -354,8 +372,11 @@
new /obj/item/reagent_containers/food/pill/salicylic(src)
new /obj/item/reagent_containers/food/pill/salicylic(src)
+/obj/item/storage/pill_bottle/fakedeath
+ allow_wrap = FALSE
+
/obj/item/storage/pill_bottle/fakedeath/New()
..()
new /obj/item/reagent_containers/food/pill/fakedeath(src)
new /obj/item/reagent_containers/food/pill/fakedeath(src)
- new /obj/item/reagent_containers/food/pill/fakedeath(src)
\ No newline at end of file
+ new /obj/item/reagent_containers/food/pill/fakedeath(src)
diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm
index 9cd4178aaf2..edccca3ff4a 100644
--- a/code/game/objects/items/weapons/storage/lockbox.dm
+++ b/code/game/objects/items/weapons/storage/lockbox.dm
@@ -116,15 +116,10 @@
/obj/item/storage/lockbox/medal/New()
..()
- new /obj/item/clothing/accessory/medal/gold/heroism(src)
- new /obj/item/clothing/accessory/medal/silver/security(src)
- new /obj/item/clothing/accessory/medal/silver/valor(src)
- new /obj/item/clothing/accessory/medal/nobel_science(src)
- new /obj/item/clothing/accessory/medal/bronze_heart(src)
- new /obj/item/clothing/accessory/medal/conduct(src)
- new /obj/item/clothing/accessory/medal/conduct(src)
- new /obj/item/clothing/accessory/medal/conduct(src)
new /obj/item/clothing/accessory/medal/gold/captain(src)
+ new /obj/item/clothing/accessory/medal/silver/leadership(src)
+ new /obj/item/clothing/accessory/medal/silver/valor(src)
+ new /obj/item/clothing/accessory/medal/heart(src)
/obj/item/storage/lockbox/t4
name = "lockbox (T4)"
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index 507d6fdb9f3..53f93775cad 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -151,8 +151,8 @@
src.boxes.screen_loc = "[tx]:,[ty] to [mx],[my]"
for(var/obj/O in src.contents)
O.screen_loc = "[cx],[cy]"
- O.layer = 20
- O.plane = HUD_PLANE
+ O.layer = ABOVE_HUD_LAYER
+ O.plane = ABOVE_HUD_PLANE
cx++
if(cx > mx)
cx = tx
@@ -171,8 +171,8 @@
ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE
ND.sample_object.screen_loc = "[cx]:16,[cy]:16"
ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]"
- ND.sample_object.layer = 20
- ND.sample_object.plane = HUD_PLANE
+ ND.sample_object.layer = ABOVE_HUD_LAYER
+ ND.sample_object.plane = ABOVE_HUD_PLANE
cx++
if(cx > (4+cols))
cx = 4
@@ -182,8 +182,8 @@
O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
O.screen_loc = "[cx]:16,[cy]:16"
O.maptext = ""
- O.layer = 20
- O.plane = HUD_PLANE
+ O.layer = ABOVE_HUD_LAYER
+ O.plane = ABOVE_HUD_PLANE
cx++
if(cx > (4+cols))
cx = 4
@@ -312,6 +312,7 @@
if(usr.s_active)
usr.s_active.show_to(usr)
W.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt
+ W.in_inventory = TRUE
update_icon()
return 1
@@ -332,8 +333,8 @@
if(ismob(loc))
W.dropped(usr)
if(ismob(new_location))
- W.layer = 20
- W.plane = HUD_PLANE
+ W.layer = ABOVE_HUD_LAYER
+ W.plane = ABOVE_HUD_PLANE
else
W.layer = initial(W.layer)
W.plane = initial(W.plane)
@@ -447,17 +448,18 @@
else
verbs -= /obj/item/storage/verb/toggle_gathering_mode
- src.boxes = new /obj/screen/storage( )
- src.boxes.name = "storage"
- src.boxes.master = src
- src.boxes.icon_state = "block"
- src.boxes.screen_loc = "7,7 to 10,8"
- src.boxes.layer = 19
- src.closer = new /obj/screen/close( )
- src.closer.master = src
- src.closer.icon_state = "x"
- src.closer.layer = 20
- src.closer.plane = HUD_PLANE
+ boxes = new /obj/screen/storage( )
+ boxes.name = "storage"
+ boxes.master = src
+ boxes.icon_state = "block"
+ boxes.screen_loc = "7,7 to 10,8"
+ boxes.layer = HUD_LAYER
+ boxes.plane = HUD_PLANE
+ closer = new /obj/screen/close( )
+ closer.master = src
+ closer.icon_state = "x"
+ closer.layer = ABOVE_HUD_LAYER
+ closer.plane = ABOVE_HUD_PLANE
orient2hud()
/obj/item/storage/Destroy()
@@ -469,7 +471,7 @@
return ..()
/obj/item/storage/emp_act(severity)
- if(!istype(src.loc, /mob/living))
+ if(!istype(loc, /mob/living))
for(var/obj/O in contents)
O.emp_act(severity)
..()
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index cac42bfced7..3736d93f3f6 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -1,112 +1,120 @@
-/obj/item/storage/box/syndicate/
- New()
- ..()
- switch(pickweight(list("bloodyspai" = 1, "thief" = 1, "bond" = 1, "sabotage" = 1, "payday" = 1, "implant" = 1, "hacker" = 1, "darklord" = 1, "gadgets" = 1, "professional" = 1)))
- if("bloodyspai") // 28TC
- new /obj/item/twohanded/garrote(src)
- new /obj/item/pinpointer/advpinpointer(src)
- new /obj/item/clothing/mask/gas/voice(src)
- new /obj/item/clothing/under/chameleon(src)
- new /obj/item/card/id/syndicate(src)
- new /obj/item/flashlight/emp(src)
- new /obj/item/storage/fancy/cigarettes/cigpack_syndicate(src)
- new /obj/item/clothing/glasses/hud/security/chameleon(src)
- new /obj/item/camera_bug(src)
- return
+/obj/item/storage/box/syndicate/New()
+ ..()
+ switch(pickweight(list("bloodyspai" = 1, "thief" = 1, "bond" = 1, "sabotage" = 1, "payday" = 1, "implant" = 1, "hacker" = 1, "darklord" = 1, "professional" = 1)))
+ if("bloodyspai") // 35TC + one 0TC
+ new /obj/item/clothing/under/chameleon(src) // 2TC
+ new /obj/item/clothing/mask/chameleon(src) // 0TC
+ new /obj/item/card/id/syndicate(src) // 2TC
+ new /obj/item/clothing/shoes/chameleon/noslip(src) // 2TC
+ new /obj/item/camera_bug(src) // 1TC
+ new /obj/item/multitool/ai_detect(src) // 1TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ new /obj/item/twohanded/garrote(src) // 10TC
+ new /obj/item/pinpointer/advpinpointer(src) // 4TC
+ new /obj/item/storage/fancy/cigarettes/cigpack_syndicate(src) // 2TC
+ new /obj/item/flashlight/emp(src) // 2TC
+ new /obj/item/clothing/glasses/hud/security/chameleon(src) // 2TC
+ new /obj/item/chameleon(src) // 8TC
+ return
- if("thief") // 30TC
- new /obj/item/gun/energy/kinetic_accelerator/crossbow(src)
- new /obj/item/chameleon(src)
- new /obj/item/clothing/gloves/color/black/thief(src)
- new /obj/item/card/id/syndicate(src)
- new /obj/item/clothing/shoes/syndigaloshes(src)
- new /obj/item/storage/box/syndie_kit/safecracking(src)
- return
+ if("thief") // 40TC
+ new /obj/item/gun/energy/kinetic_accelerator/crossbow(src) // 12TC
+ new /obj/item/chameleon(src) // 8TC
+ new /obj/item/clothing/glasses/chameleon/thermal(src) // 6TC
+ new /obj/item/clothing/gloves/color/black/thief(src) // 6TC
+ new /obj/item/card/id/syndicate(src) // 2TC
+ new /obj/item/clothing/shoes/chameleon/noslip(src) // 2TC
+ new /obj/item/storage/backpack/satchel_flat(src) // 2TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ return
- if("bond") // 29TC + Healing Cocktail + armored suit jacket
- new /obj/item/gun/projectile/automatic/pistol(src)
- new /obj/item/suppressor(src)
- new /obj/item/ammo_box/magazine/m10mm/hp(src)
- new /obj/item/ammo_box/magazine/m10mm/ap(src)
- new /obj/item/encryptionkey/syndicate(src)
- new /obj/item/reagent_containers/food/drinks/drinkingglass/alliescocktail(src) // This drink heals now
- new /obj/item/card/id/syndicate(src)
- new /obj/item/dnascrambler(src)
- new /obj/item/storage/box/syndie_kit/emp(src)
- new /obj/item/CQC_manual(src)
- new /obj/item/clothing/under/suit_jacket/really_black(src)
- new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src)
- return
+ if("bond") // 33TC + three 0TC
+ new /obj/item/gun/projectile/automatic/pistol(src) // 4TC
+ new /obj/item/suppressor(src) // 1TC
+ new /obj/item/ammo_box/magazine/m10mm/hp(src) // 3TC
+ new /obj/item/ammo_box/magazine/m10mm/ap(src) // 2TC
+ new /obj/item/clothing/under/suit_jacket/really_black(src) // 0TC
+ new /obj/item/card/id/syndicate(src) // 2TC
+ new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src) // 0TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ new /obj/item/reagent_containers/food/drinks/drinkingglass/alliescocktail(src) // 0TC
+ new /obj/item/dnascrambler(src) // 4TC
+ new /obj/item/storage/box/syndie_kit/emp(src) // 2TC
+ new /obj/item/CQC_manual(src) // 13TC
+ return
- if("sabotage") // 31TC + RCD + Insuls
- new /obj/item/powersink(src)
- new /obj/item/grenade/syndieminibomb(src)
- new /obj/item/card/emag(src)
- new /obj/item/grenade/clusterbuster/n2o(src)
- new /obj/item/clothing/gloves/color/yellow(src)
- new /obj/item/rcd/preloaded(src)
- new /obj/item/storage/box/syndie_kit/space(src)
- return
+ if("sabotage") // 47TC + three 0TC
+ new /obj/item/grenade/plastic/c4(src) // 1TC
+ new /obj/item/grenade/plastic/c4(src) // 1TC
+ new /obj/item/camera_bug(src) // 1TC
+ new /obj/item/powersink(src) // 10TC
+ new /obj/item/cartridge/syndicate(src) // 6TC
+ new /obj/item/rcd/preloaded(src) // 0TC
+ new /obj/item/card/emag(src) // 6TC
+ new /obj/item/clothing/gloves/color/yellow(src) // 0TC
+ new /obj/item/grenade/syndieminibomb(src) // 6TC
+ new /obj/item/grenade/clusterbuster/n2o(src) // 0TC
+ new /obj/item/storage/box/syndie_kit/space(src) // 4TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ return
- if("payday") // 31TC + armored suit jacket
- new /obj/item/gun/projectile/revolver(src)
- new /obj/item/ammo_box/a357(src)
- new /obj/item/ammo_box/a357(src)
- new /obj/item/card/emag(src)
- new /obj/item/grenade/plastic/c4(src)
- new /obj/item/card/id/syndicate(src)
- new /obj/item/clothing/under/suit_jacket/really_black(src)
- new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src)
- new /obj/item/clothing/gloves/color/latex/nitrile(src)
- new /obj/item/clothing/mask/gas/clown_hat(src)
- new /obj/item/thermal_drill(src)
- return
+ if("payday") // 33TC + four 0TC
+ new /obj/item/gun/projectile/revolver(src) // 13TC
+ new /obj/item/ammo_box/a357(src) // 3TC
+ new /obj/item/ammo_box/a357(src) // 3TC
+ new /obj/item/card/emag(src) // 6TC
+ new /obj/item/grenade/plastic/c4(src) // 1TC
+ new /obj/item/card/id/syndicate(src) // 2TC
+ new /obj/item/clothing/under/suit_jacket/really_black(src) //0TC
+ new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src) //0TC
+ new /obj/item/clothing/gloves/color/latex/nitrile(src) //0 TC
+ new /obj/item/clothing/mask/gas/clown_hat(src) // 0TC
+ new /obj/item/thermal_drill(src) // 3TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ return
- if("implant") // 35TC
- new /obj/item/implanter/uplink(src)
- new /obj/item/implanter/adrenalin(src)
- new /obj/item/implanter/storage(src)
- new /obj/item/implanter/freedom(src)
- return
+ if("implant") // 39TC + ten free TC
+ new /obj/item/implanter/freedom(src) // 5TC
+ new /obj/item/implanter/uplink(src) // 14TC (ten free TC)
+ new /obj/item/implanter/emp(src) // 0TC
+ new /obj/item/implanter/adrenalin(src) // 8TC
+ new /obj/item/implanter/explosive(src) // 2TC
+ new /obj/item/implanter/storage(src) // 8TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ return
- if("hacker") // 22TC + Ion law uploader
- new /obj/item/aiModule/syndicate(src)
- new /obj/item/encryptionkey/binary(src)
- new /obj/item/encryptionkey/syndicate(src)
- new /obj/item/aiModule/toyAI(src)
- new /obj/item/card/emag(src)
- return
+ if("hacker") // 30TC + one 0TC
+ new /obj/item/aiModule/syndicate(src) // 12TC
+ new /obj/item/card/emag(src) // 6TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ new /obj/item/encryptionkey/binary(src) // 5TC
+ new /obj/item/aiModule/toyAI(src) // 0TC
+ new /obj/item/multitool/ai_detect(src) // 1TC
+ new /obj/item/storage/box/syndie_kit/c4 // 4TC
+ return
- if("darklord") // 23TC + TK implant
- new /obj/item/melee/energy/sword/saber/red(src)
- new /obj/item/melee/energy/sword/saber/red(src)
- new /obj/item/dnainjector/telemut/darkbundle(src)
- new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
- new /obj/item/card/id/syndicate(src)
- new /obj/item/clothing/shoes/syndigaloshes(src)
- new /obj/item/clothing/mask/gas/voice(src)
- return
+ if("darklord") // 22TC + two 0TC
+ new /obj/item/melee/energy/sword/saber/red(src) // 8TC
+ new /obj/item/melee/energy/sword/saber/red(src) // 8TC
+ new /obj/item/dnainjector/telemut/darkbundle(src) // 0TC
+ new /obj/item/clothing/suit/hooded/chaplain_hoodie(src) // 0TC
+ new /obj/item/card/id/syndicate(src) // 2TC
+ new /obj/item/clothing/shoes/chameleon/noslip(src) // 2TC
+ new /obj/item/clothing/mask/chameleon(src) // 2TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ return
- if("gadgets") // 30TC
- new /obj/item/clothing/gloves/color/yellow/power(src)
- new /obj/item/pen/sleepy(src)
- new /obj/item/clothing/shoes/syndigaloshes(src)
- new /obj/item/clothing/glasses/thermal/syndi(src)
- new /obj/item/flashlight/emp(src)
- new /obj/item/stamp/chameleon(src)
- new /obj/item/multitool/ai_detect(src)
- return
-
- if("professional") // 29TC + armored suit jacket + insulated combat gloves
- new /obj/item/gun/projectile/automatic/sniper_rifle/soporific(src) // Unique version that starts with soporific rounds loaded and cannot be suppressed
- new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
- new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
- new /obj/item/pen/edagger(src)
- new /obj/item/clothing/glasses/thermal/syndi/sunglasses(src)
- new /obj/item/clothing/under/suit_jacket/really_black(src)
- new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src)
- new /obj/item/clothing/gloves/combat(src)
- return
+ if("professional") // 32 TC + two 0TC
+ new /obj/item/gun/projectile/automatic/sniper_rifle/syndicate/penetrator(src) // 16TC
+ new /obj/item/ammo_box/magazine/sniper_rounds/penetrator(src) // 5TC
+ new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src) // 3TC
+ new /obj/item/clothing/glasses/chameleon/thermal(src) // 6TC
+ new /obj/item/clothing/gloves/combat(src) // 0 TC
+ new /obj/item/clothing/under/suit_jacket/really_black(src) // 0 TC
+ new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src) // 0TC
+ new /obj/item/pen/edagger(src) // 2TC
+ new /obj/item/encryptionkey/syndicate(src) // 2TC
+ return
/obj/item/storage/box/syndie_kit
name = "Box"
@@ -254,6 +262,13 @@
new /obj/item/ammo_casing/shotgun/assassination(src)
new /obj/item/gun/projectile/revolver/doublebarrel/improvised/cane(src)
+/obj/item/storage/box/syndie_kit/fake_revolver
+ name = "trick revolver kit"
+
+/obj/item/storage/box/syndie_kit/fake_revolver/New()
+ ..()
+ new /obj/item/toy/russian_revolver/trick_revolver(src)
+
/obj/item/storage/box/syndie_kit/mimery
name = "advanced mimery kit"
@@ -262,13 +277,24 @@
new /obj/item/spellbook/oneuse/mime/greaterwall(src)
new /obj/item/spellbook/oneuse/mime/fingergun(src)
-/obj/item/storage/box/syndie_kit/atmosgasgrenades
- name = "Atmos Grenades"
-/obj/item/storage/box/syndie_kit/atmosgasgrenades/New()
+/obj/item/storage/box/syndie_kit/atmosn2ogrenades
+ name = "Atmos N2O Grenades"
+
+/obj/item/storage/box/syndie_kit/atmosn2ogrenades/New()
+ ..()
+ new /obj/item/grenade/clusterbuster/n2o(src)
+ new /obj/item/grenade/clusterbuster/n2o(src)
+
+
+/obj/item/storage/box/syndie_kit/atmosfiregrenades
+ name = "Plasma Fire Grenades"
+
+/obj/item/storage/box/syndie_kit/atmosfiregrenades/New()
..()
new /obj/item/grenade/clusterbuster/plasma(src)
- new /obj/item/grenade/clusterbuster/n2o(src)
+ new /obj/item/grenade/clusterbuster/plasma(src)
+
/obj/item/storage/box/syndie_kit/missionary_set
name = "Missionary Starter Kit"
@@ -322,4 +348,21 @@ To apply, hold the injector a short distance away from the outer thigh before ap
new /obj/item/clothing/gloves/color/latex/nitrile(src)
new /obj/item/clothing/mask/balaclava(src)
new /obj/item/clothing/accessory/stethoscope(src)
- new /obj/item/book/manual/engineering_hacking(src)
\ No newline at end of file
+ new /obj/item/book/manual/engineering_hacking(src)
+
+/obj/item/storage/box/syndie_kit/chameleon
+ name = "chameleon kit"
+
+/obj/item/storage/box/syndie_kit/chameleon/New()
+ ..()
+ new /obj/item/clothing/under/chameleon(src)
+ new /obj/item/clothing/suit/chameleon(src)
+ new /obj/item/clothing/gloves/chameleon(src)
+ new /obj/item/clothing/shoes/chameleon(src)
+ new /obj/item/clothing/glasses/chameleon(src)
+ new /obj/item/clothing/head/chameleon(src)
+ new /obj/item/clothing/mask/chameleon(src)
+ new /obj/item/storage/backpack/chameleon(src)
+ new /obj/item/radio/headset/chameleon(src)
+ new /obj/item/stamp/chameleon(src)
+ new /obj/item/pda/chameleon(src)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index f33fc7240d2..526340daea5 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -18,7 +18,10 @@
/obj/item/melee/baton/suicide_act(mob/user)
user.visible_message("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide.")
- return (FIRELOSS)
+ return FIRELOSS
+
+/obj/item/melee/baton/get_cell()
+ return bcell
/obj/item/melee/baton/New()
..()
@@ -141,6 +144,12 @@
if(isrobot(M))
..()
return
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(check_martial_counter(H, user))
+ return
+
if(!isliving(M))
return
@@ -166,8 +175,6 @@
if(ishuman(L))
var/mob/living/carbon/human/H = L
- if(check_martial_counter(L, user))
- return
if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK)) //No message; check_shields() handles that
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return
diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm
index 3fc4b4b7717..d0526ebbcb8 100644
--- a/code/game/objects/items/weapons/swords_axes_etc.dm
+++ b/code/game/objects/items/weapons/swords_axes_etc.dm
@@ -52,7 +52,9 @@
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK))
- return 0
+ return
+ if(check_martial_counter(H, user))
+ return
playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1)
target.Weaken(3)
add_attack_logs(user, target, "Stunned with [src]")
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index d533a7e595b..c44264c6529 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -27,13 +27,13 @@
air_contents.volume = volume //liters
air_contents.temperature = T20C
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
return
/obj/item/tank/Destroy()
QDEL_NULL(air_contents)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index 5eb7a5b30ff..7afb1885ea2 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -32,7 +32,7 @@
/obj/item/wrench/suicide_act(mob/user)
user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/wrench/cyborg
name = "automatic wrench"
@@ -76,7 +76,7 @@
/obj/item/wrench/power/suicide_act(mob/user)
user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/wrench/medical
name = "medical wrench"
@@ -113,7 +113,7 @@
return
user.dust()
- return OXYLOSS
+ return OBLITERATION
//Screwdriver
/obj/item/screwdriver
@@ -143,7 +143,7 @@
/obj/item/screwdriver/suicide_act(mob/user)
user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!")
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/screwdriver/New(loc, var/param_color = null)
..()
@@ -199,7 +199,7 @@
/obj/item/screwdriver/power/suicide_act(mob/user)
user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!")
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/screwdriver/power/attack_self(mob/user)
playsound(get_turf(user), 'sound/items/change_drill.ogg', 50, 1)
@@ -256,7 +256,7 @@
/obj/item/wirecutters/suicide_act(mob/user)
user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, usesound, 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/wirecutters/brass
name = "brass wirecutters"
@@ -299,7 +299,7 @@
if(head)
head.droplimb(0, DROPLIMB_BLUNT, FALSE, TRUE)
playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/wirecutters/power/attack_self(mob/user)
playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
@@ -349,7 +349,7 @@
/obj/item/weldingtool/suicide_act(mob/user)
user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!")
- return (FIRELOSS)
+ return FIRELOSS
/obj/item/weldingtool/proc/update_torch()
overlays.Cut()
@@ -377,7 +377,7 @@
damtype = "brute"
update_icon()
if(!can_off_process)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return
//Welders left on now use up fuel, but lets not have them run out quite that fast
if(1)
@@ -539,7 +539,7 @@
damtype = "fire"
hitsound = 'sound/items/welder.ogg'
update_icon()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
else
to_chat(user, "You need more fuel!")
switched_off(user)
@@ -738,7 +738,7 @@ obj/item/weldingtool/experimental/process()
/obj/item/crowbar/power/suicide_act(mob/user)
user.visible_message("[user] is putting [user.p_their()] head in [src]. It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/crowbar/power/attack_self(mob/user)
playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index de219626d31..15456386541 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -28,12 +28,15 @@
var/force_wielded = 0
var/wieldsound = null
var/unwieldsound = null
+ var/sharp_when_wielded = FALSE
/obj/item/twohanded/proc/unwield(mob/living/carbon/user)
if(!wielded || !user)
return
wielded = FALSE
force = force_unwielded
+ if(sharp_when_wielded)
+ sharp = FALSE
var/sf = findtext(name," (Wielded)")
if(sf)
name = copytext(name, 1, sf)
@@ -66,6 +69,8 @@
return
wielded = TRUE
force = force_wielded
+ if(sharp_when_wielded)
+ sharp = TRUE
name = "[name] (Wielded)"
update_icon()
if(user)
@@ -192,6 +197,15 @@
var/obj/structure/grille/G = A
G.take_damage(40, BRUTE, "melee", 0)
+/obj/item/twohanded/fireaxe/boneaxe // Blatant imitation of the fireaxe, but made out of bone.
+ icon_state = "bone_axe0"
+ name = "bone axe"
+ desc = "A large, vicious axe crafted out of several sharpened bone plates and crudely tied together. Made of monsters, by killing monsters, for killing monsters."
+ force_wielded = 23
+
+/obj/item/twohanded/fireaxe/boneaxe/update_icon()
+ icon_state = "bone_axe[wielded]"
+
/*
* Double-Bladed Energy Swords - Cheridan
*/
@@ -215,7 +229,7 @@
origin_tech = "magnets=4;syndicate=5"
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
block_chance = 75
- sharp = TRUE
+ sharp_when_wielded = TRUE // only sharp when wielded
light_power = 2
var/brightness_on = 2
var/colormap = list(red=LIGHT_COLOR_RED, blue=LIGHT_COLOR_LIGHTBLUE, green=LIGHT_COLOR_GREEN, purple=LIGHT_COLOR_PURPLE, rainbow=LIGHT_COLOR_WHITE)
@@ -347,6 +361,19 @@
explosive.prime()
qdel(src)
+/obj/item/twohanded/spear/bonespear //Blatant imitation of spear, but made out of bone. Not valid for explosive modification.
+ icon_state = "bone_spear0"
+ name = "bone spear"
+ desc = "A haphazardly-constructed yet still deadly weapon. The pinnacle of modern technology."
+ force = 11
+ force_unwielded = 11
+ force_wielded = 20 //I have no idea how to balance
+ throwforce = 22
+ armour_penetration = 15 //Enhanced armor piercing
+
+/obj/item/twohanded/spear/bonespear/update_icon()
+ icon_state = "bone_spear[wielded]"
+
//GREY TIDE
/obj/item/twohanded/spear/grey_tide
icon_state = "spearglass0"
@@ -557,10 +584,10 @@
/obj/item/twohanded/singularityhammer/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/twohanded/singularityhammer/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/twohanded/singularityhammer/process()
@@ -664,10 +691,10 @@
/obj/item/twohanded/knighthammer/New()
..()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/item/twohanded/knighthammer/Destroy()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/twohanded/knighthammer/process()
@@ -797,7 +824,7 @@
/obj/item/twohanded/pitchfork/suicide_act(mob/user)
user.visible_message("[user] impales \himself in \his abdomen with [src]! It looks like \he's trying to commit suicide...")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/twohanded/pitchfork/demonic/pickup(mob/user)
. = ..()
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index cd295befb83..b759139dba6 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -12,8 +12,8 @@
/obj/item/banhammer/suicide_act(mob/user)
- to_chat(viewers(user), "[user] is hitting [user.p_them()]self with the [src.name]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life.")
- return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS)
+ to_chat(viewers(user), "[user] is hitting [user.p_them()]self with the [src.name]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life.")
+ return BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS
/obj/item/sord
name = "\improper SORD"
@@ -49,7 +49,7 @@
/obj/item/claymore/suicide_act(mob/user)
user.visible_message("[user] is falling on the [name]! It looks like [user.p_theyre()] trying to commit suicide.")
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/claymore/ceremonial
name = "ceremonial claymore"
@@ -76,7 +76,7 @@
/obj/item/katana/suicide_act(mob/user)
user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku.")
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/harpoon
name = "harpoon"
diff --git a/code/game/objects/items/weapons/whetstone.dm b/code/game/objects/items/weapons/whetstone.dm
index fcc3e05bf14..f74f8d28f57 100644
--- a/code/game/objects/items/weapons/whetstone.dm
+++ b/code/game/objects/items/weapons/whetstone.dm
@@ -10,7 +10,7 @@
var/max = 30
var/prefix = "sharpened"
var/requires_sharpness = 1
- var/claw_damage_increase = 1
+ var/claw_damage_increase = 2
/obj/item/whetstone/attackby(obj/item/I, mob/user, params)
@@ -58,13 +58,18 @@
var/mob/living/carbon/human/H = user
var/datum/unarmed_attack/attack = H.dna.species.unarmed
if(istype(attack, /datum/unarmed_attack/claws))
- attack.damage += claw_damage_increase
- H.visible_message("[H] sharpens [H.p_their()] claws on [src]!", "You sharpen your claws on [src].")
- playsound(get_turf(H), usesound, 50, 1)
- name = "worn out [name]"
- desc = "[desc] At least, it used to."
- used = TRUE
- update_icon()
+ var/datum/unarmed_attack/claws/C = attack
+ if(!C.has_been_sharpened)
+ C.has_been_sharpened = TRUE
+ attack.damage += claw_damage_increase
+ H.visible_message("[H] sharpens [H.p_their()] claws on [src]!", "You sharpen your claws on [src].")
+ playsound(get_turf(H), usesound, 50, 1)
+ name = "worn out [name]"
+ desc = "[desc] At least, it used to."
+ used = TRUE
+ update_icon()
+ else
+ to_chat(user, "You can not sharpen your claws any further!")
/obj/item/whetstone/super
name = "super whetstone block"
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 246fc5df75d..572495b503f 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -49,13 +49,9 @@
tforce = O.throwforce
take_damage(tforce, BRUTE, "melee", 1, get_dir(src, AM))
-/obj/ex_act(severity, target)
+/obj/ex_act(severity)
if(resistance_flags & INDESTRUCTIBLE)
return
- if(target == src)
- obj_integrity = 0
- qdel(src)
- return
switch(severity)
if(1)
obj_integrity = 0
@@ -69,7 +65,8 @@
. = ..()
playsound(src, P.hitsound, 50, 1)
visible_message("[src] is hit by \a [P]!")
- take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration)
+ if(!QDELETED(src)) //Bullet on_hit effect might have already destroyed this object
+ take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration)
/obj/proc/hulk_damage()
return 150 //the damage hulks do on punches to this object, is affected by melee armor
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index d9358c3a694..c2428dd8d97 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -29,6 +29,7 @@
var/on_blueprints = FALSE //Are we visible on the station blueprints at roundstart?
var/force_blueprints = FALSE //forces the obj to be on the blueprints, regardless of when it was created.
+ var/suicidal_hands = FALSE // Does it requires you to hold it to commit suicide with it?
/obj/New()
..()
@@ -65,16 +66,26 @@
// Nada
/obj/Destroy()
- GLOB.machines -= src
- processing_objects -= src
- GLOB.fast_processing -= src
+ if(!ismachinery(src))
+ if(!speed_process)
+ STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists
+ else
+ STOP_PROCESSING(SSfastprocess, src)
SSnanoui.close_uis(src)
return ..()
-/obj/proc/process()
- set waitfor = 0
- processing_objects.Remove(src)
- return 0
+//user: The mob that is suiciding
+//damagetype: The type of damage the item will inflict on the user
+//BRUTELOSS = 1
+//FIRELOSS = 2
+//TOXLOSS = 4
+//OXYLOSS = 8
+//SHAME = 16
+//OBLITERATION = 32
+
+//Output a creative message and then return the damagetype done
+/obj/proc/suicide_act(mob/user)
+ return FALSE
/obj/assume_air(datum/gas_mixture/giver)
if(loc)
@@ -286,15 +297,15 @@ a {
if(speed_process)
return
speed_process = TRUE
- processing_objects.Remove(src)
- GLOB.fast_processing.Add(src)
+ STOP_PROCESSING(SSobj, src)
+ START_PROCESSING(SSfastprocess, src)
/obj/proc/makeNormalProcess()
if(!speed_process)
return
speed_process = FALSE
- processing_objects.Add(src)
- GLOB.fast_processing.Remove(src)
+ START_PROCESSING(SSobj, src)
+ STOP_PROCESSING(SSfastprocess, src)
/obj/vv_get_dropdown()
. = ..()
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index faf86394dba..58a2d0464fc 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -31,17 +31,17 @@
/obj/structure/New()
..()
if(smooth)
- if(ticker && ticker.current_state == GAME_STATE_PLAYING)
+ if(SSticker && SSticker.current_state == GAME_STATE_PLAYING)
queue_smooth(src)
queue_smooth_neighbors(src)
icon_state = ""
if(climbable)
verbs += /obj/structure/proc/climb_on
- if(ticker)
+ if(SSticker)
cameranet.updateVisibility(src)
/obj/structure/Destroy()
- if(ticker)
+ if(SSticker)
cameranet.updateVisibility(src)
if(smooth)
var/turf/T = get_turf(src)
diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm
index 90e32882087..bf13a05f691 100644
--- a/code/game/objects/structures/aliens.dm
+++ b/code/game/objects/structures/aliens.dm
@@ -113,6 +113,7 @@
anchored = TRUE
density = FALSE
layer = TURF_LAYER
+ plane = FLOOR_PLANE
icon_state = "weeds"
max_integrity = 15
var/obj/structure/alien/weeds/node/linked_node = null
@@ -234,14 +235,22 @@
var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive
layer = MOB_LAYER
+/obj/structure/alien/egg/grown
+ status = GROWN
+ icon_state = "egg"
+
+/obj/structure/alien/egg/burst
+ status = BURST
+ icon_state = "egg_hatched"
/obj/structure/alien/egg/New()
new /obj/item/clothing/mask/facehugger(src)
..()
- spawn(rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME))
- Grow()
if(status == BURST)
obj_integrity = integrity_failure
+ else if(status != GROWN)
+ spawn(rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME))
+ Grow()
/obj/structure/alien/egg/attack_alien(mob/living/carbon/alien/user)
return attack_hand(user)
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index 8c4f40a7b62..43f45647985 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -87,6 +87,12 @@ LINEN BINS
dream_messages = list("yellow")
nightmare_messages = list("locker full of banana peels")
+/obj/item/bedsheet/black
+ icon_state = "sheetblack"
+ item_color = "sheetblack"
+ dream_messages = list("black")
+ nightmare_messages = list("the void of space")
+
/obj/item/bedsheet/mime
name = "mime's blanket"
desc = "A very soothing striped blanket. All the noise just seems to fade out when you're under the covers in this."
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 5be8c938f3e..2037293d734 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -278,9 +278,11 @@
if(src == user.loc)
to_chat(user, "You can not [welded?"unweld":"weld"] the locker from inside.")
return
- if(!WT.remove_fuel(0,user))
+ if(!WT.remove_fuel(0, user))
to_chat(user, "You need more welding fuel to complete this task.")
return
+ if(!do_after_once(user, 15, target = src))
+ return
welded = !welded
update_icon()
for(var/mob/M in viewers(src))
@@ -450,7 +452,7 @@
icon_closed = transparent ? "bluespacetrans" : "bluespace"
icon_state = opened ? icon_opened : icon_closed
-/obj/structure/closet/bluespace/Crossed(atom/movable/AM)
+/obj/structure/closet/bluespace/Crossed(atom/movable/AM, oldloc)
if(AM.density)
icon_state = opened ? "bluespaceopentrans" : "bluespacetrans"
diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm
index 9ae35b7d4f1..f1053ec917b 100644
--- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm
@@ -76,6 +76,7 @@
new /obj/item/radio/headset/headset_service(src)
new /obj/item/cartridge/janitor(src)
new /obj/item/flashlight(src)
+ new /obj/item/melee/flyswatter(src)
new /obj/item/clothing/shoes/galoshes(src)
new /obj/item/soap(src)
new /obj/item/caution(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 7b07e003bca..0cd6e541398 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -20,6 +20,7 @@
new /obj/item/storage/box/permits(src)
new /obj/item/clothing/under/rank/chief_engineer(src)
new /obj/item/clothing/under/rank/chief_engineer/skirt(src)
+ new /obj/item/clothing/suit/mantle/chief_engineer(src)
new /obj/item/clothing/head/hardhat/white(src)
new /obj/item/clothing/glasses/welding/superior(src)
new /obj/item/clothing/gloves/color/yellow(src)
@@ -37,6 +38,7 @@
new /obj/item/rpd(src)
new /obj/item/reagent_containers/food/drinks/mug/ce(src)
new /obj/item/organ/internal/cyberimp/eyes/meson(src)
+ new /obj/item/clothing/accessory/medal/engineering(src)
/obj/structure/closet/secure_closet/engineering_electrical
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
index 4f2356872c5..9e030a29187 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
@@ -28,17 +28,30 @@
name = "kitchen cabinet"
req_access = list(access_kitchen)
- New()
- ..()
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/food/condiment/flour(src)
- new /obj/item/reagent_containers/food/condiment/rice(src)
- new /obj/item/reagent_containers/food/condiment/sugar(src)
+/obj/structure/closet/secure_closet/freezer/kitchen/New()
+ ..()
+ for(var/i in 1 to 3)
+ new /obj/item/reagent_containers/food/condiment/flour(src)
+ new /obj/item/reagent_containers/food/condiment/rice(src)
+ new /obj/item/reagent_containers/food/condiment/sugar(src)
/obj/structure/closet/secure_closet/freezer/kitchen/mining
req_access = list()
+/obj/structure/closet/secure_closet/freezer/kitchen/maintenance
+ name = "maintenance refrigerator"
+ desc = "This refrigerator looks quite dusty, is there anything edible still inside?"
+ req_access = list()
+
+/obj/structure/closet/secure_closet/freezer/kitchen/maintenance/New()
+ ..()
+ for(var/i = 0, i < 5, i++)
+ new /obj/item/reagent_containers/food/condiment/milk(src)
+ for(var/i = 0, i < 5, i++)
+ new /obj/item/reagent_containers/food/condiment/soymilk(src)
+ for(var/i = 0, i < 2, i++)
+ new /obj/item/storage/fancy/egg_box(src)
/obj/structure/closet/secure_closet/freezer/meat
name = "meat fridge"
@@ -54,6 +67,9 @@
for(var/i in 1 to 4)
new /obj/item/reagent_containers/food/snacks/meat/monkey(src)
+/obj/structure/closet/secure_closet/freezer/meat/open
+ req_access = null
+ locked = FALSE
/obj/structure/closet/secure_closet/freezer/fridge
name = "refrigerator"
@@ -72,6 +88,9 @@
for(var/i in 1 to 2)
new /obj/item/storage/fancy/egg_box(src)
+/obj/structure/closet/secure_closet/freezer/fridge/open
+ req_access = null
+ locked = FALSE
/obj/structure/closet/secure_closet/freezer/money
name = "freezer"
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
index 9cbd43bf098..189cbc5893d 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
@@ -70,6 +70,7 @@
new /obj/item/radio/headset/headset_med(src)
new /obj/item/clothing/gloves/color/latex/nitrile(src)
new /obj/item/defibrillator/loaded(src)
+ new /obj/item/handheld_defibrillator(src)
new /obj/item/storage/belt/medical(src)
new /obj/item/clothing/glasses/hud/health(src)
new /obj/item/clothing/shoes/sandal/white(src)
@@ -109,6 +110,7 @@
/obj/item/storage/pill_bottle/psychiatrist
name = "psychiatrist's pill bottle"
desc = "Contains various pills to calm or sedate patients."
+ wrapper_color = COLOR_PALE_BTL_GREEN
/obj/item/storage/pill_bottle/psychiatrist/New()
..()
@@ -180,16 +182,19 @@
new /obj/item/clothing/head/surgery/purple(src)
new /obj/item/clothing/suit/storage/labcoat/cmo(src)
new /obj/item/clothing/under/rank/chief_medical_officer(src)
+ new /obj/item/clothing/suit/mantle/labcoat/chief_medical_officer(src)
new /obj/item/clothing/shoes/brown (src)
new /obj/item/radio/headset/heads/cmo(src)
new /obj/item/clothing/gloves/color/latex/nitrile(src)
new /obj/item/defibrillator/compact/loaded(src)
+ new /obj/item/handheld_defibrillator(src)
new /obj/item/storage/belt/medical(src)
new /obj/item/flash(src)
new /obj/item/reagent_containers/hypospray/CMO(src)
new /obj/item/organ/internal/cyberimp/eyes/hud/medical(src)
new /obj/item/door_remote/chief_medical_officer(src)
new /obj/item/reagent_containers/food/drinks/mug/cmo(src)
+ new /obj/item/clothing/accessory/medal/medical(src)
/obj/structure/closet/secure_closet/animal
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
index ca673d40ec1..4d688f65dac 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
@@ -13,6 +13,7 @@
new /obj/item/storage/backpack/science(src)
new /obj/item/storage/backpack/satchel_tox(src)
new /obj/item/clothing/under/rank/scientist(src)
+ new /obj/item/clothing/under/rank/scientist/skirt(src)
//new /obj/item/clothing/suit/labcoat/science(src)
new /obj/item/clothing/suit/storage/labcoat/science(src)
new /obj/item/clothing/shoes/white(src)
@@ -63,6 +64,7 @@
new /obj/item/clothing/head/bio_hood/scientist(src)
new /obj/item/clothing/under/rank/research_director(src)
new /obj/item/clothing/suit/storage/labcoat(src)
+ new /obj/item/clothing/suit/mantle/labcoat(src)
new /obj/item/cartridge/rd(src)
new /obj/item/clothing/shoes/white(src)
new /obj/item/clothing/gloves/color/latex(src)
@@ -75,7 +77,7 @@
new /obj/item/door_remote/research_director(src)
new /obj/item/reagent_containers/food/drinks/mug/rd(src)
new /obj/item/organ/internal/cyberimp/eyes/hud/diagnostic(src)
-
+ new /obj/item/clothing/accessory/medal/science(src)
/obj/structure/closet/secure_closet/research_reagents
name = "research chemical storage closet"
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 6925c495309..fe6b0082207 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -18,6 +18,7 @@
new /obj/item/storage/backpack/duffel/captain(src)
new /obj/item/clothing/suit/captunic(src)
new /obj/item/clothing/suit/captunic/capjacket(src)
+ new /obj/item/clothing/suit/mantle/armor/captain(src)
new /obj/item/clothing/under/captainparade(src)
new /obj/item/clothing/head/caphat/parade(src)
new /obj/item/clothing/under/rank/captain(src)
@@ -59,7 +60,7 @@
new /obj/item/clothing/accessory/petcollar(src)
new /obj/item/door_remote/civillian(src)
new /obj/item/reagent_containers/food/drinks/mug/hop(src)
-
+ new /obj/item/clothing/accessory/medal/service(src)
/obj/structure/closet/secure_closet/hop2
name = "head of personnel's attire"
@@ -74,6 +75,7 @@
/obj/structure/closet/secure_closet/hop2/New()
..()
new /obj/item/clothing/under/rank/head_of_personnel(src)
+ new /obj/item/clothing/suit/mantle/armor/head_of_personnel(src)
new /obj/item/clothing/under/dress/dress_hop(src)
new /obj/item/clothing/under/dress/dress_hr(src)
new /obj/item/clothing/under/lawyer/female(src)
@@ -113,6 +115,7 @@
new /obj/item/clothing/suit/armor/hos/alt(src)
new /obj/item/clothing/head/HoS(src)
new /obj/item/clothing/head/HoS/beret(src)
+ new /obj/item/clothing/suit/mantle/armor(src)
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
new /obj/item/storage/lockbox/mindshield(src)
new /obj/item/storage/box/flashbangs(src)
@@ -125,7 +128,7 @@
new /obj/item/door_remote/head_of_security(src)
new /obj/item/reagent_containers/food/drinks/mug/hos(src)
new /obj/item/organ/internal/cyberimp/eyes/hud/security(src)
-
+ new /obj/item/clothing/accessory/medal/security(src)
/obj/structure/closet/secure_closet/warden
name = "warden's locker"
@@ -461,4 +464,5 @@
new /obj/item/clothing/head/powdered_wig(src)
new /obj/item/gavelblock(src)
new /obj/item/gavelhammer(src)
- new /obj/item/clothing/head/justice_wig(src)
\ No newline at end of file
+ new /obj/item/clothing/head/justice_wig(src)
+ new /obj/item/clothing/accessory/medal/legal(src)
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets/statue.dm b/code/game/objects/structures/crates_lockers/closets/statue.dm
index 0692c90ec6d..909ee79e1ab 100644
--- a/code/game/objects/structures/crates_lockers/closets/statue.dm
+++ b/code/game/objects/structures/crates_lockers/closets/statue.dm
@@ -41,7 +41,7 @@
qdel(src)
return
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
..()
/obj/structure/closet/statue/process()
@@ -53,7 +53,7 @@
M.setOxyLoss(intialOxy)
if(timer <= 0)
dump_contents()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
qdel(src)
/obj/structure/closet/statue/dump_contents()
diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
index f88dcbba954..a89bce34396 100644
--- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
@@ -19,6 +19,9 @@
icon_closed = "emergency"
icon_opened = "emergencyopen"
+/obj/structure/closet/emcloset/anchored
+ anchored = TRUE
+
/obj/structure/closet/emcloset/New()
..()
diff --git a/code/game/objects/structures/crates_lockers/crittercrate.dm b/code/game/objects/structures/crates_lockers/crittercrate.dm
index ffaff75288d..50d9b056e96 100644
--- a/code/game/objects/structures/crates_lockers/crittercrate.dm
+++ b/code/game/objects/structures/crates_lockers/crittercrate.dm
@@ -44,6 +44,10 @@
name = "cow crate"
content_mob = /mob/living/simple_animal/cow
+/obj/structure/closet/critter/pig
+ name = "pig crate"
+ content_mob = /mob/living/simple_animal/pig
+
/obj/structure/closet/critter/goat
name = "goat crate"
content_mob = /mob/living/simple_animal/hostile/retaliate/goat
diff --git a/code/game/objects/structures/depot.dm b/code/game/objects/structures/depot.dm
index b286749f908..a3dc4ac7007 100644
--- a/code/game/objects/structures/depot.dm
+++ b/code/game/objects/structures/depot.dm
@@ -87,7 +87,7 @@
/obj/effect/overload/New()
. = ..()
// Do not attempt to put the code below into Initialize() or even LateInitialize() with a "return INITIALIZE_HINT_LATELOAD". It won't work!
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
depotarea = areaMaster
if(istype(depotarea))
if(!depotarea.used_self_destruct)
@@ -122,6 +122,6 @@
for(var/obj/mecha/E in range(30, T))
E.Destroy()
explosion(get_turf(src), 25, 35, 45, 55, 1, 1, 60, 0, 0)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
qdel(src)
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index 543ebd7af91..c03b9694cfa 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -2,17 +2,15 @@
#define DISPLAYCASE_FRAME_SCREWDRIVER 1
// List and hook used to set up the captain's print on their display case
-var/global/list/captain_display_cases = list()
+GLOBAL_LIST_INIT(captain_display_cases, list())
-/hook/captain_spawned/proc/displaycase(mob/living/carbon/human/captain)
- if(!captain_display_cases.len)
- return 1
+/proc/updateDisplaycase(mob/living/carbon/human/captain)
+ if(!GLOB.captain_display_cases.len)
+ return
var/fingerprint = captain.get_full_print()
- for(var/obj/structure/displaycase/D in captain_display_cases)
- if(istype(D))
- D.ue = fingerprint
-
- return 1
+ for(var/item in GLOB.captain_display_cases)
+ var/obj/structure/displaycase/CASE = item
+ CASE.ue = fingerprint
/obj/structure/displaycase_frame
name = "display case frame"
@@ -95,14 +93,14 @@ var/global/list/captain_display_cases = list()
icon = 'icons/obj/stationobjs.dmi'
icon_state = "glassbox20"
desc = "A display case for prized possessions. It taunts you to kick it."
- density = 1
- anchored = 1
- unacidable = 1 //Dissolving the case would also delete the contents.
+ density = TRUE
+ anchored = TRUE
+ unacidable = TRUE //Dissolving the case would also delete the contents.
var/health = 30
var/obj/item/occupant = null
- var/destroyed = 0
- var/locked = 0
- var/burglar_alarm = 0
+ var/destroyed = FALSE
+ var/locked = FALSE
+ var/burglar_alarm = FALSE
var/ue = null
var/image/occupant_overlay = null
var/obj/item/airlock_electronics/circuit
@@ -118,11 +116,15 @@ var/global/list/captain_display_cases = list()
/obj/structure/displaycase/captains_laser
name = "captain's display case"
desc = "A display case for the captain's antique laser gun. Hooked up with an anti-theft system."
- burglar_alarm = 1
- locked = 1
+ burglar_alarm = TRUE
+ locked = TRUE
req_access = list(access_captain)
start_showpiece_type = /obj/item/gun/energy/laser/captain
+/obj/structure/displaycase/captains_laser/Initialize(mapload)
+ . = ..()
+ GLOB.captain_display_cases += src
+
/obj/structure/displaycase/stechkin
name = "officer's display case"
desc = "A display case containing a humble stechkin pistol. Never forget your roots."
@@ -136,7 +138,7 @@ var/global/list/captain_display_cases = list()
return ..()
/obj/structure/displaycase/captains_laser/Destroy()
- captain_display_cases -= src
+ GLOB.captain_display_cases -= src
return ..()
/obj/structure/displaycase/examine(mob/user)
@@ -203,7 +205,7 @@ var/global/list/captain_display_cases = list()
return
/obj/structure/displaycase/proc/burglar_alarm()
- if(burglar_alarm)
+ if(burglar_alarm && is_station_contact(z))
var/area/alarmed = get_area(src)
alarmed.burglaralert(src)
visible_message("The burglar alarm goes off!")
@@ -213,10 +215,10 @@ var/global/list/captain_display_cases = list()
sleep(74) // 7.4 seconds long
/obj/structure/displaycase/update_icon()
- if(src.destroyed)
- src.icon_state = "glassbox2b"
+ if(destroyed)
+ icon_state = "glassbox2b"
else
- src.icon_state = "glassbox2[locked]"
+ icon_state = "glassbox2[locked]"
overlays = 0
if(occupant)
var/icon/occupant_icon=getFlatIcon(occupant)
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index eca9d524730..b21754cae96 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -226,6 +226,7 @@
door = new airlock_type(loc)
door.setDir(dir)
door.electronics = electronics
+ door.unres_sides = electronics.unres_sides
door.heat_proof = heat_proof_finished
if(electronics.one_access)
door.req_access = null
diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm
index 568fb0ededc..303862ff66f 100644
--- a/code/game/objects/structures/extinguisher.dm
+++ b/code/game/objects/structures/extinguisher.dm
@@ -28,6 +28,22 @@
else
has_extinguisher = new/obj/item/extinguisher
+/obj/structure/extinguisher_cabinet/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click to [opened ? "close":"open"] it.")
+
+/obj/structure/extinguisher_cabinet/AltClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!in_range(src, user))
+ return
+ if(!iscarbon(usr))
+ return
+ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
+ opened = !opened
+ update_icon()
+
/obj/structure/extinguisher_cabinet/Destroy()
QDEL_NULL(has_extinguisher)
return ..()
@@ -37,11 +53,16 @@
return
if(istype(O, /obj/item/extinguisher))
if(!has_extinguisher && opened)
+ if(!user.drop_item())
+ return
user.drop_item(O)
contents += O
has_extinguisher = O
+ update_icon()
to_chat(user, "You place [O] in [src].")
+ return TRUE
else
+ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
else if(istype(O, /obj/item/weldingtool))
if(has_extinguisher)
@@ -65,6 +86,7 @@
new material_drop(T)
qdel(src)
else
+ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
update_icon()
@@ -81,21 +103,27 @@
to_chat(user, "You try to move your [temp.name], but cannot!")
return
if(has_extinguisher)
+ if(icon_state == "extinguisher_closed")
+ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
user.put_in_hands(has_extinguisher)
to_chat(user, "You take [has_extinguisher] from [src].")
has_extinguisher = null
opened = 1
else
+ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
update_icon()
/obj/structure/extinguisher_cabinet/attack_tk(mob/user)
if(has_extinguisher)
+ if(icon_state == "extinguisher_closed")
+ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
has_extinguisher.loc = loc
to_chat(user, "You telekinetically remove [has_extinguisher] from [src].")
has_extinguisher = null
opened = 1
else
+ playsound(loc, 'sound/machines/click.ogg', 15, TRUE, -3)
opened = !opened
update_icon()
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index 9b777d45b58..4a70729d7e9 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -9,19 +9,26 @@
/obj/structure/falsewall
name = "wall"
desc = "A huge chunk of metal used to seperate rooms."
- anchored = 1
+ anchored = TRUE
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
- var/mineral = "metal"
- var/walltype = "metal"
- var/opening = 0
- density = 1
- opacity = 1
+
+ var/mineral = /obj/item/stack/sheet/metal
+ var/mineral_amount = 2
+ var/walltype = /turf/simulated/wall
+ var/girder_type = /obj/structure/girder/displaced
+ var/opening = FALSE
+
+ density = TRUE
+ opacity = TRUE
+
+ can_deconstruct = TRUE
canSmoothWith = list(
/turf/simulated/wall,
/turf/simulated/wall/r_wall,
/obj/structure/falsewall,
+ /obj/structure/falsewall/brass,
/obj/structure/falsewall/reinforced, // WHY DO WE SMOOTH WITH FALSE R-WALLS WHEN WE DON'T SMOOTH WITH REAL R-WALLS. //because we do smooth with real r-walls now
/turf/simulated/wall/rust,
/turf/simulated/wall/r_wall/rust)
@@ -31,6 +38,10 @@
..()
air_update_turf(1)
+/obj/structure/falsewall/ratvar_act()
+ new /obj/structure/falsewall/brass(loc)
+ qdel(src)
+
/obj/structure/falsewall/Destroy()
density = 0
air_update_turf(1)
@@ -124,18 +135,11 @@
/obj/structure/falsewall/proc/dismantle(mob/user)
user.visible_message("[user] dismantles the false wall.", "You dismantle the false wall.")
- new /obj/structure/girder/displaced(loc)
- if(mineral == "metal")
- if(istype(src, /obj/structure/falsewall/reinforced))
- new /obj/item/stack/sheet/plasteel(loc, 2)
- else
- new /obj/item/stack/sheet/metal(loc, 2)
- else if(mineral == "wood")
- new/obj/item/stack/sheet/wood(loc, 2)
- else
- var/P = text2path("/obj/item/stack/sheet/mineral/[mineral]")
- new P(loc)
- new P(loc)
+ if(can_deconstruct)
+ new girder_type(loc)
+ if(mineral_amount)
+ for(var/i in 1 to mineral_amount)
+ new mineral(loc)
playsound(src, 'sound/items/welder.ogg', 100, 1)
qdel(src)
@@ -148,7 +152,8 @@
desc = "A huge chunk of reinforced metal used to seperate rooms."
icon = 'icons/turf/walls/reinforced_wall.dmi'
icon_state = "r_wall"
- walltype = "rwall"
+ walltype = /turf/simulated/wall/r_wall
+ mineral = /obj/item/stack/sheet/plasteel
/obj/structure/falsewall/reinforced/ChangeToWall(delete = 1)
var/turf/T = get_turf(src)
@@ -166,8 +171,8 @@
desc = "A wall with uranium plating. This is probably a bad idea."
icon = 'icons/turf/walls/uranium_wall.dmi'
icon_state = "uranium"
- mineral = "uranium"
- walltype = "uranium"
+ mineral = /obj/item/stack/sheet/mineral/uranium
+ walltype = /turf/simulated/wall/mineral/uranium
var/active = null
var/last_event = 0
canSmoothWith = list(/obj/structure/falsewall/uranium, /turf/simulated/wall/mineral/uranium)
@@ -201,8 +206,8 @@
desc = "A wall with gold plating. Swag!"
icon = 'icons/turf/walls/gold_wall.dmi'
icon_state = "gold"
- mineral = "gold"
- walltype = "gold"
+ mineral = /obj/item/stack/sheet/mineral/gold
+ walltype = /turf/simulated/wall/mineral/gold
canSmoothWith = list(/obj/structure/falsewall/gold, /turf/simulated/wall/mineral/gold)
/obj/structure/falsewall/silver
@@ -210,8 +215,8 @@
desc = "A wall with silver plating. Shiny."
icon = 'icons/turf/walls/silver_wall.dmi'
icon_state = "silver"
- mineral = "silver"
- walltype = "silver"
+ mineral = /obj/item/stack/sheet/mineral/silver
+ walltype = /turf/simulated/wall/mineral/silver
canSmoothWith = list(/obj/structure/falsewall/silver, /turf/simulated/wall/mineral/silver)
/obj/structure/falsewall/diamond
@@ -219,8 +224,8 @@
desc = "A wall with diamond plating. You monster."
icon = 'icons/turf/walls/diamond_wall.dmi'
icon_state = "diamond"
- mineral = "diamond"
- walltype = "diamond"
+ mineral = /obj/item/stack/sheet/mineral/diamond
+ walltype = /turf/simulated/wall/mineral/diamond
canSmoothWith = list(/obj/structure/falsewall/diamond, /turf/simulated/wall/mineral/diamond)
@@ -229,18 +234,18 @@
desc = "A wall with plasma plating. This is definately a bad idea."
icon = 'icons/turf/walls/plasma_wall.dmi'
icon_state = "plasma"
- mineral = "plasma"
- walltype = "plasma"
+ mineral = /obj/item/stack/sheet/mineral/plasma
+ walltype = /turf/simulated/wall/mineral/plasma
canSmoothWith = list(/obj/structure/falsewall/plasma, /turf/simulated/wall/mineral/plasma, /turf/simulated/wall/mineral/alien)
/obj/structure/falsewall/plasma/attackby(obj/item/W, mob/user, params)
if(is_hot(W) > 300)
- message_admins("Plasma falsewall ignited by [key_name_admin(user)] in ([x],[y],[z] - JMP)",0,1)
- log_game("Plasma falsewall ignited by [key_name(user)] in ([x],[y],[z])")
+ message_admins("Plasma falsewall ignited by [key_name_admin(user)] in [ADMIN_VERBOSEJMP(T)]")
+ log_game("Plasma falsewall ignited by [key_name(user)] in [AREACOORD(T)]")
investigate_log("was ignited by [key_name(user)]","atmos")
burnbabyburn()
- return
- ..()
+ else
+ return ..()
/obj/structure/falsewall/plasma/proc/burnbabyburn(user)
playsound(src, 'sound/items/welder.ogg', 100, 1)
@@ -258,8 +263,8 @@
desc = "A strange-looking alien wall."
icon = 'icons/turf/walls/plasma_wall.dmi'
icon_state = "plasma"
- mineral = "alien"
- walltype = "alien"
+ mineral = /obj/item/stack/sheet/mineral/abductor
+ walltype = /turf/simulated/wall/mineral/abductor
canSmoothWith = list(/obj/structure/falsewall/alien, /turf/simulated/wall/mineral/alien)
@@ -268,16 +273,16 @@
desc = "A wall with bananium plating. Honk!"
icon = 'icons/turf/walls/bananium_wall.dmi'
icon_state = "bananium"
- mineral = "clown"
- walltype = "clown"
+ mineral = /obj/item/stack/sheet/mineral/bananium
+ walltype = /turf/simulated/wall/mineral/bananium
canSmoothWith = list(/obj/structure/falsewall/bananium, /turf/simulated/wall/mineral/bananium)
/obj/structure/falsewall/sandstone
name = "sandstone wall"
desc = "A wall with sandstone plating."
icon_state = "sandstone"
- mineral = "sandstone"
- walltype = "sandstone"
+ mineral = /obj/item/stack/sheet/mineral/sandstone
+ walltype = /turf/simulated/wall/mineral/sandstone
canSmoothWith = list(/obj/structure/falsewall/sandstone, /turf/simulated/wall/mineral/sandstone)
/obj/structure/falsewall/wood
@@ -285,8 +290,8 @@
desc = "A wall with wooden plating. Stiff."
icon = 'icons/turf/walls/wood_wall.dmi'
icon_state = "wood"
- mineral = "wood"
- walltype = "wood"
+ mineral = /obj/item/stack/sheet/wood
+ walltype = /turf/simulated/wall/mineral/wood
canSmoothWith = list(/obj/structure/falsewall/wood, /turf/simulated/wall/mineral/wood)
/obj/structure/falsewall/iron
@@ -294,8 +299,9 @@
desc = "A wall with rough metal plating."
icon = 'icons/turf/walls/iron_wall.dmi'
icon_state = "iron"
- mineral = "metal"
- walltype = "iron"
+ mineral = /obj/item/stack/rods
+ mineral_amount = 5
+ walltype = /turf/simulated/wall/mineral/iron
canSmoothWith = list(/obj/structure/falsewall/iron, /turf/simulated/wall/mineral/iron)
/obj/structure/falsewall/abductor
@@ -303,8 +309,8 @@
desc = "A wall with alien alloy plating."
icon = 'icons/turf/walls/abductor_wall.dmi'
icon_state = "abductor"
- mineral = "abductor"
- walltype = "abductor"
+ mineral = /obj/item/stack/sheet/mineral/abductor
+ walltype = /turf/simulated/wall/mineral/abductor
canSmoothWith = list(/obj/structure/falsewall/abductor, /turf/simulated/wall/mineral/abductor)
/obj/structure/falsewall/titanium
@@ -324,3 +330,23 @@
walltype = /turf/simulated/wall/mineral/plastitanium
smooth = SMOOTH_MORE
canSmoothWith = list(/turf/simulated/wall/mineral/plastitanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/full/shuttle, /obj/structure/shuttle/engine/heater)
+
+/obj/structure/falsewall/brass
+ name = "clockwork wall"
+ desc = "A huge chunk of warm metal. The clanging of machinery emanates from within."
+ icon = 'icons/turf/walls/clockwork_wall.dmi'
+ icon_state = "clockwork_wall"
+ resistance_flags = FIRE_PROOF
+ unacidable = TRUE
+ mineral_amount = 1
+ canSmoothWith = list(/obj/effect/clockwork/overlay/wall, /obj/structure/falsewall/brass)
+ girder_type = /obj/structure/clockwork/wall_gear/displaced
+ walltype = /turf/simulated/wall/clockwork
+ mineral = /obj/item/stack/tile/brass
+
+/obj/structure/falsewall/brass/New(loc)
+ ..()
+ var/turf/T = get_turf(src)
+ new /obj/effect/temp_visual/ratvar/wall/false(T)
+ new /obj/effect/temp_visual/ratvar/beam/falsewall(T)
+
diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm
new file mode 100644
index 00000000000..a6a4f699314
--- /dev/null
+++ b/code/game/objects/structures/fluff.dm
@@ -0,0 +1,81 @@
+//Fluff structures serve no purpose and exist only for enriching the environment. They can be destroyed with a wrench.
+
+/obj/structure/fluff
+ name = "fluff structure"
+ desc = "Fluffier than a sheep. This shouldn't exist."
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "minibar"
+ anchored = TRUE
+ density = FALSE
+ opacity = 0
+ var/deconstructible = TRUE
+
+/obj/structure/fluff/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/wrench) && deconstructible)
+ user.visible_message("[user] starts disassembling [src]...", "You start disassembling [src]...")
+ playsound(loc, I.usesound, 50, 1)
+ if(do_after(src, 50 * I.toolspeed, target = src))
+ user.visible_message("[user] disassembles [src]!", "You break down [src] into scrap metal.")
+ playsound(user, 'sound/items/deconstruct.ogg', 50, 1)
+ new/obj/item/stack/sheet/metal(drop_location())
+ qdel(src)
+ return
+ ..()
+
+/obj/structure/fluff/empty_terrarium //Empty terrariums are created when a preserved terrarium in a lavaland seed vault is activated.
+ name = "empty terrarium"
+ desc = "An ancient machine that seems to be used for storing plant matter. Its hatch is ajar."
+ icon = 'icons/obj/lavaland/spawners.dmi'
+ icon_state = "terrarium_open"
+ density = TRUE
+
+/obj/structure/fluff/empty_sleeper //Empty sleepers are created by a good few ghost roles in lavaland.
+ name = "empty sleeper"
+ desc = "An open sleeper. It looks as though it would be awaiting another patient, were it not broken."
+ icon = 'icons/obj/cryogenic2.dmi'
+ icon_state = "sleeper-open"
+
+/obj/structure/fluff/empty_sleeper/nanotrasen
+ name = "broken hypersleep chamber"
+ desc = "A Nanotrasen hypersleep chamber - this one appears broken. \
+ There are exposed bolts for easy disassembly using a wrench."
+ icon_state = "sleeper-o"
+
+/obj/structure/fluff/empty_sleeper/syndicate
+ icon_state = "sleeper_s-open"
+
+/obj/structure/fluff/empty_cryostasis_sleeper //Empty cryostasis sleepers are created when a malfunctioning cryostasis sleeper in a lavaland shelter is activated
+ name = "empty cryostasis sleeper"
+ desc = "Although comfortable, this sleeper won't function as anything but a bed ever again."
+ icon = 'icons/obj/lavaland/spawners.dmi'
+ icon_state = "cryostasis_sleeper_open"
+
+/obj/structure/fluff/drake_statue //Ash drake status spawn on either side of the necropolis gate in lavaland.
+ name = "drake statue"
+ desc = "A towering basalt sculpture of a proud and regal drake. Its eyes are six glowing gemstones."
+ icon = 'icons/effects/64x64.dmi'
+ icon_state = "drake_statue"
+ pixel_x = -16
+ density = TRUE
+ deconstructible = FALSE
+ layer = EDGED_TURF_LAYER
+
+/obj/structure/fluff/drake_statue/falling //A variety of statue in disrepair; parts are broken off and a gemstone is missing
+ desc = "A towering basalt sculpture of a drake. Cracks run down its surface and parts of it have fallen off."
+ icon_state = "drake_statue_falling"
+
+/obj/structure/fluff/divine
+ name = "Miracle"
+ icon = 'icons/obj/hand_of_god_structures.dmi'
+ anchored = TRUE
+ density = TRUE
+
+/obj/structure/fluff/divine/nexus
+ name = "nexus"
+ desc = "It anchors a deity to this world. It radiates an unusual aura. It looks well protected from explosive shock."
+ icon_state = "nexus"
+
+/obj/structure/fluff/divine/conduit
+ name = "conduit"
+ desc = "It allows a deity to extend their reach. Their powers are just as potent near a conduit as a nexus."
+ icon_state = "conduit"
\ No newline at end of file
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index c06e5d82244..1e3cb331cd1 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -245,20 +245,20 @@
/obj/structure/grille/proc/shock(mob/user, prb)
if(!anchored || broken) // unanchored/broken grilles are never connected
- return 0
+ return FALSE
if(!prob(prb))
- return 0
+ return FALSE
if(!in_range(src, user))//To prevent TK and mech users from getting shocked
- return 0
+ return FALSE
var/turf/T = get_turf(src)
var/obj/structure/cable/C = T.get_cable_node()
if(C)
- if(electrocute_mob(user, C, src))
+ if(electrocute_mob(user, C, src, 1, TRUE))
do_sparks(3, 1, src)
- return 1
+ return TRUE
else
- return 0
- return 0
+ return FALSE
+ return FALSE
/obj/structure/grille/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
@@ -273,8 +273,8 @@
var/obj/structure/cable/C = T.get_cable_node()
if(C)
playsound(loc, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5)
- tesla_zap(src, 3, C.powernet.avail * 0.01) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot.
- C.powernet.load += C.powernet.avail * 0.0375 // you can gain up to 3.5 via the 4x upgrades power is halved by the pole so thats 2x then 1X then .5X for 3.5x the 3 bounces shock.
+ tesla_zap(src, 3, C.newavail() * 0.01) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot.
+ C.add_delayedload(C.newavail() * 0.0375) // you can gain up to 3.5 via the 4x upgrades power is halved by the pole so thats 2x then 1X then .5X for 3.5x the 3 bounces shock.
return ..()
/obj/structure/grille/broken // Pre-broken grilles for map placement
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index e5c0fc85722..67ee4b6ac00 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -116,9 +116,9 @@
if(.)
return
if(!shockcd)
- if(ismob(user))
+ if(isliving(user))
var/mob/living/M = user
- M.electrocute_act(15,"Energy Barrier", safety=1)
+ M.electrocute_act(15, "Energy Barrier", safety = TRUE)
shockcd = TRUE
addtimer(CALLBACK(src, .proc/cooldown), 5)
@@ -130,6 +130,6 @@
return
var/mob/living/M = AM
- M.electrocute_act(15, "Energy Barrier", safety = 1)
+ M.electrocute_act(15, "Energy Barrier", safety = TRUE)
shockcd = TRUE
addtimer(CALLBACK(src, .proc/cooldown), 5)
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index 936c94f5c4f..c1233aaee0c 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -1,86 +1,132 @@
/obj/structure/lattice
- desc = "A lightweight support lattice."
name = "lattice"
- icon = 'icons/obj/structures.dmi'
- icon_state = "latticefull"
- density = 0
- anchored = 1.0
+ desc = "A lightweight support lattice."
+ icon = 'icons/obj/smooth_structures/lattice.dmi'
+ icon_state = "lattice"
+ density = FALSE
+ anchored = TRUE
armor = list(melee = 50, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
- layer = 2.3 //under pipes
- // flags = CONDUCT
+ layer = LATTICE_LAYER //under pipes
+ plane = FLOOR_PLANE
+ var/number_of_rods = 1
+ canSmoothWith = list(/obj/structure/lattice,
+ /turf/simulated/floor,
+ /turf/simulated/wall,
+ /obj/structure/falsewall)
+ smooth = SMOOTH_MORE
-/obj/structure/lattice/New()
- ..()
- if(!(istype(src.loc, /turf/space)))
- qdel(src)
- for(var/obj/structure/lattice/LAT in src.loc)
+/obj/structure/lattice/Initialize(mapload)
+ . = ..()
+ for(var/obj/structure/lattice/LAT in loc)
if(LAT != src)
- qdel(LAT)
- icon = 'icons/obj/smoothlattice.dmi'
- icon_state = "latticeblank"
- updateOverlays()
- for(var/dir in cardinal)
- var/obj/structure/lattice/L
- if(locate(/obj/structure/lattice, get_step(src, dir)))
- L = locate(/obj/structure/lattice, get_step(src, dir))
- L.updateOverlays()
+ QDEL_IN(LAT, 0)
-/obj/structure/lattice/Destroy()
- for(var/dir in cardinal)
- var/obj/structure/lattice/L
- if(locate(/obj/structure/lattice, get_step(src, dir)))
- L = locate(/obj/structure/lattice, get_step(src, dir))
- L.updateOverlays(src.loc)
- return ..()
+/obj/structure/lattice/examine(mob/user)
+ ..()
+ deconstruction_hints(user)
+
+/obj/structure/lattice/proc/deconstruction_hints(mob/user)
+ to_chat(user, "The rods look like they could be cut. There's space for more rods or a tile.")
+
+/obj/structure/lattice/attackby(obj/item/C, mob/user, params)
+ if(resistance_flags & INDESTRUCTIBLE)
+ return
+ if(istype(C, /obj/item/wirecutters))
+ var/obj/item/wirecutters/W = C
+ playsound(loc, W.usesound, 50, 1)
+ to_chat(user, "Slicing [name] joints...")
+ deconstruct()
+ else
+ var/turf/T = get_turf(src)
+ return T.attackby(C, user) //hand this off to the turf instead (for building plating, catwalks, etc)
+
+/obj/structure/lattice/deconstruct(disassembled = TRUE)
+ new /obj/item/stack/rods(get_turf(src), number_of_rods)
+ qdel(src)
/obj/structure/lattice/blob_act()
qdel(src)
- return
/obj/structure/lattice/ex_act(severity)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
- return
- if(2.0)
+ if(2)
qdel(src)
+ if(3)
return
- if(3.0)
- return
- else
- return
-
-/obj/structure/lattice/attackby(obj/item/C as obj, mob/user as mob, params)
- if(istype(C, /obj/item/stack/tile/plasteel) || istype(C, /obj/item/stack/rods))
- var/turf/T = get_turf(src)
- T.attackby(C, user) //BubbleWrap - hand this off to the underlying turf instead
- return
- if(istype(C, /obj/item/weldingtool))
- var/obj/item/weldingtool/WT = C
- if(WT.remove_fuel(0, user))
- to_chat(user, "Slicing lattice joints...")
- new /obj/item/stack/rods(src.loc)
- qdel(src)
-
-
-/obj/structure/lattice/proc/updateOverlays()
- //if(!(istype(src.loc, /turf/space)))
- // qdel(src)
- spawn(1)
- overlays = list()
-
- var/dir_sum = 0
-
- for(var/direction in cardinal)
- if(locate(/obj/structure/lattice, get_step(src, direction)))
- dir_sum += direction
- else
- if(!(istype(get_step(src, direction), /turf/space)))
- dir_sum += direction
-
- icon_state = "lattice[dir_sum]"
- return
/obj/structure/lattice/singularity_pull(S, current_size)
if(current_size >= STAGE_FOUR)
- qdel(src)
\ No newline at end of file
+ qdel(src)
+
+/obj/structure/lattice/clockwork
+ name = "cog lattice"
+ desc = "A lightweight support lattice. These hold the Justicar's station together."
+ icon = 'icons/obj/smooth_structures/lattice_clockwork.dmi'
+
+/obj/structure/lattice/clockwork/Initialize(mapload)
+ . = ..()
+ ratvar_act()
+
+/obj/structure/lattice/clockwork/ratvar_act()
+ if((x + y) % 2 != 0)
+ icon = 'icons/obj/smooth_structures/lattice_clockwork_large.dmi'
+ pixel_x = -9
+ pixel_y = -9
+ else
+ icon = 'icons/obj/smooth_structures/lattice_clockwork.dmi'
+ pixel_x = 0
+ pixel_y = 0
+ return TRUE
+
+/obj/structure/lattice/catwalk
+ name = "catwalk"
+ desc = "A catwalk for easier EVA maneuvering and cable placement."
+ icon = 'icons/obj/smooth_structures/catwalk.dmi'
+ icon_state = "catwalk"
+ number_of_rods = 2
+ smooth = SMOOTH_TRUE
+ canSmoothWith = null
+
+/obj/structure/lattice/catwalk/deconstruction_hints(mob/user)
+ to_chat(user, "The supporting rods look like they could be cut.")
+
+/obj/structure/lattice/catwalk/Move()
+ var/turf/T = loc
+ for(var/obj/structure/cable/C in T)
+ C.deconstruct()
+ ..()
+
+/obj/structure/lattice/catwalk/deconstruct()
+ var/turf/T = loc
+ for(var/obj/structure/cable/C in T)
+ C.deconstruct()
+ ..()
+
+/obj/structure/lattice/catwalk/clockwork
+ name = "clockwork catwalk"
+ icon = 'icons/obj/smooth_structures/catwalk_clockwork.dmi'
+ canSmoothWith = list(/obj/structure/lattice,
+ /turf/simulated/floor,
+ /turf/simulated/wall,
+ /obj/structure/falsewall)
+ smooth = SMOOTH_MORE
+
+/obj/structure/lattice/catwalk/clockwork/Initialize(mapload)
+ . = ..()
+ ratvar_act()
+ if(!mapload)
+ new /obj/effect/temp_visual/ratvar/floor/catwalk(loc)
+ new /obj/effect/temp_visual/ratvar/beam/catwalk(loc)
+
+/obj/structure/lattice/catwalk/clockwork/ratvar_act()
+ if((x + y) % 2 != 0)
+ icon = 'icons/obj/smooth_structures/catwalk_clockwork_large.dmi'
+ pixel_x = -9
+ pixel_y = -9
+ else
+ icon = 'icons/obj/smooth_structures/catwalk_clockwork.dmi'
+ pixel_x = 0
+ pixel_y = 0
+ return TRUE
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 5e6e72929fe..f2d39dcd8ca 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -35,7 +35,7 @@
/obj/structure/mineral_door/Move()
var/turf/T = loc
- ..()
+ . = ..()
move_update_air(T)
/obj/structure/mineral_door/Bumped(atom/user)
@@ -133,7 +133,7 @@
if(istype(W, /obj/item/pickaxe))
var/obj/item/pickaxe/digTool = W
to_chat(user, "You start digging \the [src].")
- if(do_after(user, digTool.digspeed * hardness, target = src) && src)
+ if(do_after(user, 40 * digTool.toolspeed * hardness, target = src) && src)
to_chat(user, "You finished digging.")
deconstruct(TRUE)
else if(user.a_intent != INTENT_HARM)
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index d8898a7d671..923fab9e885 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -6,7 +6,6 @@
icon_state = "mirror"
density = 0
anchored = 1
- var/shattered = 0
var/list/ui_users = list()
/obj/structure/mirror/New(turf/T, newdir = SOUTH, building = FALSE)
@@ -23,7 +22,7 @@
pixel_x = 32
/obj/structure/mirror/attack_hand(mob/user)
- if(shattered)
+ if(broken)
return
if(ishuman(user))
@@ -36,9 +35,9 @@
AC.ui_interact(user)
/obj/structure/mirror/proc/shatter()
- if(shattered)
+ if(broken)
return
- shattered = 1
+ broken = TRUE
icon_state = "mirror_broke"
playsound(src, "shatter", 70, 1)
desc = "Oh no, seven years of bad luck!"
@@ -46,7 +45,7 @@
/obj/structure/mirror/bullet_act(obj/item/projectile/Proj)
if(prob(Proj.damage * 2))
- if(!shattered)
+ if(!broken)
shatter()
else
playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
@@ -58,7 +57,7 @@
if(isscrewdriver(I))
user.visible_message("[user] begins to unfasten [src].", "You begin to unfasten [src].")
if(do_after(user, 30 * I.toolspeed, target = src))
- if(shattered)
+ if(broken)
user.visible_message("[user] drops the broken shards to the floor.", "You drop the broken shards on the floor.")
new /obj/item/shard(get_turf(user))
else
@@ -68,7 +67,7 @@
return
user.do_attack_animation(src)
- if(shattered)
+ if(broken)
playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
@@ -85,7 +84,7 @@
if(islarva(user))
return
user.do_attack_animation(src)
- if(shattered)
+ if(broken)
playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
user.visible_message("[user] smashes [src]!")
@@ -100,7 +99,7 @@
if(M.melee_damage_upper <= 0)
return
M.do_attack_animation(src)
- if(shattered)
+ if(broken)
playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
user.visible_message("[user] smashes [src]!")
@@ -113,7 +112,7 @@
if(!S.is_adult)
return
user.do_attack_animation(src)
- if(shattered)
+ if(broken)
playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
user.visible_message("[user] smashes [src]!")
@@ -136,7 +135,7 @@
icon_state = "magic_mirror"
/obj/structure/mirror/magic/attack_hand(mob/user)
- if(!ishuman(user))
+ if(!ishuman(user) || broken)
return
var/mob/living/carbon/human/H = user
@@ -154,6 +153,9 @@
H.dna.real_name = newname
if(H.mind)
H.mind.name = newname
+
+ if(newname)
+ curse(user)
if("Body")
var/list/race_list = list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin")
@@ -172,6 +174,7 @@
AC.whitelist = race_list
ui_users[user] = AC
AC.ui_interact(user)
+
if("Voice")
var/voice_choice = input(user, "Perhaps...", "Voice effects") as null|anything in list("Comic Sans", "Wingdings", "Swedish", "Chav")
var/voice_mutation
@@ -192,8 +195,17 @@
H.dna.SetSEState(voice_mutation, TRUE)
genemutcheck(H, voice_mutation, null, MUTCHK_FORCED)
+ if(voice_choice)
+ curse(user)
+
+/obj/structure/mirror/magic/on_ui_close(mob/user)
+ curse(user)
+
/obj/structure/mirror/magic/attackby(obj/item/I, mob/living/user, params)
return
/obj/structure/mirror/magic/shatter()
- return //can't be broken. it's magic, i ain't gotta explain shit
\ No newline at end of file
+ return //can't be broken. it's magic, i ain't gotta explain shit
+
+/obj/structure/mirror/magic/proc/curse(mob/living/user)
+ return
\ No newline at end of file
diff --git a/code/game/objects/structures/misc.dm b/code/game/objects/structures/misc.dm
index 6be7bf072d8..01fab63dd57 100644
--- a/code/game/objects/structures/misc.dm
+++ b/code/game/objects/structures/misc.dm
@@ -92,11 +92,11 @@
last_ghost_alert = world.time
attack_atom = src
if(active)
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
/obj/structure/ghost_beacon/Destroy()
if(active)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
attack_atom = null
return ..()
@@ -111,9 +111,9 @@
return
to_chat(user, "You [active ? "disable" : "enable"] \the [src].")
if(active)
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
else
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
active = !active
/obj/structure/ghost_beacon/process()
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 3001b52f399..2953744a824 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -484,14 +484,4 @@
if(istype(C)) //We found our corpse, is it inside a morgue?
morgue = get(C.loc, /obj/structure/morgue)
if(morgue)
- morgue.update()
-
-/hook/mob_login/proc/update_morgue(var/client/client, var/mob/mob)
- //Update morgues on login
- mob.update_morgue()
- return 1
-
-/hook/mob_logout/proc/update_morgue(var/client/client, var/mob/mob)
- //Update morgues on logout
- mob.update_morgue()
- return 1
+ morgue.update()
\ No newline at end of file
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
index c6e3ab2e5bd..1bb19a81bd2 100644
--- a/code/game/objects/structures/safe.dm
+++ b/code/game/objects/structures/safe.dm
@@ -2,8 +2,8 @@
CONTAINS:
SAFES
FLOOR SAFES
-Safe Codes
-Safe Internals
+SAFE INTERNALS
+SAFE CODES
*/
GLOBAL_LIST_EMPTY(safes)
@@ -11,22 +11,26 @@ GLOBAL_LIST_EMPTY(safes)
//SAFES
/obj/structure/safe
name = "\improper Safe"
- desc = "A huge chunk of metal with a dial embedded in it. Fine print on the dial reads \"Scarborough Arms - 2 tumbler safe, guaranteed thermite resistant, explosion resistant, and assistant resistant.\""
+ desc = "A huge chunk of metal with a dial embedded in it. Fine print on the dial reads \"Scarborough Arms tumbler safe, guaranteed thermite resistant, explosion resistant, and assistant resistant.\""
icon = 'icons/obj/structures.dmi'
icon_state = "safe"
- anchored = 1
- density = 1
- var/open = FALSE //is the safe open?
+
+ anchored = TRUE
+ density = TRUE
+ resistance_flags = LAVA_PROOF | FIRE_PROOF
+ unacidable = TRUE
+
+ var/open = FALSE
var/locked = TRUE
- var/tumbler_1_pos //the tumbler position- from 0 to 72
- var/tumbler_1_open //the tumbler position to open at- 0 to 72
- var/tumbler_2_pos
- var/tumbler_2_open
- var/open_pos
- var/dial = 0 //where is the dial pointing?
- var/space = 0 //the combined w_class of everything in the safe
- var/maxspace = 24 //the maximum combined w_class of stuff in the safe
- var/combo_to_open //so admins know the code
+ var/dial = 0 // The position the dial is pointing to.
+
+ var/number_of_tumblers = 3 // The amount of tumblers that will be generated.
+ var/list/tumblers = list() // The list of tumbler dial positions that need to be hit.
+ var/list/current_tumbler_index = 1 // The index in the tumblers list of the tumbler dial position that needs to be hit.
+
+ var/space = 0 // The combined w_class of everything in the safe.
+ var/maxspace = 24 // The maximum combined w_class of stuff in the safe.
+
var/obj/item/thermal_drill/drill = null
var/drill_timer
var/time_to_drill
@@ -34,63 +38,81 @@ GLOBAL_LIST_EMPTY(safes)
var/drill_start_time
var/drill_x_offset = -13
var/drill_y_offset = -3
- var/knownby = list()
+ var/known_by = list()
+ var/image/progress_bar
+ var/image/drill_overlay
+
+/obj/structure/safe/Initialize(mapload)
+ . = ..()
-/obj/structure/safe/New()
GLOB.safes += src
- tumbler_2_pos = rand(0, 99) // first value in the combination set first
- tumbler_2_open = rand(0, 99)
- tumbler_1_pos = rand(0, 99)
- do
- tumbler_1_open = rand(0, 99)
- while(tumbler_1_open > Wrap(tumbler_2_open +48, 0, 100) && tumbler_1_open < Wrap(tumbler_2_open + 53, 0, 100)) // prevents a combination that wont open
- do
- open_pos = rand(0,99)
- while(open_pos > Wrap(tumbler_1_open - 2, 0, 100) && open_pos < Wrap(tumbler_1_open + 2, 0, 100)) // prevents a combination that wont open
- var/num1 = tumbler_2_open + 54
- if(num1 > 99)
- num1 = num1 - 100
- var/num2 = tumbler_1_open + 98
- if(num2 > 99)
- num2 = num2 - 100
+ for(var/i in 1 to number_of_tumblers)
+ tumblers.Add(rand(0, 99))
- combo_to_open = "[num1] - [num2]"
-
-
-/obj/structure/safe/Initialize()
- ..()
for(var/obj/item/I in loc)
if(space >= maxspace)
return
if(I.w_class + space <= maxspace)
space += I.w_class
- I.loc = src
+ I.forceMove(src)
+/obj/structure/safe/Destroy()
+ GLOB.safes -= src
+ drill?.soundloop?.stop()
+ drill?.forceMove(loc)
+ drill = null
+
+ qdel(progress_bar)
+ qdel(drill_overlay)
+ return ..()
+
+/obj/structure/safe/process()
+ if(drill_timer)
+ cut_overlay(progress_bar)
+ progress_bar = image('icons/effects/progessbar.dmi', src, "prog_bar_[round((((world.time - drill_start_time) / time_to_drill) * 100), 5)]", HUD_LAYER)
+ add_overlay(progress_bar)
+ if(prob(15))
+ drill.spark_system.start()
+
+/obj/structure/safe/examine(mob/user)
+ . = ..()
+
+ to_chat(user, "This model appears to have [number_of_tumblers] tumblers.")
+ if(open)
+ to_chat(user, "The inside of the the door has numbers written on it: [get_combination()]")
+
+/obj/structure/safe/blob_act()
+ return
+
+/obj/structure/safe/ex_act(severity)
+ return
+
+/obj/structure/safe/examine_status(mob/user)
+ return
/obj/structure/safe/proc/check_unlocked()
- if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open && dial == open_pos)
+ if(current_tumbler_index > number_of_tumblers)
locked = FALSE
+ visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!")
return TRUE
+
locked = TRUE
return FALSE
-/obj/structure/safe/proc/make_noise(turns, turns_total, tum1 = 0, tum2 = 0, mob/user, canhear)
- if(user && canhear)
- if(turns == 2)
- to_chat(user, "The sounds from [src] are too fast and blend together.")
- if(tum1 && (turns_total == 1 || prob(10))) // So multi turns dont super spam the chat
- to_chat(user, "You hear a [pick("clack", "scrape", "clank")] from [src].")
- if(tum2 && (turns_total == 1 || prob(10))) // So multi turns dont super spam the chat
- to_chat(user, "You hear a [pick("click", "chink", "clink")] from [src].")
- if(tumbler_1_pos == tumbler_1_open && turns_total == 1 && tum1) // You cant hear tumblers if you spin fast!
- to_chat(user, "You hear a [pick("tonk", "krunk", "plunk")] from [src].")
- if(tumbler_2_pos == tumbler_2_open && turns_total == 1 && tum2) // You cant hear tumblers if you spin fast!
- to_chat(user, "You hear a [pick("tink", "krink", "plink")] from [src].")
- if(!locked)
- if(user)
- visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!")
+/obj/structure/safe/proc/get_combination()
+ var/combination = ""
+ var/looped = 0
+
+ for(var/tumbler in tumblers)
+ looped++
+ combination += "[tumbler]"
+
+ if(looped < LAZYLEN(tumblers))
+ combination += ", "
+
+ return combination
/obj/structure/safe/update_icon()
if(open)
@@ -103,21 +125,32 @@ GLOBAL_LIST_EMPTY(safes)
icon_state = "[initial(icon_state)]-broken"
else
icon_state = initial(icon_state)
- overlays.Cut()
- if(istype(drill, /obj/item/thermal_drill/diamond_drill))
+
+ var/list/overlays_to_cut = list(drill_overlay)
+ if(!drill_timer)
+ overlays_to_cut += progress_bar
+
+ cut_overlay(overlays_to_cut)
+
+ if(istype(drill, /obj/item/thermal_drill))
+ var/drill_icon = istype(drill, /obj/item/thermal_drill/diamond_drill) ? "d" : "h"
if(drill_timer)
- overlays += image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_d-drill-on", pixel_x = drill_x_offset, pixel_y = drill_y_offset)
+ drill_overlay = image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_[drill_icon]-drill-on", pixel_x = drill_x_offset, pixel_y = drill_y_offset)
else
- overlays += image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_d-drill-off", pixel_x = drill_x_offset, pixel_y = drill_y_offset)
- else if(istype(drill, /obj/item/thermal_drill))
- if(drill_timer)
- overlays += image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_h-drill-on", pixel_x = drill_x_offset, pixel_y = drill_y_offset)
- else
- overlays += image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_h-drill-off", pixel_x = drill_x_offset, pixel_y = drill_y_offset)
+ drill_overlay = image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_[drill_icon]-drill-off", pixel_x = drill_x_offset, pixel_y = drill_y_offset)
+
+ add_overlay(drill_overlay)
+
+/obj/structure/safe/attack_ghost(mob/user)
+ if(..() || drill)
+ return TRUE
+
+ ui_interact(user)
/obj/structure/safe/attack_hand(mob/user)
if(..())
return TRUE
+
if(drill)
switch(alert("What would you like to do?", "Thermal Drill", "Turn [drill_timer ? "Off" : "On"]", "Remove Drill", "Cancel"))
if("Turn On")
@@ -126,14 +159,14 @@ GLOBAL_LIST_EMPTY(safes)
drill_start_time = world.time
drill.soundloop.start()
update_icon()
- processing_objects.Add(src)
+ START_PROCESSING(SSobj, src)
if("Turn Off")
if(do_after(user, 2 SECONDS, target = src))
deltimer(drill_timer)
drill_timer = null
drill.soundloop.stop()
update_icon()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
if("Remove Drill")
if(drill_timer)
to_chat(user, "You cant remove the drill while it's running!")
@@ -145,7 +178,6 @@ GLOBAL_LIST_EMPTY(safes)
return
else
ui_interact(user)
- return
/obj/structure/safe/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -161,30 +193,39 @@ GLOBAL_LIST_EMPTY(safes)
for(var/obj/O in contents)
contents_names[++contents_names.len] = list("name" = O.name, "index" = contents.Find(O), "sprite" = O.icon_state)
user << browse_rsc(icon(O.icon, O.icon_state), "[O.icon_state].png")
- else
- contents_names = list(list("name" = "you're"), list("name" = "a"), list("name" = "cheater"))
data["dial"] = dial
data["open"] = open
data["locked"] = locked
- data["rotation"] = "[-dial*3.6]deg"
+ data["rotation"] = "[-dial * 3.6]deg"
data["contents"] = contents_names
return data
+/obj/structure/safe/proc/notify_user(user, canhear, sounds, total_ticks, current_tick)
+ if(!canhear)
+ return
+
+ if(current_tick == 2)
+ to_chat(user, "The sounds from [src] are too fast and blend together.")
+
+ if(total_ticks == 1 || prob(10))
+ to_chat(user, "You hear a [pick(sounds)] from [src].")
/obj/structure/safe/Topic(href, href_list)
if(..())
return TRUE
- var/canhear = 0
- if(!ishuman(usr))
- to_chat(usr, "You don't have hands to operate the safe!")
- return FALSE
+ var/mob/user = usr
+ if(!user.IsAdvancedToolUser() && !isobserver(user))
+ to_chat(user, "You're not able to operate the safe.")
+ return
- var/mob/living/carbon/human/user = usr
- if(istype(user.l_hand, /obj/item/clothing/accessory/stethoscope) || istype(user.r_hand, /obj/item/clothing/accessory/stethoscope))
- canhear = 1
+ var/canhear = FALSE
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.can_hear() && H.is_in_hands(/obj/item/clothing/accessory/stethoscope))
+ canhear = TRUE
if(href_list["open"])
if(check_unlocked() || open || broken)
@@ -192,52 +233,65 @@ GLOBAL_LIST_EMPTY(safes)
open = !open
update_icon()
else
- to_chat(user, "You can't open [src], the lock is engaged!")
- .= TRUE
- SSnanoui.update_uis(src)
+ to_chat(user, "You can't open [src], as its lock is engaged!")
- if(href_list["decrement"])
- var/ticks = text2num(href_list["decrement"])
+ . = TRUE
+
+ if(href_list["turnright"])
if(open)
return
+
if(broken)
- to_chat(user, "The dial will not turn, the mechanism is destroyed.")
+ to_chat(user, "The dial will not turn, as the mechanism is destroyed.")
return
- for(var/i=1 to ticks)
- if(!check_unlocked())
- dial = Wrap(dial - 1, 0 ,100)
- if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 99)
- tumbler_1_pos = Wrap(tumbler_1_pos - 1, 0, 100)
- make_noise(i, ticks, 1, 0, user, canhear)
- if(tumbler_1_pos == tumbler_2_pos + 51 || tumbler_1_pos == tumbler_2_pos - 49)
- tumbler_2_pos = Wrap(tumbler_2_pos - 1, 0, 100)
- make_noise(0, ticks, 0, 1, user, canhear)
+
+ var/ticks = text2num(href_list["turnright"])
+ for(var/i = 1 to ticks)
+ dial = Wrap(dial - 1, 0, 100)
+
+ var/invalid_turn = current_tumbler_index % 2 == 0 || current_tumbler_index > number_of_tumblers
+ if(invalid_turn) // The moment you turn the wrong way or go too far, the tumblers reset
+ current_tumbler_index = 1
+
+ if(!invalid_turn && dial == tumblers[current_tumbler_index])
+ notify_user(user, canhear, list("tink", "krink", "plink"), ticks, i)
+ current_tumbler_index++
+ else
+ notify_user(user, canhear, list("clack", "scrape", "clank"), ticks, i)
+
sleep(1)
- check_unlocked()
+ check_unlocked(user, canhear)
SSnanoui.update_uis(src)
- make_noise(0, 0, 0, 0, user, canhear)
- .= TRUE
- if(href_list["increment"])
- var/ticks = text2num(href_list["increment"])
+ . = TRUE
+
+ if(href_list["turnleft"])
if(open)
return
+
if(broken)
- to_chat(user, "The dial will not turn, the mechanism is destroyed.")
+ to_chat(user, "The dial will not turn, as the mechanism is destroyed.")
return
- for(var/i=1 to ticks)
- check_unlocked()
+
+ var/ticks = text2num(href_list["turnleft"])
+ for(var/i = 1 to ticks)
dial = Wrap(dial + 1, 0, 100)
- if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 99)
- tumbler_1_pos = Wrap(tumbler_1_pos + 1, 0, 100)
- make_noise(i, ticks, 1, 0, user, canhear)
- if(tumbler_1_pos == tumbler_2_pos - 51 || tumbler_1_pos == tumbler_2_pos + 49)
- tumbler_2_pos = Wrap(tumbler_2_pos + 1, 0, 100)
- make_noise(0, ticks, 0, 1, user, canhear)
+
+ var/invalid_turn = current_tumbler_index % 2 != 0 || current_tumbler_index > number_of_tumblers
+ if(invalid_turn) // The moment you turn the wrong way or go too far, the tumblers reset
+ current_tumbler_index = 1
+
+ if(!invalid_turn && dial == tumblers[current_tumbler_index])
+ notify_user(user, canhear, list("tonk", "krunk", "plunk"), ticks, i)
+ current_tumbler_index++
+ else
+ notify_user(user, canhear, list("click", "chink", "clink"), ticks, i)
+
sleep(1)
+ check_unlocked(user, canhear)
SSnanoui.update_uis(src)
- make_noise(0, 0, 0, 0, user, canhear)
- .= TRUE
+
+ . = TRUE
if(href_list["retrieve"])
var/index = text2num(href_list["retrieve"])
@@ -247,104 +301,67 @@ GLOBAL_LIST_EMPTY(safes)
if(P && in_range(src, user))
user.put_in_hands(P)
space -= P.w_class
- SSnanoui.update_uis(src)
- .= TRUE
-
-
- updateUsrDialog()
- return
-
-
-/obj/structure/safe/attackby(obj/item/I, mob/user, params)
- if(open)
- if(broken && istype(I, /obj/item/safe_internals) && do_after(user, 2 SECONDS, target = src))
- to_chat(user, "You replace the broken mechanism.")
- qdel(I)
- broken = !broken
- update_icon()
- return
- else if(I.w_class + space <= maxspace)
- space += I.w_class
- if(!user.drop_item())
- to_chat(user, "\The [I] is stuck to your hand, you cannot put it in the safe!")
- return
- I.loc = src
- to_chat(user, "You put [I] in [src].")
- updateUsrDialog()
- return
- else
- to_chat(user, "[I] won't fit in [src].")
- return
- else
- if(istype(I, /obj/item/clothing/accessory/stethoscope))
- to_chat(user, "Hold [I] in one of your hands while you manipulate the dial!")
- return
- else if(istype(I, /obj/item/thermal_drill))
- if(drill)
- to_chat(user, "There is already a drill attached!")
- else if(do_after(user, 2 SECONDS, target = src))
- if(!user.drop_item())
- to_chat(user, "[I] is stuck to your hand, you cannot put it in the safe!")
- return
- I.loc = src
- drill = I
- time_to_drill = 300 SECONDS * drill.time_multiplier
- update_icon()
- else
- to_chat(user, "You can't put [I] in into the safe while it is closed!")
- return
+ . = TRUE
/obj/structure/safe/proc/drill_open()
broken = TRUE
drill_timer = null
drill.soundloop.stop()
update_icon()
- processing_objects.Remove(src)
+ STOP_PROCESSING(SSobj, src)
-/obj/structure/safe/blob_act()
- return
-
-/obj/structure/safe/ex_act(severity)
- return
-
-/obj/structure/safe/examine_status(mob/user)
- return
-
-/obj/structure/safe/Destroy()
- GLOB.safes -= src
- drill?.soundloop?.stop()
- return ..()
-
-/obj/structure/safe/process()
- if(drill_timer)
- overlays -= bar
- bar = image('icons/effects/progessbar.dmi', src, "prog_bar_[round((((world.time - drill_start_time) / time_to_drill) * 100), 5)]", HUD_LAYER)
- overlays += bar
- if(prob(15))
- drill.spark_system.start()
-
-/obj/structure/safe/examine(mob/user)
- ..()
+/obj/structure/safe/attackby(obj/item/I, mob/user, params)
if(open)
- to_chat(user, "On the inside of the the door is [combo_to_open]")
+ if(broken && istype(I, /obj/item/safe_internals) && do_after(user, 2 SECONDS, target = src))
+ to_chat(user, "You replace the broken mechanism.")
+ qdel(I)
+ broken = !broken
+ update_icon()
+ else if(I.w_class + space <= maxspace)
+ if(!user.drop_item())
+ to_chat(user, "\The [I] is stuck to your hand, you cannot put it in the safe!")
+ return
+ space += I.w_class
+ I.forceMove(src)
+ to_chat(user, "You put [I] in [src].")
+ else
+ to_chat(user, "[I] won't fit in [src].")
+ else
+ if(istype(I, /obj/item/clothing/accessory/stethoscope))
+ to_chat(user, "Hold [I] in one of your hands while you manipulate the dial!")
+ return
+ else if(istype(I, /obj/item/thermal_drill))
+ if(drill)
+ to_chat(user, "There is already a drill attached!")
+ else if(do_after(user, 2 SECONDS, target = src))
+ if(!user.drop_item())
+ to_chat(user, "[I] is stuck to your hand, you cannot put it in the safe!")
+ return
+ I.forceMove(src)
+ drill = I
+ time_to_drill = 300 SECONDS * drill.time_multiplier
+ update_icon()
+ else
+ to_chat(user, "You can't put [I] into the safe while it is closed!")
+ return
//FLOOR SAFES
/obj/structure/safe/floor
name = "floor safe"
icon_state = "floorsafe"
- density = 0
- level = 1 //underfloor
- layer = 2.5
+ density = FALSE
+ level = 1 //Under the floor
+ layer = LOW_OBJ_LAYER
drill_x_offset = -1
drill_y_offset = 20
/obj/structure/safe/floor/Initialize()
- ..()
+ . = ..()
var/turf/T = loc
hide(T.intact)
-/obj/structure/safe/floor/hide(var/intact)
- invisibility = intact ? 101 : 0
+/obj/structure/safe/floor/hide(intact)
+ invisibility = intact ? INVISIBILITY_MAXIMUM : 0
/obj/item/safe_internals
name = "safe internals"
@@ -356,14 +373,14 @@ GLOBAL_LIST_EMPTY(safes)
var/owner
info = "
Safe Codes
"
-/obj/item/paper/safe_code/New()
- ..()
- addtimer(CALLBACK(src, .proc/populate_codes), 10)
+/obj/item/paper/safe_code/Initialize(mapload)
+ return INITIALIZE_HINT_LATELOAD
-/obj/item/paper/safe_code/proc/populate_codes()
+/obj/item/paper/safe_code/LateInitialize(mapload)
+ . = ..()
for(var/safe in GLOB.safes)
var/obj/structure/safe/S = safe
- if(owner in S.knownby)
- info += " The combination for the safe located in the [get_area(S).name] is: [S.combo_to_open] "
+ if(owner in S.known_by)
+ info += " The combination for the safe located in the [get_area(S).name] is: [S.get_combination()] "
info_links = info
update_icon()
\ No newline at end of file
diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm
index 6168d637c56..345d35cb4aa 100644
--- a/code/game/objects/structures/signs.dm
+++ b/code/game/objects/structures/signs.dm
@@ -106,6 +106,11 @@
desc = "A warning sign which reads 'HARD VACUUM AHEAD'"
icon_state = "space"
+/obj/structure/sign/vacuum/external
+ name = "\improper EXTERNAL AIRLOCK"
+ desc = "A warning sign which reads 'EXTERNAL AIRLOCK'."
+ layer = MOB_LAYER
+
/obj/structure/sign/deathsposal
name = "\improper DISPOSAL LEADS TO SPACE"
desc = "A warning sign which reads 'DISPOSAL LEADS TO SPACE'"
@@ -131,6 +136,15 @@
desc = "A warning sign which reads 'NO SMOKING'"
icon_state = "nosmoking2"
+/obj/structure/sign/radiation
+ name = "\improper HAZARDOUS RADIATION"
+ desc = "A warning sign alerting the user of potential radiation hazards."
+ icon_state = "radiation"
+
+/obj/structure/sign/radiation/rad_area
+ name = "\improper RADIOACTIVE AREA"
+ desc = "A warning sign which reads 'RADIOACTIVE AREA'."
+
/obj/structure/sign/redcross
name = "medbay"
desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here.'"
@@ -161,21 +175,6 @@
desc = "A dead and stuffed Diona nymph, mounted on a board."
icon_state = "kidanplaque"
-/obj/structure/sign/science //These 3 have multiple types, just var-edit the icon_state to whatever one you want on the map
- name = "\improper SCIENCE!"
- desc = "A warning sign which reads 'SCIENCE!'"
- icon_state = "science1"
-
-/obj/structure/sign/chemistry
- name = "\improper CHEMISTRY"
- desc = "A warning sign which reads 'CHEMISTRY'"
- icon_state = "chemistry1"
-
-/obj/structure/sign/botany
- name = "\improper HYDROPONICS"
- desc = "A warning sign which reads 'HYDROPONICS'"
- icon_state = "hydro1"
-
/obj/structure/sign/mech
name = "\improper mech painting"
desc = "A painting of a mech"
@@ -211,6 +210,74 @@
desc = "A glowing dragon invites you in."
icon_state = "chinese"
+/obj/structure/sign/science
+ name = "\improper SCIENCE!"
+ desc = "A warning sign which reads 'SCIENCE!'"
+ icon_state = "science1"
+
+/obj/structure/sign/chemistry
+ name = "\improper CHEMISTRY"
+ desc = "A warning sign which reads 'CHEMISTRY'"
+ icon_state = "chemistry1"
+
+/obj/structure/sign/botany
+ name = "\improper HYDROPONICS"
+ desc = "A warning sign which reads 'HYDROPONICS'"
+ icon_state = "hydro1"
+
+/obj/structure/sign/xenobio
+ name = "\improper XENOBIOLOGY"
+ desc = "A sign labelling an area as a place where xenobiological entities are researched."
+ icon_state = "xenobio"
+
+/obj/structure/sign/evac
+ name = "\improper EVACUATION"
+ desc = "A sign labelling an area where evacuation procedures take place."
+ icon_state = "evac"
+
+/obj/structure/sign/drop
+ name = "\improper DROP PODS"
+ desc = "A sign labelling an area where drop pod loading procedures take place."
+ icon_state = "drop"
+
+/obj/structure/sign/custodian
+ name = "\improper CUSTODIAN"
+ desc = "A sign labelling an area where the custodian works."
+ icon_state = "custodian"
+
+/obj/structure/sign/engineering
+ name = "\improper ENGINEERING"
+ desc = "A sign labelling an area where engineers work."
+ icon_state = "engine"
+
+/obj/structure/sign/cargo
+ name = "\improper CARGO"
+ desc = "A sign labelling an area where cargo ships dock."
+ icon_state = "cargo"
+
+/obj/structure/sign/security
+ name = "\improper SECURITY"
+ desc = "A sign labelling an area where the law is law."
+ icon_state = "security"
+
+/obj/structure/sign/holy
+ name = "\improper HOLY"
+ desc = "A sign labelling a religious area."
+ icon_state = "holy"
+
+/obj/structure/sign/restroom
+ name = "\improper RESTROOM"
+ desc = "A sign labelling a restroom."
+ icon_state = "restroom"
+
+/obj/structure/sign/medbay
+ name = "\improper MEDBAY"
+ desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here."
+ icon_state = "bluecross"
+
+/obj/structure/sign/medbay/alt
+ icon_state = "bluecross2"
+
/obj/structure/sign/directions/science
name = "\improper Research Division"
desc = "A direction sign, pointing out which way the Research Division is."
@@ -235,3 +302,18 @@
name = "\improper Escape Arm"
desc = "A direction sign, pointing out which way escape shuttle dock is."
icon_state = "direction_evac"
+
+/obj/structure/sign/directions/cargo
+ name = "\improper Cargo Department"
+ desc = "A direction sign, pointing out which way the Cargo department is."
+ icon_state = "direction_supply"
+
+/obj/structure/sign/explosives
+ name = "\improper HIGH EXPLOSIVES"
+ desc = "A warning sign which reads 'HIGH EXPLOSIVES'."
+ icon_state = "explosives"
+
+/obj/structure/sign/explosives/alt
+ name = "\improper HIGH EXPLOSIVES"
+ desc = "A warning sign which reads 'HIGH EXPLOSIVES'."
+ icon_state = "explosives2"
\ No newline at end of file
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index 88adc9643ba..6f531f5c14c 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -256,18 +256,18 @@
/obj/structure/statue/diamond
hardness = 10
material_drop_type = /obj/item/stack/sheet/mineral/diamond
- desc = "This is a very expensive diamond statue"
+ desc = "This is a very expensive diamond statue."
/obj/structure/statue/diamond/captain
- name = "statue of THE captain."
+ name = "statue of THE captain"
icon_state = "cap"
/obj/structure/statue/diamond/ai1
- name = "statue of the AI hologram."
+ name = "statue of the AI hologram"
icon_state = "ai1"
/obj/structure/statue/diamond/ai2
- name = "statue of the AI core."
+ name = "statue of the AI core"
icon_state = "ai2"
/obj/structure/statue/bananium
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 98da892a00f..15e578ed88f 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -28,6 +28,11 @@
W.setDir(dir)
qdel(src)
+/obj/structure/chair/ratvar_act()
+ var/obj/structure/chair/brass/B = new(get_turf(src))
+ B.setDir(dir)
+ qdel(src)
+
/obj/structure/chair/Move(atom/newloc, direct)
..()
handle_rotation()
@@ -59,6 +64,12 @@
if(usr.incapacitated())
to_chat(usr, "You can't do that right now!")
return
+ if(!usr.has_right_hand() && !usr.has_left_hand())
+ to_chat(usr, "You try to grab the chair, but you are missing both of your hands!")
+ return
+ if(usr.get_active_hand() && usr.get_inactive_hand())
+ to_chat(usr, "You try to grab the chair, but your hands are already full!")
+ return
if(!ishuman(usr))
return
usr.visible_message("[usr] grabs \the [src.name].", "You grab \the [src.name].")
@@ -80,7 +91,7 @@
/obj/structure/chair/proc/handle_layer()
if(buckled_mob && dir == NORTH)
- layer = FLY_LAYER
+ layer = ABOVE_MOB_LAYER
else
layer = OBJ_LAYER
@@ -146,35 +157,38 @@
name = "comfy chair"
desc = "It looks comfy."
icon_state = "comfychair"
- color = rgb(255,255,255)
+ color = rgb(255, 255, 255)
burn_state = FLAMMABLE
burntime = 30
buildstackamount = 2
item_chair = null
var/image/armrest = null
-/obj/structure/chair/comfy/New()
- armrest = image("icons/obj/chairs.dmi", "comfychair_armrest")
+/obj/structure/chair/comfy/Initialize(mapload)
+ armrest = GetArmrest()
armrest.layer = ABOVE_MOB_LAYER
return ..()
+/obj/structure/chair/comfy/proc/GetArmrest()
+ return mutable_appearance('icons/obj/chairs.dmi', "comfychair_armrest")
+
/obj/structure/chair/comfy/Destroy()
QDEL_NULL(armrest)
return ..()
/obj/structure/chair/comfy/post_buckle_mob(mob/living/M)
- ..()
- if(buckled_mob)
- overlays += armrest
- else
- overlays -= armrest
+ . = ..()
+ update_armrest()
/obj/structure/chair/comfy/post_unbuckle_mob(mob/living/M)
- ..()
- if(buckled_mob)
- overlays -= armrest
+ . = ..()
+ update_armrest()
+
+/obj/structure/chair/comfy/proc/update_armrest()
+ if(has_buckled_mobs())
+ add_overlay(armrest)
else
- overlays += armrest
+ cut_overlay(armrest)
/obj/structure/chair/comfy/brown
color = rgb(141,70,0)
@@ -209,6 +223,14 @@
item_chair = null
buildstackamount = 5
+/obj/structure/chair/comfy/shuttle
+ name = "shuttle seat"
+ desc = "A comfortable, secure seat. It has a more sturdy looking buckling system, for smoother flights."
+ icon_state = "shuttle_chair"
+
+/obj/structure/chair/comfy/shuttle/GetArmrest()
+ return mutable_appearance('icons/obj/chairs.dmi', "shuttle_chair_armrest")
+
/obj/structure/chair/office/Bump(atom/A)
..()
if(!buckled_mob)
@@ -416,3 +438,41 @@
desc = "You sit in this. Either by will or force. Looks REALLY uncomfortable."
icon_state = "chairold"
item_chair = null
+
+// Brass chair
+/obj/structure/chair/brass
+ name = "brass chair"
+ desc = "A spinny chair made of brass. It looks uncomfortable."
+ icon_state = "brass_chair"
+ max_integrity = 150
+ buildstacktype = /obj/item/stack/tile/brass
+ buildstackamount = 1
+ item_chair = null
+ var/turns = 0
+
+/obj/structure/chair/brass/Destroy()
+ STOP_PROCESSING(SSfastprocess, src)
+ . = ..()
+
+/obj/structure/chair/brass/process()
+ setDir(turn(dir,-90))
+ playsound(src, 'sound/effects/servostep.ogg', 50, FALSE)
+ turns++
+ if(turns >= 8)
+ STOP_PROCESSING(SSfastprocess, src)
+
+/obj/structure/chair/brass/ratvar_act()
+ return
+
+/obj/structure/chair/brass/AltClick(mob/living/user)
+ turns = 0
+ if(!istype(user) || user.incapacitated() || !in_range(src, user))
+ return
+ if(!isprocessing)
+ user.visible_message("[user] spins [src] around, and Ratvarian technology keeps it spinning FOREVER.", \
+ "Automated spinny chairs. The pinnacle of Ratvarian technology.")
+ START_PROCESSING(SSfastprocess, src)
+ else
+ user.visible_message("[user] stops [src]'s uncontrollable spinning.", \
+ "You grab [src] and stop its wild spinning.")
+ STOP_PROCESSING(SSfastprocess, src)
\ No newline at end of file
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 999e90cd89f..ac013ebcf93 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -377,7 +377,7 @@
qdel(i)
. = ..()
-/obj/structure/table/glass/Crossed(atom/movable/AM)
+/obj/structure/table/glass/Crossed(atom/movable/AM, oldloc)
. = ..()
if(!can_deconstruct)
return
diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm
index a51f58e5ec6..591157e8bd6 100644
--- a/code/game/objects/structures/target_stake.dm
+++ b/code/game/objects/structures/target_stake.dm
@@ -13,7 +13,7 @@
return ..()
/obj/structure/target_stake/Move()
- ..()
+ . = ..()
// Move the pinned target along with the stake
if(pinned_target in view(3, src))
pinned_target.loc = loc
diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm
index 810659d81bb..04271015f4c 100644
--- a/code/game/objects/structures/transit_tubes/station.dm
+++ b/code/game/objects/structures/transit_tubes/station.dm
@@ -19,10 +19,10 @@
/obj/structure/transit_tube/station/New()
..()
- processing_objects += src
+ START_PROCESSING(SSobj, src)
/obj/structure/transit_tube/station/Destroy()
- processing_objects -= src
+ STOP_PROCESSING(SSobj, src)
return ..()
// Stations which will send the tube in the opposite direction after their stop.
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index b48774eb046..ada70921c99 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -363,7 +363,7 @@
qdel(mymist)
ismist = 0
-/obj/machinery/shower/Crossed(atom/movable/O)
+/obj/machinery/shower/Crossed(atom/movable/O, oldloc)
..()
wash(O)
if(ismob(O))
@@ -600,7 +600,7 @@
wateract = (W.wash(user, src))
busy = 0
if(wateract)
- W.water_act(20,310.15,src)
+ W.water_act(20, 310.15, src)
if("Disconnect")
user.visible_message("[user] starts disconnecting [src].", "You begin disconnecting [src]...")
if(do_after(user, 40 * O.toolspeed, target = src))
@@ -633,7 +633,7 @@
wateract = (O.wash(user, src))
busy = 0
if(wateract)
- O.water_act(20,310.15,src)
+ O.water_act(20, 310.15, src)
/obj/structure/sink/update_icon()
..()
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index 72469e2ebfb..1124745d8b3 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -46,7 +46,7 @@ obj/structure/windoor_assembly/Destroy()
/obj/structure/windoor_assembly/Move()
var/turf/T = loc
- ..()
+ . = ..()
setDir(ini_dir)
move_update_air(T)
@@ -269,51 +269,37 @@ obj/structure/windoor_assembly/Destroy()
density = TRUE //Shouldn't matter but just incase
to_chat(user, "You finish the windoor.")
-
+ var/obj/machinery/door/window/windoor
if(secure)
- var/obj/machinery/door/window/brigdoor/windoor = new /obj/machinery/door/window/brigdoor(src.loc)
+ windoor = new /obj/machinery/door/window/brigdoor(src.loc)
if(facing == "l")
windoor.icon_state = "leftsecureopen"
windoor.base_state = "leftsecure"
else
windoor.icon_state = "rightsecureopen"
windoor.base_state = "rightsecure"
- windoor.setDir(dir)
- windoor.density = FALSE
-
- if(electronics.one_access)
- windoor.req_one_access = electronics.conf_access
- else
- windoor.req_access = electronics.conf_access
- windoor.electronics = src.electronics
- electronics.forceMove(windoor)
- if(created_name)
- windoor.name = created_name
- qdel(src)
- windoor.close()
-
-
else
- var/obj/machinery/door/window/windoor = new /obj/machinery/door/window(loc)
+ windoor = new /obj/machinery/door/window(loc)
if(facing == "l")
windoor.icon_state = "leftopen"
windoor.base_state = "left"
else
windoor.icon_state = "rightopen"
windoor.base_state = "right"
- windoor.setDir(dir)
- windoor.density = FALSE
+ windoor.setDir(dir)
+ windoor.density = FALSE
- if(electronics.one_access)
- windoor.req_one_access = electronics.conf_access
- else
- windoor.req_access = electronics.conf_access
- windoor.electronics = src.electronics
- electronics.forceMove(windoor)
- if(created_name)
- windoor.name = created_name
- qdel(src)
- windoor.close()
+ if(electronics.one_access)
+ windoor.req_one_access = electronics.conf_access
+ else
+ windoor.req_access = electronics.conf_access
+ windoor.electronics = src.electronics
+ electronics.forceMove(windoor)
+ electronics = null
+ if(created_name)
+ windoor.name = created_name
+ qdel(src)
+ windoor.close()
else
return ..()
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index ad655a39b64..16851097844 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -4,7 +4,7 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f
/obj/proc/color_windows(obj/W)
var/list/wcBarAreas = list(/area/crew_quarters/bar)
- var/list/wcBrigAreas = list(/area/security,/area/prison,/area/shuttle/gamma)
+ var/list/wcBrigAreas = list(/area/security, /area/shuttle/gamma)
var/newcolor
var/turf/T = get_turf(W)
@@ -431,7 +431,7 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f
/obj/structure/window/Move()
var/turf/T = loc
- ..()
+ . = ..()
setDir(ini_dir)
move_update_air(T)
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 9e0a28493bd..d27239ae4e7 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -5,6 +5,9 @@
var/turf/turf_source = get_turf(source)
+ if(!turf_source)
+ return
+
//allocate a channel if necessary now so its the same for everyone
channel = channel || open_sound_channel()
@@ -18,13 +21,17 @@
var/mob/M = P
if(!M || !M.client)
continue
+
+ var/turf/T = get_turf(M) // These checks need to be changed if z-levels are ever further refactored
+ if(!T)
+ continue
+ if(T.z != turf_source.z)
+ continue
+
var/distance = get_dist(M, turf_source)
if(distance <= maxdistance)
- var/turf/T = get_turf(M)
-
- if(T && T.z == turf_source.z)
- M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S)
+ M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S)
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S)
if(!client || !can_hear())
@@ -101,10 +108,10 @@
SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = chan))
/client/proc/playtitlemusic()
- if(!ticker || !ticker.login_music || config.disable_lobby_music)
+ if(!SSticker || !SSticker.login_music || config.disable_lobby_music)
return
if(prefs.sound & SOUND_LOBBY)
- SEND_SOUND(src, sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = CHANNEL_LOBBYMUSIC)) // MAD JAMS
+ SEND_SOUND(src, sound(SSticker.login_music, repeat = 0, wait = 0, volume = 85, channel = CHANNEL_LOBBYMUSIC)) // MAD JAMS
/proc/get_rand_frequency()
return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs.
@@ -153,4 +160,4 @@
soundin = pick('sound/effects/bone_break_1.ogg', 'sound/effects/bone_break_2.ogg', 'sound/effects/bone_break_3.ogg', 'sound/effects/bone_break_4.ogg', 'sound/effects/bone_break_5.ogg', 'sound/effects/bone_break_6.ogg')
if("honkbot_e")
soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bcreep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg')
- return soundin
+ return soundin
\ No newline at end of file
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index 51549c1a563..f54e28defb1 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -10,6 +10,7 @@
var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to
var/dirt = 0
var/dirtoverlay = null
+ var/unacidable = FALSE
/turf/simulated/New()
..()
@@ -17,8 +18,24 @@
visibilityChanged()
/turf/simulated/proc/break_tile()
+ return
/turf/simulated/proc/burn_tile()
+ return
+
+/turf/simulated/water_act(volume, temperature, source)
+ . = ..()
+
+ if(volume >= 3)
+ MakeSlippery()
+
+ var/hotspot = (locate(/obj/effect/hotspot) in src)
+ if(hotspot)
+ var/datum/gas_mixture/lowertemp = remove_air(air.total_moles())
+ lowertemp.temperature = max(min(lowertemp.temperature-2000,lowertemp.temperature / 2), 0)
+ lowertemp.react()
+ assume_air(lowertemp)
+ qdel(hotspot)
/turf/simulated/proc/MakeSlippery(wet_setting = TURF_WET_WATER) // 1 = Water, 2 = Lube, 3 = Ice, 4 = Permafrost
if(wet >= wet_setting)
@@ -35,7 +52,10 @@
else
wet_overlay = image('icons/effects/water.dmi', src, "wet_floor_static")
else
- wet_overlay = image('icons/effects/water.dmi', src, "wet_static")
+ if(wet_setting >= TURF_WET_ICE)
+ wet_overlay = image('icons/effects/water.dmi', src, "ice_floor")
+ else
+ wet_overlay = image('icons/effects/water.dmi', src, "wet_static")
overlays += wet_overlay
spawn(rand(790, 820)) // Purely so for visual effect
@@ -74,22 +94,28 @@
switch(src.wet)
if(TURF_WET_WATER)
- if(!(M.slip("wet floor", 4, 2, tilesSlipped = 0, walkSafely = 1)))
+ if(!(M.slip("the wet floor", 4, 2, tilesSlipped = 0, walkSafely = 1)))
M.inertia_dir = 0
return
if(TURF_WET_LUBE) //lube
- M.slip("floor", 0, 5, tilesSlipped = 3, walkSafely = 0, slipAny = 1)
+ M.slip("the floor", 0, 5, tilesSlipped = 3, walkSafely = 0, slipAny = 1)
if(TURF_WET_ICE) // Ice
- if(!(prob(30) && M.slip("icy floor", 4, 2, tilesSlipped = 1, walkSafely = 1)))
+ if(M.slip("the icy floor", 4, 2, tilesSlipped = 0, walkSafely = 0))
M.inertia_dir = 0
+ if(prob(5))
+ var/obj/item/organ/external/affected = M.get_organ("head")
+ if(affected)
+ M.apply_damage(5, BRUTE, "head")
+ M.visible_message("[M] hits their head on the ice!")
+ playsound(src, 'sound/weapons/genhit1.ogg', 50, 1)
if(TURF_WET_PERMAFROST) // Permafrost
- M.slip("icy floor", 0, 5, tilesSlipped = 1, walkSafely = 0, slipAny = 1)
+ M.slip("the frosted floor", 0, 5, tilesSlipped = 1, walkSafely = 0, slipAny = 1)
-/turf/simulated/ChangeTurf(var/path)
+/turf/simulated/ChangeTurf(path, defer_change = FALSE, keep_icon = TRUE, ignore_air = FALSE)
. = ..()
queue_smooth_neighbors(src)
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 6b3dc1e93ff..7166a7fbfc0 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -17,7 +17,7 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
name = "floor"
icon = 'icons/turf/floors.dmi'
icon_state = "dont_use_this_floor"
-
+ plane = FLOOR_PLANE
var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default
var/icon_plating = "plating"
thermal_conductivity = 0.040
@@ -31,7 +31,6 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
var/list/broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5")
var/list/burnt_states = list("floorscorched1", "floorscorched2")
-
/turf/simulated/floor/New()
..()
if(icon_state in icons_to_ignore_at_floor_init) //so damaged/burned tiles or plating icons aren't saved as the default
@@ -57,26 +56,26 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
return
switch(severity)
if(1.0)
- src.ChangeTurf(/turf/space)
+ ChangeTurf(baseturf)
if(2.0)
switch(pick(1,2;75,3))
if(1)
spawn(0)
- src.ReplaceWithLattice()
+ ReplaceWithLattice()
if(prob(33)) new /obj/item/stack/sheet/metal(src)
if(2)
- src.ChangeTurf(/turf/space)
+ ChangeTurf(baseturf)
if(3)
if(prob(80))
- src.break_tile_to_plating()
+ break_tile_to_plating()
else
- src.break_tile()
- src.hotspot_expose(1000,CELL_VOLUME)
+ break_tile()
+ hotspot_expose(1000,CELL_VOLUME)
if(prob(33)) new /obj/item/stack/sheet/metal(src)
if(3.0)
if(prob(50))
- src.break_tile()
- src.hotspot_expose(1000,CELL_VOLUME)
+ break_tile()
+ hotspot_expose(1000,CELL_VOLUME)
return
/turf/simulated/floor/burn_down()
@@ -91,8 +90,7 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
return
/turf/simulated/floor/proc/update_icon()
- if(air)
- update_visuals()
+ update_visuals()
overlays -= current_overlay
if(current_overlay)
overlays.Add(current_overlay)
@@ -122,31 +120,40 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
/turf/simulated/floor/proc/make_plating()
return ChangeTurf(/turf/simulated/floor/plating)
-/turf/simulated/floor/ChangeTurf(turf/simulated/floor/T, defer_change = FALSE, keep_icon = TRUE)
- if(!istype(src,/turf/simulated/floor)) return ..() //fucking turfs switch the fucking src of the fucking running procs
- if(!ispath(T,/turf/simulated/floor)) return ..()
+/turf/simulated/floor/ChangeTurf(turf/simulated/floor/T, defer_change = FALSE, keep_icon = TRUE, ignore_air = FALSE)
+ if(!istype(src, /turf/simulated/floor))
+ return ..() //fucking turfs switch the fucking src of the fucking running procs
+ if(!ispath(T, /turf/simulated/floor))
+ return ..()
+
var/old_icon = icon_regular_floor
var/old_plating = icon_plating
var/old_dir = dir
+
var/turf/simulated/floor/W = ..()
+
if(keep_icon)
W.icon_regular_floor = old_icon
W.icon_plating = old_plating
W.dir = old_dir
+
W.update_icon()
return W
-
/turf/simulated/floor/attackby(obj/item/C as obj, mob/user as mob, params)
if(!C || !user)
- return 1
+ return TRUE
+
if(..())
- return 1
+ return TRUE
+
if(intact && iscrowbar(C))
pry_tile(C, user)
- return 1
+ return TRUE
+
if(intact && istype(C, /obj/item/stack/tile))
try_replace_tile(C, user, params)
+
if(istype(C, /obj/item/pipe))
var/obj/item/pipe/P = C
if(P.pipe_type != -1) // ANY PIPE
@@ -155,6 +162,7 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
"You slide [P] along \the [src].", \
"You hear the scrape of metal against something.")
user.drop_item()
+
if(P.is_bent_pipe()) // bent pipe rotation fix see construction.dm
P.dir = 5
if(user.dir == 1)
@@ -164,13 +172,14 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
else if(user.dir == 4)
P.dir = 10
else
- P.dir = user.dir
+ P.setDir(user.dir)
+
P.x = src.x
P.y = src.y
P.z = src.z
- P.loc = src
- return 1
- return 0
+ P.forceMove(src)
+ return TRUE
+ return FALSE
/turf/simulated/floor/proc/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
if(T.turf_type == type)
diff --git a/code/game/turfs/simulated/floor/asteroid.dm b/code/game/turfs/simulated/floor/asteroid.dm
new file mode 100644
index 00000000000..5f2ad4b629c
--- /dev/null
+++ b/code/game/turfs/simulated/floor/asteroid.dm
@@ -0,0 +1,330 @@
+/**********************Asteroid**************************/
+
+/turf/simulated/floor/plating/asteroid
+ name = "asteroid sand"
+ baseturf = /turf/simulated/floor/plating/asteroid
+ icon_state = "asteroid"
+ icon_plating = "asteroid"
+ var/environment_type = "asteroid"
+ var/turf_type = /turf/simulated/floor/plating/asteroid //Because caves do whacky shit to revert to normal
+ var/dug = 0 //0 = has not yet been dug, 1 = has already been dug
+ var/sand_type = /obj/item/stack/ore/glass
+ var/floor_variance = 20 //probability floor has a different icon state
+
+/turf/simulated/floor/plating/asteroid/New()
+ var/proper_name = name
+ ..()
+ name = proper_name
+ if(prob(floor_variance))
+ icon_state = "[environment_type][rand(0,12)]"
+
+/turf/simulated/floor/plating/asteroid/burn_tile()
+ return
+
+/turf/simulated/floor/plating/asteroid/MakeSlippery(wet_setting)
+ return
+
+/turf/simulated/floor/plating/asteroid/MakeDry(wet_setting)
+ return
+
+/turf/simulated/floor/plating/asteroid/remove_plating()
+ return
+
+/turf/simulated/floor/plating/asteroid/ex_act(severity, target)
+ switch(severity)
+ if(3)
+ return
+ if(2)
+ if(prob(20))
+ gets_dug()
+ if(1)
+ gets_dug()
+
+/turf/simulated/floor/plating/asteroid/attackby(obj/item/W, mob/user, params)
+ //note that this proc does not call ..()
+ if(!W || !user)
+ return 0
+
+ if((istype(W, /obj/item/shovel) || istype(W, /obj/item/pickaxe)))
+ var/turf/T = get_turf(user)
+ if(!istype(T))
+ return
+
+ if(dug)
+ to_chat(user, "This area has already been dug!")
+ return
+
+ to_chat(user, "You start digging...")
+ playsound(src, W.usesound, 50, 1)
+ if(do_after(user, 20 * W.toolspeed, target = src))
+ to_chat(user, "You dig a hole.")
+ gets_dug()
+ return
+
+ else if(istype(W,/obj/item/storage/bag/ore))
+ var/obj/item/storage/bag/ore/S = W
+ if(S.collection_mode == 1)
+ for(var/obj/item/stack/ore/O in src.contents)
+ O.attackby(W,user)
+ return
+
+ else if(istype(W, /obj/item/stack/tile))
+ var/obj/item/stack/tile/Z = W
+ if(!Z.use(1))
+ return
+ if(istype(Z, /obj/item/stack/tile/plasteel)) // Turn asteroid floors into plating by default
+ ChangeTurf(/turf/simulated/floor/plating, keep_icon = FALSE)
+ else
+ ChangeTurf(Z.turf_type, keep_icon = FALSE)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
+
+/turf/simulated/floor/plating/asteroid/gets_drilled()
+ if(!dug)
+ gets_dug()
+ else
+ ..()
+
+/turf/simulated/floor/plating/asteroid/proc/gets_dug()
+ if(dug)
+ return
+ for(var/i in 1 to 5)
+ new sand_type(src)
+ dug = 1
+ icon_plating = "[environment_type]_dug"
+ icon_state = "[environment_type]_dug"
+ slowdown = 0
+ return
+
+/turf/simulated/floor/plating/asteroid/basalt
+ name = "volcanic floor"
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt
+ icon_state = "basalt"
+ icon_plating = "basalt"
+ environment_type = "basalt"
+ sand_type = /obj/item/stack/ore/glass/basalt
+ floor_variance = 15
+
+/turf/simulated/floor/plating/asteroid/basalt/lava //lava underneath
+ baseturf = /turf/simulated/floor/plating/lava/smooth
+
+/turf/simulated/floor/plating/asteroid/basalt/airless
+ temperature = TCMB
+ oxygen = 0
+ nitrogen = 0
+
+/turf/simulated/floor/plating/asteroid/basalt/Initialize()
+ . = ..()
+ set_basalt_light(src)
+
+/proc/set_basalt_light(turf/simulated/floor/B)
+ switch(B.icon_state)
+ if("basalt1", "basalt2", "basalt3")
+ B.set_light(2, 0.6, LIGHT_COLOR_LAVA) //more light
+ if("basalt5", "basalt9")
+ B.set_light(1.4, 0.6, LIGHT_COLOR_LAVA) //barely anything!
+
+/turf/simulated/floor/plating/asteroid/basalt/gets_dug()
+ if(!dug)
+ set_light(0)
+ ..()
+
+///////Surface. The surface is warm, but survivable without a suit. Internals are required. The floors break to chasms, which drop you into the underground.
+
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ baseturf = /turf/simulated/floor/plating/lava/smooth/lava_land_surface
+
+/turf/simulated/floor/plating/asteroid/airless
+ temperature = TCMB
+ oxygen = 0
+ nitrogen = 0
+ turf_type = /turf/simulated/floor/plating/asteroid/airless
+
+#define SPAWN_MEGAFAUNA "MEGAFAUNA"
+
+GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/megafauna/dragon = 4, /mob/living/simple_animal/hostile/megafauna/colossus = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = 6))
+
+/turf/simulated/floor/plating/asteroid/airless/cave
+ var/length = 100
+ var/list/mob_spawn_list
+ var/list/megafauna_spawn_list
+ var/list/flora_spawn_list
+ var/sanity = 1
+ var/forward_cave_dir = 1
+ var/backward_cave_dir = 2
+ var/going_backwards = TRUE
+ var/has_data = FALSE
+ var/data_having_type = /turf/simulated/floor/plating/asteroid/airless/cave/has_data
+ turf_type = /turf/simulated/floor/plating/asteroid/airless
+
+/turf/simulated/floor/plating/asteroid/airless/cave/has_data //subtype for producing a tunnel with given data
+ has_data = TRUE
+
+/turf/simulated/floor/plating/asteroid/airless/cave/volcanic
+ mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /mob/living/simple_animal/hostile/spawner/lavaland/goliath = 3, \
+ /mob/living/simple_animal/hostile/asteroid/basilisk/watcher = 40, /mob/living/simple_animal/hostile/spawner/lavaland = 2, \
+ /mob/living/simple_animal/hostile/asteroid/hivelord/legion = 30, /mob/living/simple_animal/hostile/spawner/lavaland/legion = 3, \
+ SPAWN_MEGAFAUNA = 6, /mob/living/simple_animal/hostile/asteroid/goldgrub = 10)
+
+ data_having_type = /turf/simulated/floor/plating/asteroid/airless/cave/volcanic/has_data
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+
+/turf/simulated/floor/plating/asteroid/airless/cave/volcanic/has_data //subtype for producing a tunnel with given data
+ has_data = TRUE
+
+/turf/simulated/floor/plating/asteroid/airless/cave/New()
+ if (!mob_spawn_list)
+ mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goldgrub = 1, /mob/living/simple_animal/hostile/asteroid/goliath = 5, /mob/living/simple_animal/hostile/asteroid/basilisk = 4, /mob/living/simple_animal/hostile/asteroid/hivelord = 3)
+ if (!megafauna_spawn_list)
+ megafauna_spawn_list = GLOB.megafauna_spawn_list
+ if (!flora_spawn_list)
+ flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2)
+
+ if(!has_data)
+ produce_tunnel_from_data()
+ ..()
+
+/turf/simulated/floor/plating/asteroid/airless/cave/proc/get_cave_data(set_length, exclude_dir = -1)
+ // If set_length (arg1) isn't defined, get a random length; otherwise assign our length to the length arg.
+ if(!set_length)
+ length = rand(25, 50)
+ else
+ length = set_length
+
+ // Get our directiosn
+ forward_cave_dir = pick(alldirs - exclude_dir)
+ // Get the opposite direction of our facing direction
+ backward_cave_dir = angle2dir(dir2angle(forward_cave_dir) + 180)
+
+/turf/simulated/floor/plating/asteroid/airless/cave/proc/produce_tunnel_from_data(tunnel_length, excluded_dir = -1)
+ get_cave_data(tunnel_length, excluded_dir)
+ // Make our tunnels
+ make_tunnel(forward_cave_dir)
+ if(going_backwards)
+ make_tunnel(backward_cave_dir)
+ // Kill ourselves by replacing ourselves with a normal floor.
+ SpawnFloor(src)
+
+/turf/simulated/floor/plating/asteroid/airless/cave/proc/make_tunnel(dir)
+ var/turf/simulated/mineral/tunnel = src
+ var/next_angle = pick(45, -45)
+
+ for(var/i = 0; i < length; i++)
+ if(!sanity)
+ break
+
+ var/list/L = list(45)
+ if(IsOdd(dir2angle(dir))) // We're going at an angle and we want thick angled tunnels.
+ L += -45
+
+ // Expand the edges of our tunnel
+ for(var/edge_angle in L)
+ var/turf/simulated/mineral/edge = get_step(tunnel, angle2dir(dir2angle(dir) + edge_angle))
+ if(istype(edge))
+ SpawnFloor(edge)
+
+ if(!sanity)
+ break
+
+ // Move our tunnel forward
+ tunnel = get_step(tunnel, dir)
+
+ if(istype(tunnel))
+ // Small chance to have forks in our tunnel; otherwise dig our tunnel.
+ if(i > 3 && prob(20))
+ var/turf/simulated/floor/plating/asteroid/airless/cave/C = tunnel.ChangeTurf(data_having_type,FALSE,TRUE)
+ C.going_backwards = FALSE
+ C.produce_tunnel_from_data(rand(10, 15), dir)
+ else
+ SpawnFloor(tunnel)
+ else //if(!istype(tunnel, src.parent)) // We hit space/normal/wall, stop our tunnel.
+ break
+
+ // Chance to change our direction left or right.
+ if(i > 2 && prob(33))
+ // We can't go a full loop though
+ next_angle = -next_angle
+ setDir(angle2dir(dir2angle(dir) )+ next_angle)
+
+
+/turf/simulated/floor/plating/asteroid/airless/cave/proc/SpawnFloor(turf/T)
+ for(var/S in RANGE_TURFS(1, src))
+ var/turf/NT = S
+ if(!NT || isspaceturf(NT) || istype(NT.loc, /area/mine/explored) || istype(NT.loc, /area/lavaland/surface/outdoors/explored))
+ sanity = 0
+ break
+ if(!sanity)
+ return
+ SpawnFlora(T)
+
+ SpawnMonster(T)
+ T.ChangeTurf(turf_type,FALSE,FALSE,TRUE)
+
+/turf/simulated/floor/plating/asteroid/airless/cave/proc/SpawnMonster(turf/T)
+ if(prob(30))
+ if(istype(loc, /area/mine/explored) || istype(loc, /area/lavaland/surface/outdoors/explored))
+ return
+ var/randumb = pickweight(mob_spawn_list)
+ while(randumb == SPAWN_MEGAFAUNA)
+ var/maybe_boss = pickweight(megafauna_spawn_list)
+ if(megafauna_spawn_list[maybe_boss])
+ randumb = maybe_boss
+ if(ispath(maybe_boss, /mob/living/simple_animal/hostile/megafauna/bubblegum)) //there can be only one bubblegum, so don't waste spawns on it
+ megafauna_spawn_list.Remove(maybe_boss)
+
+ for(var/mob/living/simple_animal/hostile/H in urange(12,T)) //prevents mob clumps
+ if((ispath(randumb, /mob/living/simple_animal/hostile/megafauna) || ismegafauna(H)) && get_dist(src, H) <= 7)
+ return //if there's a megafauna within standard view don't spawn anything at all
+ if(ispath(randumb, /mob/living/simple_animal/hostile/asteroid) || istype(H, /mob/living/simple_animal/hostile/asteroid))
+ return //if the random is a standard mob, avoid spawning if there's another one within 12 tiles
+ if((ispath(randumb, /mob/living/simple_animal/hostile/spawner/lavaland) || istype(H, /mob/living/simple_animal/hostile/spawner/lavaland)) && get_dist(src, H) <= 2)
+ return //prevents tendrils spawning in each other's collapse range
+
+ new randumb(T)
+ return
+
+#undef SPAWN_MEGAFAUNA
+
+/turf/simulated/floor/plating/asteroid/airless/cave/proc/SpawnFlora(turf/T)
+ if(prob(12))
+ if(istype(loc, /area/mine/explored) || istype(loc, /area/lavaland/surface/outdoors/explored))
+ return
+ var/randumb = pickweight(flora_spawn_list)
+ for(var/obj/structure/flora/ash/F in range(4, T)) //Allows for growing patches, but not ridiculous stacks of flora
+ if(!istype(F, randumb))
+ return
+ new randumb(T)
+
+
+
+/turf/simulated/floor/plating/asteroid/snow
+ name = "snow"
+ desc = "Looks cold."
+ icon = 'icons/turf/snow.dmi'
+ baseturf = /turf/simulated/floor/plating/asteroid/snow
+ icon_state = "snow"
+ icon_plating = "snow"
+ temperature = 180
+ slowdown = 2
+ environment_type = "snow"
+ sand_type = /obj/item/stack/sheet/mineral/snow
+
+/turf/simulated/floor/plating/asteroid/snow/airless
+ temperature = TCMB
+ oxygen = 0
+ nitrogen = 0
+
+/turf/simulated/floor/plating/asteroid/snow/temperature
+ temperature = 255.37
+
+/turf/simulated/floor/plating/asteroid/snow/atmosphere
+ oxygen = 22
+ nitrogen = 82
+ temperature = 180
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor/chasm.dm b/code/game/turfs/simulated/floor/chasm.dm
new file mode 100644
index 00000000000..6a213400d04
--- /dev/null
+++ b/code/game/turfs/simulated/floor/chasm.dm
@@ -0,0 +1,179 @@
+/turf/simulated/floor/chasm
+ name = "chasm"
+ desc = "Watch your step."
+ baseturf = /turf/simulated/floor/chasm
+ smooth = SMOOTH_TRUE | SMOOTH_BORDER | SMOOTH_MORE
+ icon = 'icons/turf/floors/Chasms.dmi'
+ icon_state = "smooth"
+ canSmoothWith = list(/turf/simulated/floor/chasm)
+ density = TRUE //This will prevent hostile mobs from pathing into chasms, while the canpass override will still let it function like an open turf
+ var/static/list/falling_atoms = list() //Atoms currently falling into the chasm
+ var/static/list/forbidden_types = typecacheof(list(/obj/effect/portal, /obj/singularity, /obj/structure/stone_tile, /obj/item/projectile, /obj/effect/temp_visual, /obj/effect/collapse, /obj/effect/collapse))
+ var/drop_x = 1
+ var/drop_y = 1
+ var/drop_z = 1
+
+/turf/simulated/floor/chasm/Entered(atom/movable/AM)
+ ..()
+ START_PROCESSING(SSprocessing, src)
+ drop_stuff(AM)
+
+/turf/simulated/floor/chasm/process()
+ if(!drop_stuff())
+ STOP_PROCESSING(SSprocessing, src)
+
+/turf/simulated/floor/chasm/attackby(obj/item/C, mob/user, params, area/area_restriction)
+ ..()
+ if(istype(C, /obj/item/stack/rods))
+ var/obj/item/stack/rods/R = C
+ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ if(!L)
+ if(R.use(1))
+ to_chat(user, "You construct a lattice.")
+ playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
+ ReplaceWithLattice()
+ else
+ to_chat(user, "You need one rod to build a lattice.")
+ return
+ if(istype(C, /obj/item/stack/tile/plasteel))
+ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ if(L)
+ var/obj/item/stack/tile/plasteel/S = C
+ if(S.use(1))
+ qdel(L)
+ playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
+ to_chat(user, "You build a floor.")
+ ChangeTurf(/turf/simulated/floor/plating)
+ else
+ to_chat(user, "You need one floor tile to build a floor!")
+ else
+ to_chat(user, "The plating is going to need some support! Place metal rods first.")
+
+/turf/simulated/floor/chasm/proc/is_safe()
+ //if anything matching this typecache is found in the chasm, we don't drop things
+ var/static/list/chasm_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile))
+ var/list/found_safeties = typecache_filter_list(contents, chasm_safeties_typecache)
+ for(var/obj/structure/stone_tile/S in found_safeties)
+ if(S.fallen)
+ LAZYREMOVE(found_safeties, S)
+ return LAZYLEN(found_safeties)
+
+/turf/simulated/floor/chasm/proc/drop_stuff(AM)
+ . = 0
+ if(is_safe())
+ return FALSE
+ var/thing_to_check = src
+ if(AM)
+ thing_to_check = list(AM)
+ for(var/thing in thing_to_check)
+ if(droppable(thing))
+ . = 1
+ INVOKE_ASYNC(src, .proc/drop, thing)
+
+/turf/simulated/floor/chasm/proc/droppable(atom/movable/AM)
+ if(falling_atoms[AM])
+ return FALSE
+ if(!isliving(AM) && !isobj(AM))
+ return FALSE
+ if(!AM.simulated || is_type_in_typecache(AM, forbidden_types) || AM.throwing)
+ return FALSE
+ //Flies right over the chasm
+ if(isliving(AM))
+ var/mob/M = AM
+ if(M.flying)
+ return FALSE
+ if(ishuman(AM))
+ var/mob/living/carbon/human/H = AM
+ if(istype(H.belt, /obj/item/wormhole_jaunter))
+ var/obj/item/wormhole_jaunter/J = H.belt
+ //To freak out any bystanders
+ visible_message("[H] falls into [src]!")
+ J.chasm_react(H)
+ return FALSE
+ return TRUE
+
+/turf/simulated/floor/chasm/proc/drop(atom/movable/AM)
+ //Make sure the item is still there after our sleep
+ if(!AM || QDELETED(AM))
+ return
+ falling_atoms[AM] = TRUE
+ var/turf/T = locate(drop_x, drop_y, drop_z)
+ if(T)
+ AM.visible_message("[AM] falls into [src]!", "GAH! Ah... where are you?")
+ T.visible_message("[AM] falls from above!")
+ AM.forceMove(T)
+ if(isliving(AM))
+ var/mob/living/L = AM
+ L.Weaken(5)
+ L.adjustBruteLoss(30)
+ falling_atoms -= AM
+
+/turf/simulated/floor/chasm/straight_down/Initialize()
+ . = ..()
+ drop_x = x
+ drop_y = y
+ drop_z = z - 1
+ var/turf/T = locate(drop_x, drop_y, drop_z)
+ if(T)
+ T.visible_message("The ceiling gives way!")
+ playsound(T, 'sound/effects/break_stone.ogg', 50, 1)
+
+/turf/simulated/floor/chasm/straight_down/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ baseturf = /turf/simulated/floor/chasm/straight_down/lava_land_surface
+ light_range = 1.9 //slightly less range than lava
+ light_power = 0.65 //less bright, too
+ light_color = LIGHT_COLOR_LAVA //let's just say you're falling into lava, that makes sense right
+
+/turf/simulated/floor/chasm/straight_down/lava_land_surface/drop(atom/movable/AM)
+ //Make sure the item is still there after our sleep
+ if(!AM || QDELETED(AM))
+ return
+ falling_atoms[AM] = TRUE
+ AM.visible_message("[AM] falls into [src]!", "You stumble and stare into an abyss before you. It stares back, and you fall \
+ into the enveloping dark.")
+ if(isliving(AM))
+ var/mob/living/L = AM
+ L.notransform = TRUE
+ L.Stun(200)
+ L.resting = TRUE
+ var/oldtransform = AM.transform
+ var/oldcolor = AM.color
+ var/oldalpha = AM.alpha
+ animate(AM, transform = matrix() - matrix(), alpha = 0, color = rgb(0, 0, 0), time = 10)
+ for(var/i in 1 to 5)
+ //Make sure the item is still there after our sleep
+ if(!AM || QDELETED(AM))
+ return
+ AM.pixel_y--
+ sleep(2)
+
+ //Make sure the item is still there after our sleep
+ if(!AM || QDELETED(AM))
+ return
+
+ if(isrobot(AM))
+ var/mob/living/silicon/robot/S = AM
+ qdel(S.mmi)
+
+ falling_atoms -= AM
+
+ qdel(AM)
+
+ if(AM && !QDELETED(AM)) //It's indestructible
+ visible_message("[src] spits out the [AM]!")
+ AM.alpha = oldalpha
+ AM.color = oldcolor
+ AM.transform = oldtransform
+ AM.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1, 10),rand(1, 10))
+
+/turf/simulated/floor/chasm/straight_down/lava_land_surface/normal_air
+ oxygen = MOLES_O2STANDARD
+ nitrogen = MOLES_N2STANDARD
+ temperature = T20C
+
+/turf/simulated/floor/chasm/CanPass(atom/movable/mover, turf/target)
+ return 1
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index e9f8d96e70f..97065cd9711 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -78,31 +78,6 @@
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
make_plating()
-// NEEDS TO BE UPDATED
-/turf/simulated/floor/basalt //By your powers combined, I am captain planet
- name = "volcanic floor"
- icon_state = "basalt0"
- oxygen = 14
- nitrogen = 23
- temperature = 300
-
-/turf/simulated/floor/basalt/attackby(obj/item/W, mob/user, params)
- if(..())
- return
- if(istype(W, /obj/item/shovel))
- new /obj/item/stack/ore/glass/basalt(src, 2)
- user.visible_message("[user] digs up [src].", "You uproot [src].")
- playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
- make_plating()
-
-/turf/simulated/floor/basalt/New()
- ..()
- if(prob(15))
- icon_state = "basalt[rand(0, 12)]"
- switch(icon_state)
- if("basalt1", "basalt2", "basalt3")
- set_light(1, 1)
-
/turf/simulated/floor/carpet
name = "carpet"
icon = 'icons/turf/floors/carpet.dmi'
diff --git a/code/game/turfs/simulated/floor/indestructible.dm b/code/game/turfs/simulated/floor/indestructible.dm
new file mode 100644
index 00000000000..6c1679776e6
--- /dev/null
+++ b/code/game/turfs/simulated/floor/indestructible.dm
@@ -0,0 +1,85 @@
+/turf/simulated/floor/indestructible
+ unacidable = TRUE
+
+/turf/simulated/floor/indestructible/ex_act(severity)
+ return
+
+/turf/simulated/floor/indestructible/blob_act()
+ return
+
+/turf/simulated/floor/indestructible/singularity_act()
+ return
+
+/turf/simulated/floor/indestructible/singularity_pull(S, current_size)
+ return
+
+/turf/simulated/floor/indestructible/narsie_act()
+ return
+
+/turf/simulated/floor/indestructible/ratvar_act(force, ignore_mobs)
+ return
+
+/turf/simulated/floor/indestructible/burn_down()
+ return
+
+/turf/simulated/floor/indestructible/attackby(obj/item/I, mob/user, params)
+ return
+
+/turf/simulated/floor/indestructible/attack_hand(mob/user)
+ return
+
+/turf/simulated/floor/indestructible/attack_hulk(mob/user, does_attack_animation = FALSE)
+ return
+
+/turf/simulated/floor/indestructible/attack_animal(mob/living/simple_animal/M)
+ return
+
+/turf/simulated/floor/indestructible/mech_melee_attack(obj/mecha/M)
+ return
+
+/turf/simulated/floor/indestructible/necropolis
+ name = "necropolis floor"
+ desc = "It's regarding you suspiciously."
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "necro1"
+ baseturf = /turf/simulated/floor/indestructible/necropolis
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+
+/turf/simulated/floor/indestructible/necropolis/Initialize()
+ . = ..()
+ if(prob(12))
+ icon_state = "necro[rand(2,3)]"
+
+/turf/simulated/floor/indestructible/necropolis/air
+ oxygen = 0
+ nitrogen = 0
+ temperature = T20C
+
+/turf/simulated/floor/indestructible/boss //you put stone tiles on this and use it as a base
+ name = "necropolis floor"
+ icon = 'icons/turf/floors/boss_floors.dmi'
+ icon_state = "boss"
+ baseturf = /turf/simulated/floor/indestructible/boss
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+
+/turf/simulated/floor/indestructible/boss/air
+ oxygen = MOLES_O2STANDARD
+ nitrogen = MOLES_N2STANDARD
+ temperature = T20C
+
+/turf/simulated/floor/indestructible/hierophant
+ icon_state = "hierophant1"
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ desc = "A floor with a square pattern. It's faintly cool to the touch."
+
+/turf/simulated/floor/indestructible/hierophant/two
+ icon_state = "hierophant2"
diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm
new file mode 100644
index 00000000000..0882bb18766
--- /dev/null
+++ b/code/game/turfs/simulated/floor/lava.dm
@@ -0,0 +1,125 @@
+/turf/simulated/floor/plating/lava
+ name = "lava"
+ icon_state = "lava"
+ gender = PLURAL //"That's some lava."
+ baseturf = /turf/simulated/floor/plating/lava //lava all the way down
+ slowdown = 2
+ light_range = 2
+ light_power = 0.75
+ light_color = LIGHT_COLOR_LAVA
+
+/turf/simulated/floor/plating/lava/New()
+ ..()
+
+/turf/simulated/floor/plating/lava/ex_act()
+ return
+
+/turf/simulated/floor/plating/lava/airless
+ temperature = TCMB
+
+/turf/simulated/floor/plating/lava/Entered(atom/movable/AM)
+ if(burn_stuff(AM))
+ START_PROCESSING(SSprocessing, src)
+
+/turf/simulated/floor/plating/lava/hitby(atom/movable/AM)
+ if(burn_stuff(AM))
+ START_PROCESSING(SSprocessing, src)
+
+/turf/simulated/floor/plating/lava/process()
+ if(!burn_stuff())
+ STOP_PROCESSING(SSprocessing, src)
+
+/turf/simulated/floor/plating/lava/singularity_act()
+ return
+
+/turf/simulated/floor/plating/lava/singularity_pull(S, current_size)
+ return
+
+/turf/simulated/floor/plating/lava/make_plating()
+ return
+
+/turf/simulated/floor/plating/lava/remove_plating()
+ return
+
+/turf/simulated/floor/plating/lava/proc/is_safe()
+ var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile))
+ var/list/found_safeties = typecache_filter_list(contents, lava_safeties_typecache)
+ for(var/obj/structure/stone_tile/S in found_safeties)
+ if(S.fallen)
+ LAZYREMOVE(found_safeties, S)
+ return LAZYLEN(found_safeties)
+
+/turf/simulated/floor/plating/lava/proc/burn_stuff(AM)
+ . = 0
+
+ if(is_safe())
+ return FALSE
+
+ var/thing_to_check = src
+ if(AM)
+ thing_to_check = list(AM)
+ for(var/thing in thing_to_check)
+ if(isobj(thing))
+ var/obj/O = thing
+ if(!O.simulated)
+ continue
+ if((O.resistance_flags & (LAVA_PROOF|INDESTRUCTIBLE)) || O.throwing)
+ continue
+ . = 1
+ if((O.resistance_flags & (ON_FIRE)))
+ continue
+ if(!(O.resistance_flags & FLAMMABLE))
+ O.resistance_flags |= FLAMMABLE //Even fireproof things burn up in lava
+ if(O.resistance_flags & FIRE_PROOF)
+ O.resistance_flags &= ~FIRE_PROOF
+ O.fire_act(10000, 1000)
+
+ else if(isliving(thing))
+ . = 1
+ var/mob/living/L = thing
+ if(L.flying)
+ continue //YOU'RE FLYING OVER IT
+ if("lava" in L.weather_immunities)
+ continue
+ if(L.buckled)
+ if(isobj(L.buckled))
+ var/obj/O = L.buckled
+ if(O.resistance_flags & LAVA_PROOF)
+ continue
+ if(isliving(L.buckled)) //Goliath riding
+ var/mob/living/live = L.buckled
+ if("lava" in live.weather_immunities)
+ continue
+
+ L.adjustFireLoss(20)
+ if(L) //mobs turning into object corpses could get deleted here.
+ L.adjust_fire_stacks(20)
+ L.IgniteMob()
+
+
+/turf/simulated/floor/plating/lava/attackby(obj/item/C, mob/user, params) //Lava isn't a good foundation to build on
+ return
+
+/turf/simulated/floor/plating/lava/break_tile()
+ return
+
+/turf/simulated/floor/plating/lava/burn_tile()
+ return
+
+/turf/simulated/floor/plating/lava/smooth
+ name = "lava"
+ baseturf = /turf/simulated/floor/plating/lava/smooth
+ icon = 'icons/turf/floors/lava.dmi'
+ icon_state = "unsmooth"
+ smooth = SMOOTH_MORE | SMOOTH_BORDER
+ canSmoothWith = list(/turf/simulated/floor/plating/lava/smooth)
+
+/turf/simulated/floor/plating/lava/smooth/lava_land_surface
+ temperature = 300
+ oxygen = 14
+ nitrogen = 23
+ planetary_atmos = TRUE
+ baseturf = /turf/simulated/floor/chasm/straight_down/lava_land_surface
+
+/turf/simulated/floor/plating/lava/smooth/airless
+ temperature = TCMB
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor/mineral.dm b/code/game/turfs/simulated/floor/mineral.dm
index d201a38d697..a801fd450c5 100644
--- a/code/game/turfs/simulated/floor/mineral.dm
+++ b/code/game/turfs/simulated/floor/mineral.dm
@@ -80,9 +80,19 @@
//TITANIUM (shuttle)
+/turf/simulated/floor/mineral/titanium
+ name = "shuttle floor"
+ icon_state = "titanium"
+ floor_tile = /obj/item/stack/tile/mineral/titanium
+ broken_states = list("titanium_dam1","titanium_dam2","titanium_dam3","titanium_dam4","titanium_dam5")
+
+/turf/simulated/floor/mineral/titanium/airless
+ oxygen = 0.01
+ nitrogen = 0.01
+ temperature = TCMB
+
/turf/simulated/floor/mineral/titanium/blue
- icon_state = "shuttlefloor"
- icons = list("shuttlefloor","shuttlefloor_dam")
+ icon_state = "titanium_blue"
/turf/simulated/floor/mineral/titanium/blue/airless
oxygen = 0.01
@@ -90,29 +100,16 @@
temperature = TCMB
/turf/simulated/floor/mineral/titanium/yellow
- icon_state = "shuttlefloor2"
- icons = list("shuttlefloor2","shuttlefloor2_dam")
+ icon_state = "titanium_yellow"
/turf/simulated/floor/mineral/titanium/yellow/airless
oxygen = 0.01
nitrogen = 0.01
temperature = TCMB
-/turf/simulated/floor/mineral/titanium
- name = "shuttle floor"
- icon_state = "shuttlefloor3"
- floor_tile = /obj/item/stack/tile/mineral/titanium
- icons = list("shuttlefloor3","shuttlefloor3_dam")
-
-/turf/simulated/floor/mineral/titanium/airless
- oxygen = 0.01
- nitrogen = 0.01
- temperature = TCMB
-
/turf/simulated/floor/mineral/titanium/purple
- icon_state = "shuttlefloor5"
+ icon_state = "titanium_purple"
floor_tile = /obj/item/stack/tile/mineral/titanium/purple
- icons = list("shuttlefloor5","shuttlefloor5_dam")
/turf/simulated/floor/mineral/titanium/purple/airless
oxygen = 0.01
@@ -122,16 +119,19 @@
//PLASTITANIUM (syndieshuttle)
/turf/simulated/floor/mineral/plastitanium
name = "shuttle floor"
- icon_state = "shuttlefloor4"
+ icon_state = "plastitanium"
floor_tile = /obj/item/stack/tile/mineral/plastitanium
- icons = list("shuttlefloor4","shuttlefloor4_dam")
+ broken_states = list("plastitanium_dam1","plastitanium_dam2","plastitanium_dam3","plastitanium_dam4","plastitanium_dam5")
-/turf/simulated/floor/mineral/plastitanium/airless
+/turf/simulated/floor/mineral/plastitanium/red
+ icon_state = "plastitanium_red"
+
+/turf/simulated/floor/mineral/plastitanium/red/airless
oxygen = 0.01
nitrogen = 0.01
temperature = TCMB
-/turf/simulated/floor/mineral/plastitanium/brig
+/turf/simulated/floor/mineral/plastitanium/red/brig
name = "brig floor"
//BANANIUM
diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm
index 6cfea0cb8f6..5c8f2022189 100644
--- a/code/game/turfs/simulated/floor/misc_floor.dm
+++ b/code/game/turfs/simulated/floor/misc_floor.dm
@@ -35,10 +35,17 @@
..()
name = "floor"
+/turf/simulated/floor/redgrid
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "rcircuit"
+
/turf/simulated/floor/beach
name = "beach"
icon = 'icons/misc/beach.dmi'
+/turf/simulated/floor/beach/pry_tile(obj/item/C, mob/user, silent = FALSE)
+ return
+
/turf/simulated/floor/beach/sand
name = "sand"
icon_state = "sand"
@@ -48,19 +55,26 @@
icon = 'icons/misc/beach2.dmi'
icon_state = "sandwater"
+/turf/simulated/floor/beach/coastline_t
+ name = "coastline"
+ desc = "Tide's high tonight. Charge your batons."
+ icon_state = "sandwater_t"
+
+/turf/simulated/floor/beach/coastline_b
+ name = "coastline"
+ icon_state = "sandwater_b"
+
/turf/simulated/floor/beach/water // TODO - Refactor water so they share the same parent type - Or alternatively component something like that
name = "water"
icon_state = "water"
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/obj/machinery/poolcontroller/linkedcontroller = null
-/turf/simulated/floor/beach/water/pry_tile(obj/item/C, mob/user, silent = FALSE)
- return //cannot pry off tiles of water
-
-
/turf/simulated/floor/beach/water/New()
..()
- overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1)
+ var/image/overlay_image = image('icons/misc/beach.dmi', icon_state = "water5", layer = ABOVE_MOB_LAYER)
+ overlay_image.plane = GAME_PLANE
+ overlays += overlay_image
/turf/simulated/floor/beach/water/Entered(atom/movable/AM, atom/OldLoc)
. = ..()
@@ -97,18 +111,35 @@
/turf/simulated/floor/clockwork
name = "clockwork floor"
desc = "Tightly-pressed brass tiles. They emit minute vibration."
- icon_state = "clockwork_floor"
+ icon_state = "plating"
+ baseturf = /turf/simulated/floor/clockwork
+ var/dropped_brass
+ var/uses_overlay = TRUE
+ var/obj/effect/clockwork/overlay/floor/realappearence
-/turf/simulated/floor/clockwork/New()
- ..()
- new /obj/effect/temp_visual/ratvar/floor(src)
- new /obj/effect/temp_visual/ratvar/beam(src)
+/turf/simulated/floor/clockwork/Initialize(mapload)
+ . = ..()
+ if(uses_overlay)
+ new /obj/effect/temp_visual/ratvar/floor(src)
+ new /obj/effect/temp_visual/ratvar/beam(src)
+ realappearence = new /obj/effect/clockwork/overlay/floor(src)
+ realappearence.linked = src
+
+/turf/simulated/floor/clockwork/Destroy()
+ if(uses_overlay && realappearence)
+ QDEL_NULL(realappearence)
+ return ..()
+
+/turf/simulated/floor/clockwork/ReplaceWithLattice()
+ . = ..()
+ for(var/obj/structure/lattice/L in src)
+ L.ratvar_act()
/turf/simulated/floor/clockwork/attackby(obj/item/I, mob/living/user, params)
if(iscrowbar(I))
user.visible_message("[user] begins slowly prying up [src]...", "You begin painstakingly prying up [src]...")
playsound(src, I.usesound, 20, 1)
- if(!do_after(user, 70*I.toolspeed, target = src))
+ if(!do_after(user, 70 * I.toolspeed, target = src))
return 0
user.visible_message("[user] pries up [src]!", "You pry up [src]!")
playsound(src, I.usesound, 80, 1)
@@ -117,7 +148,11 @@
return ..()
/turf/simulated/floor/clockwork/make_plating()
- new /obj/item/stack/tile/brass(src)
+ if(!dropped_brass)
+ new /obj/item/stack/tile/brass(src)
+ dropped_brass = TRUE
+ if(baseturf == type)
+ return
return ..()
/turf/simulated/floor/clockwork/narsie_act()
@@ -126,3 +161,12 @@
var/previouscolor = color
color = "#960000"
animate(src, color = previouscolor, time = 8)
+ addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
+
+/turf/simulated/floor/clockwork/reebe
+ name = "cogplate"
+ desc = "Warm brass plating. You can feel it gently vibrating, as if machinery is on the other side."
+ icon_state = "reebe"
+ baseturf = /turf/simulated/floor/clockwork/reebe
+ uses_overlay = FALSE
+ planetary_atmos = TRUE
diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm
index cba841ce823..d36396aaa5f 100644
--- a/code/game/turfs/simulated/floor/plasteel_floor.dm
+++ b/code/game/turfs/simulated/floor/plasteel_floor.dm
@@ -30,4 +30,30 @@
name = "Commemorative Plaque"
desc = "\"This is a plaque in honour of our comrades on the G4407 Stations. Hopefully TG4407 model can live up to your fame and fortune.\" Scratched in beneath that is a crude image of a meteor and a spaceman. The spaceman is laughing. The meteor is exploding."
-//TODO: Make subtypes for all normal turf icons
\ No newline at end of file
+//TODO: Make subtypes for all normal turf icons
+/turf/simulated/floor/plasteel/white
+ icon_state = "white"
+/turf/simulated/floor/plasteel/white/side
+ icon_state = "whitehall"
+/turf/simulated/floor/plasteel/white/corner
+ icon_state = "whitecorner"
+
+/turf/simulated/floor/plasteel/dark
+ icon_state = "darkfull"
+
+/turf/simulated/floor/plasteel/freezer
+ icon_state = "freezerfloor"
+
+/turf/simulated/floor/plasteel/stairs
+ icon_state = "stairs"
+/turf/simulated/floor/plasteel/stairs/left
+ icon_state = "stairs-l"
+/turf/simulated/floor/plasteel/stairs/medium
+ icon_state = "stairs-m"
+/turf/simulated/floor/plasteel/stairs/right
+ icon_state = "stairs-r"
+/turf/simulated/floor/plasteel/stairs/old
+ icon_state = "stairs-old"
+
+/turf/simulated/floor/plasteel/grimy
+ icon_state = "grimy"
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 22a74ceed46..2ef4602d268 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -2,7 +2,7 @@
name = "plating"
icon_state = "plating"
icon = 'icons/turf/floors/plating.dmi'
- intact = 0
+ intact = FALSE
floor_tile = null
broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5")
burnt_states = list("floorscorched1", "floorscorched2")
@@ -17,6 +17,14 @@
icon_plating = icon_state
update_icon()
+/turf/simulated/floor/plating/damaged/New()
+ ..()
+ break_tile()
+
+/turf/simulated/floor/plating/burnt/New()
+ ..()
+ burn_tile()
+
/turf/simulated/floor/plating/update_icon()
if(!..())
return
@@ -25,16 +33,16 @@
/turf/simulated/floor/plating/attackby(obj/item/C, mob/user, params)
if(..())
- return 1
+ return TRUE
if(istype(C, /obj/item/stack/rods))
if(broken || burnt)
to_chat(user, "Repair the plating first!")
- return 1
+ return TRUE
var/obj/item/stack/rods/R = C
if(R.get_amount() < 2)
to_chat(user, "You need two rods to make a reinforced floor!")
- return 1
+ return TRUE
else
to_chat(user, "You begin reinforcing the floor...")
if(do_after(user, 30 * C.toolspeed, target = src))
@@ -43,7 +51,7 @@
playsound(src, C.usesound, 80, 1)
R.use(2)
to_chat(user, "You reinforce the floor.")
- return 1
+ return TRUE
else if(istype(C, /obj/item/stack/tile))
if(!broken && !burnt)
@@ -54,20 +62,39 @@
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
else
to_chat(user, "This section is too damaged to support a tile! Use a welder to fix the damage.")
- return 1
+ return TRUE
- else if(istype(C, /obj/item/weldingtool))
+ else if(iswelder(C))
var/obj/item/weldingtool/welder = C
- if( welder.isOn() && (broken || burnt) )
- if(welder.remove_fuel(0,user))
+ if(welder.isOn())
+ if(!welder.remove_fuel(0, user))
+ to_chat(user, "You need more welding fuel to complete this task.")
+ return TRUE
+
+ if(broken || burnt)
to_chat(user, "You fix some dents on the broken plating.")
playsound(src, welder.usesound, 80, 1)
overlays -= current_overlay
current_overlay = null
- burnt = 0
- broken = 0
+ burnt = FALSE
+ broken = FALSE
update_icon()
- return 1
+ else
+ to_chat(user, "You start removing [src].")
+ playsound(src, welder.usesound, 100, 1)
+ if(do_after(user, 50 * welder.toolspeed, target = src) && welder && welder.isOn())
+ to_chat(user, "You remove [src].")
+ new /obj/item/stack/tile/plasteel(get_turf(src))
+ remove_plating(user)
+ return TRUE
+
+ return TRUE
+
+/turf/simulated/floor/plating/proc/remove_plating(mob/user)
+ if(baseturf == /turf/space)
+ ReplaceWithLattice()
+ else
+ TerraformTurf(baseturf)
/turf/simulated/floor/plating/airless
icon_state = "plating"
@@ -87,6 +114,7 @@
var/insulated
heat_capacity = 325000
floor_tile = /obj/item/stack/rods
+ unacidable = TRUE
/turf/simulated/floor/engine/break_tile()
return //unbreakable
@@ -94,11 +122,17 @@
/turf/simulated/floor/engine/burn_tile()
return //unburnable
-/turf/simulated/floor/engine/make_plating(var/force = 0)
+/turf/simulated/floor/engine/make_plating(force = 0)
if(force)
..()
return //unplateable
+/turf/simulated/floor/engine/attack_hand(mob/user as mob)
+ user.Move_Pulled(src)
+
+/turf/simulated/floor/engine/pry_tile(obj/item/C, mob/user, silent = FALSE)
+ return
+
/turf/simulated/floor/engine/attackby(obj/item/C as obj, mob/user as mob, params)
if(!C || !user)
return
@@ -111,6 +145,7 @@
new /obj/item/stack/rods(src, 2)
ChangeTurf(/turf/simulated/floor/plating)
return
+
if(istype(C, /obj/item/stack/sheet/plasteel) && !insulated) //Insulating the floor
to_chat(user, "You begin insulating [src]...")
if(do_after(user, 40, target = src) && !insulated) //You finish insulating the insulated insulated insulated insulated insulated insulated insulated insulated vacuum floor
@@ -122,30 +157,26 @@
name = "insulated " + name
return
-/turf/simulated/floor/engine/ex_act(severity,target)
+/turf/simulated/floor/engine/ex_act(severity)
switch(severity)
if(1)
- if(prob(80))
- ReplaceWithLattice()
- else if(prob(50))
- qdel(src)
- else
- if(builtin_tile)
- builtin_tile.loc = src
- builtin_tile = null
- make_plating(1)
+ ChangeTurf(baseturf)
if(2)
if(prob(50))
- make_plating(1)
+ ChangeTurf(baseturf)
+/turf/simulated/floor/engine/blob_act()
+ if(prob(25))
+ ChangeTurf(baseturf)
+
/turf/simulated/floor/engine/cult
name = "engraved floor"
icon_state = "cult"
/turf/simulated/floor/engine/cult/New()
..()
- if(ticker.mode)//only do this if the round is going..otherwise..fucking asteroid..
- icon_state = ticker.cultdat.cult_floor_icon_state
+ if(SSticker.mode)//only do this if the round is going..otherwise..fucking asteroid..
+ icon_state = SSticker.cultdat.cult_floor_icon_state
/turf/simulated/floor/engine/cult/narsie_act()
return
@@ -204,6 +235,9 @@
..()
icon_state = "ironsand[rand(1,15)]"
+/turf/simulated/floor/plating/ironsand/remove_plating()
+ return
+
/turf/simulated/floor/plating/snow
name = "snow"
icon = 'icons/turf/snow.dmi'
@@ -212,6 +246,9 @@
/turf/simulated/floor/plating/snow/ex_act(severity)
return
+/turf/simulated/floor/plating/snow/remove_plating()
+ return
+
/turf/simulated/floor/snow
name = "snow"
icon = 'icons/turf/snow.dmi'
@@ -220,59 +257,8 @@
/turf/simulated/floor/snow/ex_act(severity)
return
-
-// CATWALKS
-// Space and plating, all in one buggy fucking turf!
-// These are *so* fucking bad it makes me want to kill myself
-/turf/simulated/floor/plating/airless/catwalk
- icon = 'icons/turf/catwalks.dmi'
- icon_state = "catwalk0"
- name = "catwalk"
- desc = "Cats really don't like these things."
-
- temperature = TCMB
- thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
- heat_capacity = 700000
-
-/turf/simulated/floor/plating/airless/catwalk/New()
- ..()
- set_light(4) //starlight
- name = "catwalk"
- update_icon(1)
-
-/turf/simulated/floor/plating/airless/catwalk/update_icon(var/propogate=1)
- underlays.Cut()
- underlays += new /icon('icons/turf/space.dmi',SPACE_ICON_STATE)
-
- var/dirs = 0
- for(var/direction in cardinal)
- var/turf/T = get_step(src,direction)
- if(istype(T, /turf/simulated/floor/plating/airless/catwalk))
- var/turf/simulated/floor/plating/airless/catwalk/C=T
- dirs |= direction
- if(propogate)
- C.update_icon(0)
- icon_state="catwalk[dirs]"
-
-/turf/simulated/floor/plating/airless/catwalk/attackby(obj/item/C, mob/user, params)
- if(istype(C, /obj/item/stack/rods))
- return 1
- else if(istype(C, /obj/item/stack/tile))
- return 1
-
- if(..())
- return 1
-
- if(!broken && isscrewdriver(C))
- to_chat(user, "You unscrew the catwalk's rods.")
- new /obj/item/stack/rods(src, 1)
- ReplaceWithLattice()
- for(var/direction in cardinal)
- var/turf/T = get_step(src,direction)
- if(istype(T, /turf/simulated/floor/plating/airless/catwalk))
- var/turf/simulated/floor/plating/airless/catwalk/CW=T
- CW.update_icon(0)
- playsound(src, C.usesound, 80, 1)
+/turf/simulated/floor/snow/pry_tile(obj/item/C, mob/user, silent = FALSE)
+ return
/turf/simulated/floor/plating/metalfoam
name = "foamed metal plating"
@@ -292,7 +278,8 @@
/turf/simulated/floor/plating/metalfoam/attackby(var/obj/item/C, mob/user, params)
if(..())
- return 1
+ return TRUE
+
if(istype(C) && C.force)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
@@ -322,7 +309,7 @@
smash()
/turf/simulated/floor/plating/metalfoam/proc/smash()
- ChangeTurf(/turf/space)
+ ChangeTurf(baseturf)
/turf/simulated/floor/plating/abductor
name = "alien floor"
diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm
new file mode 100644
index 00000000000..119f0b000d9
--- /dev/null
+++ b/code/game/turfs/simulated/minerals.dm
@@ -0,0 +1,515 @@
+/**********************Mineral deposits**************************/
+
+/turf/simulated/mineral //wall piece
+ name = "rock"
+ icon = 'icons/turf/mining.dmi'
+ icon_state = "rock"
+ var/smooth_icon = 'icons/turf/smoothrocks.dmi'
+ smooth = SMOOTH_MORE | SMOOTH_BORDER
+ canSmoothWith
+ baseturf = /turf/simulated/floor/plating/asteroid/airless
+ temperature = 2.7
+ opacity = 1
+ density = 1
+ blocks_air = 1
+ layer = EDGED_TURF_LAYER
+ temperature = TCMB
+ var/environment_type = "asteroid"
+ var/turf/simulated/floor/plating/turf_type = /turf/simulated/floor/plating/asteroid/airless
+ var/mineralType = null
+ var/mineralAmt = 3
+ var/spread = 0 //will the seam spread?
+ var/spreadChance = 0 //the percentual chance of an ore spreading to the neighbouring tiles
+ var/last_act = 0
+ var/scan_state = null //Holder for the image we display when we're pinged by a mining scanner
+ var/defer_change = FALSE
+
+/turf/simulated/mineral/New()
+ if (!canSmoothWith)
+ canSmoothWith = list(/turf/simulated/mineral)
+ pixel_y = -4
+ pixel_x = -4
+ icon = smooth_icon
+
+ ..()
+ GLOB.mineral_turfs += src
+
+ if (mineralType && mineralAmt && spread && spreadChance)
+ for(var/dir in cardinal)
+ if(prob(spreadChance))
+ var/turf/T = get_step(src, dir)
+ if(istype(T, /turf/simulated/mineral/random))
+ Spread(T)
+
+/turf/simulated/mineral/Spread(turf/T)
+ T.ChangeTurf(type)
+
+/turf/simulated/mineral/shuttleRotate(rotation)
+ setDir(angle2dir(rotation + dir2angle(dir)))
+ queue_smooth(src)
+
+/turf/simulated/mineral/attackby(var/obj/item/pickaxe/P as obj, mob/user as mob, params)
+ if(!user.IsAdvancedToolUser())
+ to_chat(usr, "You don't have the dexterity to do this!")
+ return
+
+ if(istype(P, /obj/item/pickaxe))
+ var/turf/T = user.loc
+ if(!isturf(T))
+ return
+
+ if(last_act + (40 * P.toolspeed) > world.time) // Prevents message spam
+ return
+
+ last_act = world.time
+ to_chat(user, "You start picking...")
+ P.playDigSound()
+
+ if(do_after(user, 40 * P.toolspeed, target = src))
+ if(istype(src, /turf/simulated/mineral)) //sanity check against turf being deleted during digspeed delay
+ to_chat(user, "You finish cutting into the rock.")
+ P.update_icon()
+ gets_drilled(user)
+ feedback_add_details("pick_used_mining","[P.name]")
+ else
+ return attack_hand(user)
+
+/turf/simulated/mineral/proc/gets_drilled()
+ if(mineralType && (mineralAmt > 0) && (mineralAmt < 11))
+ var/i
+ for(i=0; i < mineralAmt; i++)
+ new mineralType(src)
+ feedback_add_details("ore_mined","[mineralType]|[mineralAmt]")
+ ChangeTurf(turf_type, defer_change)
+ addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE)
+ playsound(src, 'sound/effects/break_stone.ogg', 50, 1) //beautiful destruction
+
+ if(rand(1, 750) == 1)
+ visible_message("An old dusty crate was buried within!")
+ new /obj/structure/closet/crate/secure/loot(src)
+
+ return
+
+/turf/simulated/mineral/attack_animal(mob/living/simple_animal/user as mob)
+ if((user.environment_smash & ENVIRONMENT_SMASH_WALLS) || (user.environment_smash & ENVIRONMENT_SMASH_RWALLS))
+ gets_drilled()
+ ..()
+
+/turf/simulated/mineral/attack_alien(var/mob/living/carbon/alien/M)
+ to_chat(M, "You start digging into the rock...")
+ playsound(src, 'sound/effects/break_stone.ogg', 50, 1)
+ if(do_after(M, 40, target = src))
+ to_chat(M, "You tunnel into the rock.")
+ gets_drilled()
+
+/turf/simulated/mineral/Bumped(AM as mob|obj)
+ . = ..()
+ if(ishuman(AM))
+ var/mob/living/carbon/human/H = AM
+ if((istype(H.l_hand,/obj/item/pickaxe)) && (!H.hand))
+ attackby(H.l_hand,H)
+ else if((istype(H.r_hand,/obj/item/pickaxe)) && H.hand)
+ attackby(H.r_hand,H)
+ return
+
+ else if(isrobot(AM))
+ var/mob/living/silicon/robot/R = AM
+ if(istype(R.module_active,/obj/item/pickaxe))
+ attackby(R.module_active,R)
+
+ else if(ismecha(AM))
+ var/obj/mecha/M = AM
+ if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/drill))
+ M.selected.action(src)
+
+/turf/simulated/mineral/ex_act(severity, target)
+ ..()
+ switch(severity)
+ if(3)
+ if (prob(75))
+ gets_drilled(null, 1)
+ if(2)
+ if (prob(90))
+ gets_drilled(null, 1)
+ if(1)
+ gets_drilled(null, 1)
+
+/turf/simulated/mineral/random
+ var/mineralSpawnChanceList
+ var/mineralChance = 13
+ var/display_icon_state = "rock"
+
+/turf/simulated/mineral/random/New()
+ if (!mineralSpawnChanceList)
+ mineralSpawnChanceList = list(
+ /turf/simulated/mineral/uranium = 5, /turf/simulated/mineral/diamond = 1, /turf/simulated/mineral/gold = 10,
+ /turf/simulated/mineral/silver = 12, /turf/simulated/mineral/plasma = 20, /turf/simulated/mineral/iron = 40, /turf/simulated/mineral/titanium = 11,
+ /turf/simulated/mineral/gibtonite = 4, /turf/simulated/floor/plating/asteroid/airless/cave = 2, /turf/simulated/mineral/bscrystal = 1)
+ if (display_icon_state)
+ icon_state = display_icon_state
+ ..()
+ if (prob(mineralChance))
+ var/path = pickweight(mineralSpawnChanceList)
+ var/turf/T = ChangeTurf(path,FALSE,TRUE)
+
+ if(T && ismineralturf(T))
+ var/turf/simulated/mineral/M = T
+ M.mineralAmt = rand(1, 5)
+ M.environment_type = environment_type
+ M.turf_type = turf_type
+ M.baseturf = baseturf
+ src = M
+ M.levelupdate()
+
+/turf/simulated/mineral/random/high_chance
+ icon_state = "rock_highchance"
+ mineralChance = 25
+ mineralSpawnChanceList = list(
+ /turf/simulated/mineral/uranium = 35, /turf/simulated/mineral/diamond = 30, /turf/simulated/mineral/gold = 45, /turf/simulated/mineral/titanium = 45,
+ /turf/simulated/mineral/silver = 50, /turf/simulated/mineral/plasma = 50, /turf/simulated/mineral/bscrystal = 20)
+
+/turf/simulated/mineral/random/high_chance/clown
+ mineralChance = 40
+ mineralSpawnChanceList = list(
+ /turf/simulated/mineral/uranium = 35, /turf/simulated/mineral/diamond = 2, /turf/simulated/mineral/gold = 5, /turf/simulated/mineral/silver = 5,
+ /turf/simulated/mineral/iron = 30, /turf/simulated/mineral/clown = 15, /turf/simulated/mineral/mime = 15, /turf/simulated/mineral/bscrystal = 10)
+
+/turf/simulated/mineral/random/high_chance/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/lava/smooth/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+ mineralSpawnChanceList = list(
+ /turf/simulated/mineral/uranium/volcanic = 35, /turf/simulated/mineral/diamond/volcanic = 30, /turf/simulated/mineral/gold/volcanic = 45, /turf/simulated/mineral/titanium/volcanic = 45,
+ /turf/simulated/mineral/silver/volcanic = 50, /turf/simulated/mineral/plasma/volcanic = 50, /turf/simulated/mineral/bscrystal/volcanic = 20)
+
+/turf/simulated/mineral/random/low_chance
+ icon_state = "rock_lowchance"
+ mineralChance = 6
+ mineralSpawnChanceList = list(
+ /turf/simulated/mineral/uranium = 2, /turf/simulated/mineral/diamond = 1, /turf/simulated/mineral/gold = 4, /turf/simulated/mineral/titanium = 4,
+ /turf/simulated/mineral/silver = 6, /turf/simulated/mineral/plasma = 15, /turf/simulated/mineral/iron = 40,
+ /turf/simulated/mineral/gibtonite = 2, /turf/simulated/mineral/bscrystal = 1)
+
+/turf/simulated/mineral/random/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/lava/smooth/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+ mineralChance = 10
+ mineralSpawnChanceList = list(
+ /turf/simulated/mineral/uranium/volcanic = 5, /turf/simulated/mineral/diamond/volcanic = 1, /turf/simulated/mineral/gold/volcanic = 10, /turf/simulated/mineral/titanium/volcanic = 11,
+ /turf/simulated/mineral/silver/volcanic = 12, /turf/simulated/mineral/plasma/volcanic = 20, /turf/simulated/mineral/iron/volcanic = 40,
+ /turf/simulated/mineral/gibtonite/volcanic = 4, /turf/simulated/floor/plating/asteroid/airless/cave/volcanic = 1, /turf/simulated/mineral/bscrystal/volcanic = 1)
+
+/turf/simulated/mineral/random/labormineral
+ mineralSpawnChanceList = list(
+ /turf/simulated/mineral/uranium = 2, /turf/simulated/mineral/diamond = 1, /turf/simulated/mineral/gold = 3, /turf/simulated/mineral/titanium = 4,
+ /turf/simulated/mineral/silver = 6, /turf/simulated/mineral/plasma = 15, /turf/simulated/mineral/iron = 80,
+ /turf/simulated/mineral/gibtonite = 3)
+ icon_state = "rock_labor"
+
+/turf/simulated/mineral/random/labormineral/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/lava/smooth/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+ mineralSpawnChanceList = list(
+ /turf/simulated/mineral/uranium/volcanic = 2, /turf/simulated/mineral/diamond/volcanic = 1, /turf/simulated/mineral/gold/volcanic = 3, /turf/simulated/mineral/titanium/volcanic = 4,
+ /turf/simulated/mineral/silver/volcanic = 6, /turf/simulated/mineral/plasma/volcanic = 15, /turf/simulated/mineral/iron/volcanic = 80,
+ /turf/simulated/mineral/gibtonite/volcanic = 3)
+
+// Actual minerals
+/turf/simulated/mineral/iron
+ mineralType = /obj/item/stack/ore/iron
+ spreadChance = 20
+ spread = 1
+ scan_state = "rock_Iron"
+
+/turf/simulated/mineral/iron/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/uranium
+ mineralType = /obj/item/stack/ore/uranium
+ spreadChance = 5
+ spread = 1
+ scan_state = "rock_Uranium"
+
+/turf/simulated/mineral/uranium/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/diamond
+ mineralType = /obj/item/stack/ore/diamond
+ spreadChance = 0
+ spread = 1
+ scan_state = "rock_Diamond"
+
+/turf/simulated/mineral/diamond/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/gold
+ mineralType = /obj/item/stack/ore/gold
+ spreadChance = 5
+ spread = 1
+ scan_state = "rock_Gold"
+
+/turf/simulated/mineral/gold/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/silver
+ mineralType = /obj/item/stack/ore/silver
+ spreadChance = 5
+ spread = 1
+ scan_state = "rock_Silver"
+
+/turf/simulated/mineral/silver/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/titanium
+ mineralType = /obj/item/stack/ore/titanium
+ spreadChance = 5
+ spread = 1
+ scan_state = "rock_Titanium"
+
+/turf/simulated/mineral/titanium/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/plasma
+ mineralType = /obj/item/stack/ore/plasma
+ spreadChance = 8
+ spread = 1
+ scan_state = "rock_Plasma"
+
+/turf/simulated/mineral/plasma/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/clown
+ mineralType = /obj/item/stack/ore/bananium
+ mineralAmt = 3
+ spreadChance = 0
+ spread = 0
+ scan_state = "rock_Clown"
+
+/turf/simulated/mineral/clown/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/mime
+ mineralType = /obj/item/stack/ore/tranquillite
+ mineralAmt = 3
+ spreadChance = 0
+ spread = 0
+
+/turf/simulated/mineral/mime/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/bscrystal
+ mineralType = /obj/item/stack/ore/bluespace_crystal
+ mineralAmt = 1
+ spreadChance = 0
+ spread = 0
+ scan_state = "rock_BScrystal"
+
+/turf/simulated/mineral/bscrystal/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+
+/turf/simulated/mineral/volcanic/lava_land_surface
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/lava/smooth/lava_land_surface
+ defer_change = 1
+
+// Gibtonite
+/turf/simulated/mineral/gibtonite
+ mineralAmt = 1
+ spreadChance = 0
+ spread = 0
+ scan_state = "rock_Gibtonite"
+ var/det_time = 8 //Countdown till explosion, but also rewards the player for how close you were to detonation when you defuse it
+ var/stage = 0 //How far into the lifecycle of gibtonite we are, 0 is untouched, 1 is active and attempting to detonate, 2 is benign and ready for extraction
+ var/activated_ckey = null //These are to track who triggered the gibtonite deposit for logging purposes
+ var/activated_name = null
+ var/activated_image = null
+
+/turf/simulated/mineral/gibtonite/volcanic
+ environment_type = "basalt"
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+ planetary_atmos = TRUE
+ defer_change = 1
+
+/turf/simulated/mineral/gibtonite/New()
+ det_time = rand(8,10) //So you don't know exactly when the hot potato will explode
+ ..()
+
+/turf/simulated/mineral/gibtonite/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) && stage == 1)
+ user.visible_message("You use [I] to locate where to cut off the chain reaction and attempt to stop it...")
+ defuse()
+ ..()
+
+/turf/simulated/mineral/gibtonite/proc/explosive_reaction(var/mob/user = null, triggered_by_explosion = 0)
+ if(stage == 0)
+ var/image/I = image('icons/turf/smoothrocks.dmi', loc = src, icon_state = "rock_Gibtonite_active", layer = ON_EDGED_TURF_LAYER)
+ add_overlay(I)
+ activated_image = I
+ name = "gibtonite deposit"
+ desc = "An active gibtonite reserve. Run!"
+ stage = 1
+ visible_message("There was gibtonite inside! It's going to explode!")
+ var/turf/bombturf = get_turf(src)
+ var/area/A = get_area(bombturf)
+
+ var/notify_admins = 0
+ if(z != 5)
+ notify_admins = 1
+ if(!triggered_by_explosion)
+ message_admins("[key_name_admin(user)] has triggered a gibtonite deposit reaction at [A.name] (JMP).")
+ else
+ message_admins("An explosion has triggered a gibtonite deposit reaction at [A.name] (JMP).")
+
+ if(!triggered_by_explosion)
+ log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [A.name] ([A.x], [A.y], [A.z]).")
+ else
+ log_game("An explosion has triggered a gibtonite deposit reaction at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
+
+ countdown(notify_admins)
+
+/turf/simulated/mineral/gibtonite/proc/countdown(notify_admins = 0)
+ set waitfor = 0
+ while(istype(src, /turf/simulated/mineral/gibtonite) && stage == 1 && det_time > 0 && mineralAmt >= 1)
+ det_time--
+ sleep(5)
+ if(istype(src, /turf/simulated/mineral/gibtonite))
+ if(stage == 1 && det_time <= 0 && mineralAmt >= 1)
+ var/turf/bombturf = get_turf(src)
+ mineralAmt = 0
+ stage = 3
+ explosion(bombturf,1,3,5, adminlog = notify_admins)
+
+/turf/simulated/mineral/gibtonite/proc/defuse()
+ if(stage == 1)
+ overlays -= activated_image
+ var/image/I = image('icons/turf/smoothrocks.dmi', loc = src, icon_state = "rock_Gibtonite_inactive", layer = ON_EDGED_TURF_LAYER)
+ add_overlay(I)
+ desc = "An inactive gibtonite reserve. The ore can be extracted."
+ stage = 2
+ if(det_time < 0)
+ det_time = 0
+ visible_message("The chain reaction was stopped! The gibtonite had [src.det_time] reactions left till the explosion!")
+
+/turf/simulated/mineral/gibtonite/gets_drilled(var/mob/user, triggered_by_explosion = 0)
+ if(stage == 0 && mineralAmt >= 1) //Gibtonite deposit is activated
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg',50,1)
+ explosive_reaction(user, triggered_by_explosion)
+ return
+ if(stage == 1 && mineralAmt >= 1) //Gibtonite deposit goes kaboom
+ var/turf/bombturf = get_turf(src)
+ mineralAmt = 0
+ stage = 3
+ explosion(bombturf, 1, 2, 5, adminlog = 0)
+ if(stage == 2) //Gibtonite deposit is now benign and extractable. Depending on how close you were to it blowing up before defusing, you get better quality ore.
+ var/obj/item/twohanded/required/gibtonite/G = new /obj/item/twohanded/required/gibtonite/(src)
+ if(det_time <= 0)
+ G.quality = 3
+ G.icon_state = "Gibtonite ore 3"
+ if(det_time >= 1 && det_time <= 2)
+ G.quality = 2
+ G.icon_state = "Gibtonite ore 2"
+
+ ChangeTurf(turf_type, defer_change)
+ addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE)
diff --git a/code/game/turfs/simulated/river.dm b/code/game/turfs/simulated/river.dm
new file mode 100644
index 00000000000..ed13f127019
--- /dev/null
+++ b/code/game/turfs/simulated/river.dm
@@ -0,0 +1,108 @@
+#define RANDOM_UPPER_X 200
+#define RANDOM_UPPER_Y 200
+
+#define RANDOM_LOWER_X 50
+#define RANDOM_LOWER_Y 50
+
+/proc/spawn_rivers(target_z, nodes = 4, turf_type = /turf/simulated/floor/plating/lava/smooth/lava_land_surface, whitelist_area = /area/lavaland/surface/outdoors/unexplored, min_x = RANDOM_LOWER_X, min_y = RANDOM_LOWER_Y, max_x = RANDOM_UPPER_X, max_y = RANDOM_UPPER_Y)
+ var/list/river_nodes = list()
+ var/num_spawned = 0
+ var/list/possible_locs = block(locate(min_x, min_y, target_z), locate(max_x, max_y, target_z))
+ while(num_spawned < nodes && possible_locs.len)
+ var/turf/T = pick(possible_locs)
+ var/area/A = get_area(T)
+ if(!istype(A, whitelist_area) || (T.flags & NO_LAVA_GEN))
+ possible_locs -= T
+ else
+ river_nodes += new /obj/effect/landmark/river_waypoint(T)
+ num_spawned++
+
+ //make some randomly pathing rivers
+ for(var/A in river_nodes)
+ var/obj/effect/landmark/river_waypoint/W = A
+ if (W.z != target_z || W.connected)
+ continue
+ W.connected = 1
+ var/turf/cur_turf = get_turf(W)
+ cur_turf.ChangeTurf(turf_type, ignore_air = TRUE)
+ var/turf/target_turf = get_turf(pick(river_nodes - W))
+ if(!target_turf)
+ break
+ var/detouring = 0
+ var/cur_dir = get_dir(cur_turf, target_turf)
+ while(cur_turf != target_turf)
+
+ if(detouring) //randomly snake around a bit
+ if(prob(20))
+ detouring = 0
+ cur_dir = get_dir(cur_turf, target_turf)
+ else if(prob(20))
+ detouring = 1
+ if(prob(50))
+ cur_dir = turn(cur_dir, 45)
+ else
+ cur_dir = turn(cur_dir, -45)
+ else
+ cur_dir = get_dir(cur_turf, target_turf)
+
+ cur_turf = get_step(cur_turf, cur_dir)
+ var/area/new_area = get_area(cur_turf)
+ if(!istype(new_area, whitelist_area) || (cur_turf.flags & NO_LAVA_GEN)) //Rivers will skip ruins
+ detouring = 0
+ cur_dir = get_dir(cur_turf, target_turf)
+ cur_turf = get_step(cur_turf, cur_dir)
+ continue
+ else
+ var/turf/river_turf = cur_turf.ChangeTurf(turf_type, ignore_air = TRUE)
+ river_turf.Spread(25, 11, whitelist_area)
+
+ for(var/WP in river_nodes)
+ qdel(WP)
+
+
+/obj/effect/landmark/river_waypoint
+ name = "river waypoint"
+ var/connected = 0
+ invisibility = INVISIBILITY_ABSTRACT
+
+
+/turf/proc/Spread(probability = 30, prob_loss = 25, whitelisted_area)
+ if(probability <= 0)
+ return
+ var/list/cardinal_turfs = list()
+ var/list/diagonal_turfs = list()
+ var/logged_turf_type
+ for(var/F in RANGE_TURFS(1, src) - src)
+ var/turf/T = F
+ var/area/new_area = get_area(T)
+ if(!T || (T.density && !ismineralturf(T)) || istype(T, /turf/unsimulated) || (whitelisted_area && !istype(new_area, whitelisted_area)) || (T.flags & NO_LAVA_GEN) )
+ continue
+
+ if(!logged_turf_type && ismineralturf(T))
+ var/turf/simulated/mineral/M = T
+ logged_turf_type = M.turf_type
+
+ if(get_dir(src, F) in cardinal)
+ cardinal_turfs += F
+ else
+ diagonal_turfs += F
+
+ for(var/F in cardinal_turfs) //cardinal turfs are always changed but don't always spread
+ var/turf/T = F
+ if(!istype(T, logged_turf_type) && T.ChangeTurf(type, ignore_air = TRUE) && prob(probability))
+ T.Spread(probability - prob_loss, prob_loss, whitelisted_area)
+
+ for(var/F in diagonal_turfs) //diagonal turfs only sometimes change, but will always spread if changed
+ var/turf/T = F
+ if(!istype(T, logged_turf_type) && prob(probability) && T.ChangeTurf(type, ignore_air = TRUE))
+ T.Spread(probability - prob_loss, prob_loss, whitelisted_area)
+ else if(ismineralturf(T))
+ var/turf/simulated/mineral/M = T
+ M.ChangeTurf(M.turf_type, ignore_air = TRUE)
+
+
+#undef RANDOM_UPPER_X
+#undef RANDOM_UPPER_Y
+
+#undef RANDOM_LOWER_X
+#undef RANDOM_LOWER_Y
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 6fddc40dfa9..5a8f842307e 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -22,6 +22,7 @@
heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall
var/hardness = 40 //lower numbers are harder. Used to determine the probability of a hulk smashing through.
+ var/slicing_duration = 100
var/engraving //engraving on the wall
var/engraving_quality
@@ -49,7 +50,6 @@
qdel(WR)
. = ..()
-
//Appearance
/turf/simulated/wall/examine(mob/user)
. = ..(user)
@@ -137,7 +137,7 @@
var/obj/structure/sign/poster/P = O
P.roll_and_drop(src)
else
- O.loc = src
+ O.forceMove(src)
ChangeTurf(/turf/simulated/floor/plating)
@@ -152,7 +152,7 @@
/turf/simulated/wall/ex_act(severity)
switch(severity)
if(1.0)
- src.ChangeTurf(/turf/space)
+ ChangeTurf(baseturf)
return
if(2.0)
if(prob(50))
@@ -253,6 +253,7 @@
/turf/simulated/wall/attack_hulk(mob/user, does_attack_animation = FALSE)
..(user, TRUE)
+
if(prob(hardness) || rotting)
playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1)
user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
@@ -340,7 +341,7 @@
to_chat(user, "You begin slicing through the outer plating.")
playsound(src, WT.usesound, 100, 1)
- if(do_after(user, 100 * WT.toolspeed, target = src) && WT && WT.isOn())
+ if(do_after(user, slicing_duration * WT.toolspeed, target = src) && WT && WT.isOn())
to_chat(user, "You remove the outer plating.")
dismantle_wall()
else
diff --git a/code/game/turfs/simulated/walls_indestructible.dm b/code/game/turfs/simulated/walls_indestructible.dm
new file mode 100644
index 00000000000..e25992a2555
--- /dev/null
+++ b/code/game/turfs/simulated/walls_indestructible.dm
@@ -0,0 +1,76 @@
+/turf/simulated/wall/indestructible
+ unacidable = TRUE
+
+/turf/simulated/wall/indestructible/dismantle_wall(devastated = 0, explode = 0)
+ return
+
+/turf/simulated/wall/indestructible/take_damage(dam)
+ return
+
+/turf/simulated/wall/indestructible/ex_act(severity)
+ return
+
+/turf/simulated/wall/indestructible/blob_act()
+ return
+
+/turf/simulated/wall/indestructible/singularity_act()
+ return
+
+/turf/simulated/wall/indestructible/singularity_pull(S, current_size)
+ return
+
+/turf/simulated/wall/indestructible/narsie_act()
+ return
+
+/turf/simulated/wall/indestructible/ratvar_act(force, ignore_mobs)
+ return
+
+/turf/simulated/wall/indestructible/burn_down()
+ return
+
+/turf/simulated/wall/indestructible/attackby(obj/item/I, mob/user, params)
+ return
+
+/turf/simulated/wall/indestructible/attack_hand(mob/user)
+ return
+
+/turf/simulated/wall/indestructible/attack_hulk(mob/user, does_attack_animation = FALSE)
+ return
+
+/turf/simulated/wall/indestructible/attack_animal(mob/living/simple_animal/M)
+ return
+
+/turf/simulated/wall/indestructible/mech_melee_attack(obj/mecha/M)
+ return
+
+/turf/simulated/wall/indestructible/necropolis
+ name = "necropolis wall"
+ desc = "A seemingly impenetrable wall."
+ icon = 'icons/turf/walls.dmi'
+ icon_state = "necro"
+ explosion_block = 50
+ baseturf = /turf/simulated/wall/indestructible/necropolis
+
+/turf/simulated/wall/indestructible/boss
+ name = "necropolis wall"
+ desc = "A thick, seemingly indestructible stone wall."
+ icon = 'icons/turf/walls/boss_wall.dmi'
+ icon_state = "wall"
+ canSmoothWith = list(/turf/simulated/wall/indestructible/boss, /turf/simulated/wall/indestructible/boss/see_through)
+ explosion_block = 50
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt
+ smooth = SMOOTH_TRUE
+
+/turf/simulated/wall/indestructible/boss/see_through
+ opacity = FALSE
+
+/turf/simulated/wall/indestructible/hierophant
+ name = "wall"
+ desc = "A wall made out of smooth, cold stone."
+ icon = 'icons/turf/walls/hierophant_wall.dmi'
+ icon_state = "hierophant"
+ smooth = SMOOTH_TRUE
+
+/turf/simulated/wall/indestructible/uranium
+ icon = 'icons/turf/walls/uranium_wall.dmi'
+ icon_state = "uranium"
\ No newline at end of file
diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm
index a0b3eb3f554..74d0e216614 100644
--- a/code/game/turfs/simulated/walls_mineral.dm
+++ b/code/game/turfs/simulated/walls_mineral.dm
@@ -275,6 +275,36 @@
icon_state = "map-overspace"
fixed_underlay = list("space"=1)
+/turf/simulated/wall/mineral/plastitanium/coated
+ name = "coated wall"
+ max_temperature = INFINITY
+ icon_state = "map-shuttle_nd"
+ smooth = SMOOTH_MORE
+
+/turf/simulated/wall/mineral/plastitanium/coated/Initialize(mapload)
+ . = ..()
+ desc += " It seems to have additional plating to protect against heat."
+
+/turf/simulated/wall/mineral/plastitanium/explosive
+ var/explosive_wall_group = EXPLOSIVE_WALL_GROUP_SYNDICATE_BASE
+ icon_state = "map-shuttle_nd"
+ smooth = SMOOTH_MORE
+
+/turf/simulated/wall/mineral/plastitanium/explosive/Initialize(mapload)
+ . = ..()
+ GLOB.explosive_walls += src
+
+/turf/simulated/wall/mineral/plastitanium/explosive/Destroy()
+ GLOB.explosive_walls -= src
+ return ..()
+
+/turf/simulated/wall/mineral/plastitanium/explosive/proc/self_destruct()
+ var/obj/item/bombcore/large/explosive_wall/bombcore = new(get_turf(src))
+ bombcore.detonate()
+
+/turf/simulated/wall/mineral/plastitanium/explosive/ex_act(severity)
+ return
+
//have to copypaste this code
/turf/simulated/wall/mineral/plastitanium/interior/copyTurf(turf/T)
if(T.type != type)
diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm
index 18492da2d00..b2d6b40c123 100644
--- a/code/game/turfs/simulated/walls_misc.dm
+++ b/code/game/turfs/simulated/walls_misc.dm
@@ -12,9 +12,9 @@
/turf/simulated/wall/cult/New()
..()
- if(ticker.mode)//game hasn't started offically don't do shit..
+ if(SSticker.mode)//game hasn't started offically don't do shit..
new /obj/effect/temp_visual/cult/turf(src)
- icon_state = ticker.cultdat.cult_wall_icon_state
+ icon_state = SSticker.cultdat.cult_wall_icon_state
/turf/simulated/wall/cult/artificer
name = "runed stone wall"
@@ -49,4 +49,101 @@
name = "coated reinforced wall"
desc = "A huge chunk of reinforced metal used to seperate rooms. It seems to have additional plating to protect against heat."
icon = 'icons/turf/walls/coated_reinforced_wall.dmi'
- max_temperature = INFINITY
\ No newline at end of file
+ max_temperature = INFINITY
+
+//Clockwork walls
+/turf/simulated/wall/clockwork
+ name = "clockwork wall"
+ desc = "A huge chunk of warm metal. The clanging of machinery emanates from within."
+ explosion_block = 2
+ hardness = 10
+ slicing_duration = 80
+ sheet_type = /obj/item/stack/tile/brass
+ sheet_amount = 1
+ girder_type = /obj/structure/clockwork/wall_gear
+ baseturf = /turf/simulated/floor/clockwork/reebe
+ var/heated
+ var/obj/effect/clockwork/overlay/wall/realappearance
+
+/turf/simulated/wall/clockwork/Initialize()
+ . = ..()
+ new /obj/effect/temp_visual/ratvar/wall(src)
+ new /obj/effect/temp_visual/ratvar/beam(src)
+ realappearance = new /obj/effect/clockwork/overlay/wall(src)
+ realappearance.linked = src
+
+/turf/simulated/wall/clockwork/Destroy()
+ if(realappearance)
+ qdel(realappearance)
+ realappearance = null
+
+ return ..()
+
+/turf/simulated/wall/clockwork/ReplaceWithLattice()
+ ..()
+ for(var/obj/structure/lattice/L in src)
+ L.ratvar_act()
+
+/turf/simulated/wall/clockwork/narsie_act()
+ ..()
+ if(istype(src, /turf/simulated/wall/clockwork)) //if we haven't changed type
+ var/previouscolor = color
+ color = "#960000"
+ animate(src, color = previouscolor, time = 8)
+ addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
+
+/turf/simulated/wall/clockwork/dismantle_wall(devastated=0, explode=0)
+ if(devastated)
+ devastate_wall()
+ ChangeTurf(baseturf)
+ else
+ playsound(src, 'sound/items/welder.ogg', 100, 1)
+ var/newgirder = break_wall()
+ if(newgirder) //maybe we want a gear!
+ transfer_fingerprints_to(newgirder)
+ ChangeTurf(baseturf)
+
+ for(var/obj/O in src) //Eject contents!
+ if(istype(O, /obj/structure/sign/poster))
+ var/obj/structure/sign/poster/P = O
+ P.roll_and_drop(src)
+ else
+ O.forceMove(src)
+
+/turf/simulated/wall/clockwork/devastate_wall()
+ for(var/i in 1 to 2)
+ new/obj/item/clockwork/alloy_shards/large(src)
+ for(var/i in 1 to 2)
+ new/obj/item/clockwork/alloy_shards/medium(src)
+ for(var/i in 1 to 3)
+ new/obj/item/clockwork/alloy_shards/small(src)
+
+/turf/simulated/wall/clockwork/attack_hulk(mob/living/user, does_attack_animation = 0)
+ ..()
+ if(heated)
+ to_chat(user, "The wall is searing hot to the touch!")
+ user.adjustFireLoss(5)
+ playsound(src, 'sound/machines/fryer/deep_fryer_emerge.ogg', 50, TRUE)
+
+/turf/simulated/wall/clockwork/mech_melee_attack(obj/mecha/M)
+ ..()
+ if(heated)
+ to_chat(M.occupant, "The wall's intense heat completely reflects your [M.name]'s attack!")
+ M.take_damage(20, BURN)
+
+/turf/simulated/wall/clockwork/proc/turn_up_the_heat()
+ if(!heated)
+ name = "superheated [name]"
+ visible_message("[src] sizzles with heat!")
+ playsound(src, 'sound/machines/fryer/deep_fryer_emerge.ogg', 50, TRUE)
+ heated = TRUE
+ hardness = -100 //Lower numbers are tougher, so this makes the wall essentially impervious to smashing
+ slicing_duration = 150
+ animate(realappearance, color = "#FFC3C3", time = 5)
+ else
+ name = initial(name)
+ visible_message("[src] cools down.")
+ heated = FALSE
+ hardness = initial(hardness)
+ slicing_duration = initial(slicing_duration)
+ animate(realappearance, color = initial(realappearance.color), time = 25)
diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm
index f1837173d6d..45abe2e155c 100644
--- a/code/game/turfs/simulated/walls_reinforced.dm
+++ b/code/game/turfs/simulated/walls_reinforced.dm
@@ -12,6 +12,7 @@
sheet_type = /obj/item/stack/sheet/plasteel
sheet_amount = 1
girder_type = /obj/structure/girder/reinforced
+ unacidable = TRUE
var/d_state = RWALL_INTACT
var/can_be_reinforced = 1
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 42f19fb2f7f..0d6428b10a2 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -2,26 +2,36 @@
icon = 'icons/turf/space.dmi'
name = "\proper space"
icon_state = "0"
- dynamic_lighting = 0
- luminosity = 1
temperature = TCMB
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
- heat_capacity = 700000
+ heat_capacity = HEAT_CAPACITY_VACUUM
+
+ plane = PLANE_SPACE
+ layer = SPACE_LAYER
+ light_power = 0.25
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
+ intact = FALSE
var/destination_z
var/destination_x
var/destination_y
-/turf/space/New()
- . = ..()
-
+/turf/space/Initialize(mapload)
if(!istype(src, /turf/space/transit))
icon_state = SPACE_ICON_STATE
- if(update_starlight() && is_station_level(z))
- // before you ask: Yes, this is fucking stupid, but looping through turf/space in world is how you make the server freeze
- // so I don't see a better way of doing this
- LAZYADD(GLOB.station_level_space_turfs, src)
+
+ var/area/A = loc
+ if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
+ add_overlay(/obj/effect/fullbright)
+
+ if (light_power && light_range)
+ update_light()
+
+ if (opacity)
+ has_opaque_atom = TRUE
+
+ return INITIALIZE_HINT_NORMAL
/turf/space/Destroy(force)
if(force)
@@ -29,7 +39,6 @@
else
return QDEL_HINT_LETMELIVE
-
/turf/space/BeforeChange()
..()
var/datum/space_level/S = space_manager.get_zlev(z)
@@ -44,26 +53,29 @@
S.apply_transition(src)
/turf/space/proc/update_starlight()
- if(!config.starlight)
- return FALSE
- if(locate(/turf/simulated) in orange(src,1))
- set_light(config.starlight)
- return TRUE
- else
+ if(config.starlight)
+ for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm
+ if(isspaceturf(t))
+ //let's NOT update this that much pls
+ continue
+ set_light(2)
+ return
set_light(0)
- return FALSE
/turf/space/attackby(obj/item/C as obj, mob/user as mob, params)
..()
if(istype(C, /obj/item/stack/rods))
var/obj/item/stack/rods/R = C
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ var/obj/structure/lattice/catwalk/W = locate(/obj/structure/lattice/catwalk, src)
+ if(W)
+ to_chat(user, "There is already a catwalk here!")
+ return
if(L)
if(R.use(1))
- to_chat(user, "You begin constructing catwalk...")
+ to_chat(user, "You construct a catwalk.")
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
- qdel(L)
- ChangeTurf(/turf/simulated/floor/plating/airless/catwalk)
+ new/obj/structure/lattice/catwalk(src)
else
to_chat(user, "You need two rods to build a catwalk!")
return
@@ -91,17 +103,17 @@
/turf/space/Entered(atom/movable/A as mob|obj, atom/OL, ignoreRest = 0)
..()
+ if((!(A) || !(src in A.locs)))
+ return
- if(destination_z && A && (src in A.locs))
- A.x = destination_x
- A.y = destination_y
- A.z = destination_z
+ if(destination_z && destination_x && destination_y)
+ A.forceMove(locate(destination_x, destination_y, destination_z))
if(isliving(A))
var/mob/living/L = A
if(L.pulling)
var/turf/T = get_step(L.loc,turn(A.dir, 180))
- L.pulling.loc = T
+ L.pulling.forceMove(T)
//now we're on the new z_level, proceed the space drifting
sleep(0)//Let a diagonal move finish, if necessary
@@ -220,6 +232,8 @@
return
/turf/space/can_have_cabling()
+ if(locate(/obj/structure/lattice/catwalk, src))
+ return 1
return 0
/turf/space/proc/set_transition_north(dest_z)
@@ -244,3 +258,8 @@
/turf/space/proc/remove_transitions()
destination_z = initial(destination_z)
+
+/turf/space/attack_ghost(mob/dead/observer/user)
+ if(destination_z)
+ var/turf/T = locate(destination_x, destination_y, destination_z)
+ user.forceMove(T)
\ No newline at end of file
diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm
index c08189e4d93..79bf171ce1f 100644
--- a/code/game/turfs/space/transit.dm
+++ b/code/game/turfs/space/transit.dm
@@ -88,7 +88,7 @@
/turf/space/transit/Entered(atom/movable/AM, atom/OldLoc, ignoreRest = 0)
if(!AM)
return
- if(istype(AM, /obj/docking_port) || !AM.simulated)
+ if(!AM.simulated || istype(AM, /obj/docking_port))
return //this was fucking hilarious, the docking ports were getting thrown to random Z-levels
var/max = world.maxx-TRANSITIONEDGE
var/min = 1+TRANSITIONEDGE
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 677357cf170..e315ad26ad0 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -38,9 +38,22 @@
..()
for(var/atom/movable/AM in src)
Entered(AM)
- if(smooth && ticker && ticker.current_state == GAME_STATE_PLAYING)
+ if(smooth && SSticker && SSticker.current_state == GAME_STATE_PLAYING)
queue_smooth(src)
+/turf/Initialize(mapload)
+ . = ..()
+
+ var/area/A = loc
+ if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
+ add_overlay(/obj/effect/fullbright)
+
+ if(light_power && light_range)
+ update_light()
+
+ if (opacity)
+ has_opaque_atom = TRUE
+
/hook/startup/proc/smooth_world()
var/watch = start_watch()
log_startup_progress("Smoothing atoms...")
@@ -167,17 +180,21 @@
if(L)
qdel(L)
+/turf/proc/TerraformTurf(path, defer_change = FALSE, keep_icon = TRUE, ignore_air = FALSE)
+ return ChangeTurf(path, defer_change, keep_icon, ignore_air)
+
//Creates a new turf
-/turf/proc/ChangeTurf(path, defer_change = FALSE, keep_icon = TRUE)
+/turf/proc/ChangeTurf(path, defer_change = FALSE, keep_icon = TRUE, ignore_air = FALSE)
if(!path)
return
if(!use_preloader && path == type) // Don't no-op if the map loader requires it to be reconstructed
return src
+
set_light(0)
var/old_opacity = opacity
var/old_dynamic_lighting = dynamic_lighting
var/old_affecting_lights = affecting_lights
- var/old_lighting_overlay = lighting_overlay
+ var/old_lighting_object = lighting_object
var/old_blueprint_data = blueprint_data
var/old_obscured = obscured
var/old_corners = corners
@@ -185,29 +202,35 @@
BeforeChange()
if(SSair)
SSair.remove_from_active(src)
+
+ var/old_baseturf = baseturf
var/turf/W = new path(src)
+ W.baseturf = old_baseturf
+
if(!defer_change)
- W.AfterChange()
-
+ W.AfterChange(ignore_air)
W.blueprint_data = old_blueprint_data
- for(var/turf/space/S in range(W,1))
- S.update_starlight()
-
recalc_atom_opacity()
- if(lighting_overlays_initialised)
- lighting_overlay = old_lighting_overlay
+ if(SSlighting.initialized)
+ recalc_atom_opacity()
+ lighting_object = old_lighting_object
+
affecting_lights = old_affecting_lights
corners = old_corners
- if((old_opacity != opacity) || (dynamic_lighting != old_dynamic_lighting))
+ if(old_opacity != opacity || dynamic_lighting != old_dynamic_lighting)
reconsider_lights()
+
if(dynamic_lighting != old_dynamic_lighting)
- if(dynamic_lighting)
+ if(IS_DYNAMIC_LIGHTING(src))
lighting_build_overlay()
else
lighting_clear_overlay()
+ for(var/turf/space/S in RANGE_TURFS(1, src)) //RANGE_TURFS is in code\__HELPERS\game.dm
+ S.update_starlight()
+
obscured = old_obscured
return W
@@ -266,8 +289,8 @@
SSair.add_to_active(src)
/turf/proc/ReplaceWithLattice()
- src.ChangeTurf(/turf/space)
- new /obj/structure/lattice( locate(src.x, src.y, src.z) )
+ ChangeTurf(baseturf)
+ new /obj/structure/lattice(locate(x, y, z))
/turf/proc/kill_creatures(mob/U = null)//Will kill people/creatures and damage mechs./N
//Useful to batch-add creatures to the list.
@@ -282,6 +305,10 @@
/turf/proc/Bless()
flags |= NOJAUNT
+/turf/get_spooked()
+ for(var/atom/movable/AM in contents)
+ AM.get_spooked()
+
/turf/proc/burn_down()
return
@@ -399,11 +426,11 @@
continue
if(O.invisibility == 101)
O.singularity_act()
- ChangeTurf(/turf/space)
+ ChangeTurf(baseturf)
return(2)
/turf/proc/visibilityChanged()
- if(ticker)
+ if(SSticker)
cameranet.updateVisibility(src)
/turf/attackby(obj/item/I, mob/user, params)
@@ -456,7 +483,7 @@
blueprint_data += I
/turf/proc/add_blueprints_preround(atom/movable/AM)
- if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
+ if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING)
add_blueprints(AM)
/turf/proc/empty(turf_type=/turf/space)
@@ -464,14 +491,14 @@
var/turf/T0 = src
for(var/X in T0.GetAllContents())
var/atom/A = X
+ if(!A.simulated)
+ continue
if(istype(A, /mob/dead))
continue
if(istype(A, /obj/effect/landmark))
continue
if(istype(A, /obj/docking_port))
continue
- if(!A.simulated)
- continue
qdel(A, force=TRUE)
T0.ChangeTurf(turf_type)
@@ -482,3 +509,7 @@
/turf/AllowDrop()
return TRUE
+
+/turf/proc/water_act(volume, temperature, source)
+ for(var/mob/living/carbon/slime/M in src)
+ M.apply_water()
diff --git a/code/game/turfs/unsimulated.dm b/code/game/turfs/unsimulated.dm
index 35b6c2056e3..8ae608a0af6 100644
--- a/code/game/turfs/unsimulated.dm
+++ b/code/game/turfs/unsimulated.dm
@@ -37,12 +37,6 @@
nitrogen = 0
temperature = TCMB
- New()
- ..()
- name = "plating"
-
-/turf/unsimulated/floor/plating/airless/catwalk
- icon = 'icons/turf/catwalks.dmi'
- icon_state = "catwalk0"
- name = "catwalk"
- desc = "Cats really don't like these things."
\ No newline at end of file
+/turf/unsimulated/floor/plating/airless/New()
+ ..()
+ name = "plating"
diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm
index b7c76359c46..15650c1f00e 100644
--- a/code/game/turfs/unsimulated/beach.dm
+++ b/code/game/turfs/unsimulated/beach.dm
@@ -7,7 +7,9 @@
/turf/unsimulated/beach/New()
..()
if(water_overlay_image)
- overlays += image("icon"='icons/misc/beach.dmi',"icon_state"= water_overlay_image,"layer"=MOB_LAYER+0.1)
+ var/image/overlay_image = image('icons/misc/beach.dmi', icon_state = water_overlay_image, layer = ABOVE_MOB_LAYER)
+ overlay_image.plane = GAME_PLANE
+ overlays += overlay_image
/turf/unsimulated/beach/sand
name = "Sand"
diff --git a/code/game/turfs/unsimulated/floor.dm b/code/game/turfs/unsimulated/floor.dm
index 8df18294f04..c71404dc0d7 100644
--- a/code/game/turfs/unsimulated/floor.dm
+++ b/code/game/turfs/unsimulated/floor.dm
@@ -16,46 +16,6 @@
icon = 'icons/turf/snow.dmi'
icon_state = "snow"
-/turf/unsimulated/floor/chasm
- name = "chasm"
- desc = "It's difficult to see the bottom."
- density = 0
- icon = 'icons/turf/floors/Chasms.dmi'
- icon_state = "Fill"
- smooth = SMOOTH_MORE
- canSmoothWith = list(/turf/unsimulated/floor/chasm)
-
-/turf/unsimulated/floor/chasm/Entered(mob/living/M, atom/OL, ignoreRest = 0)
- // "fall" south
- if(istype(M))
- spawn(1)
- if(step(M, SOUTH))
- M.emote("scream")
-
-/turf/unsimulated/floor/chasm/dense
- density = 1
-
-/turf/unsimulated/floor/lava
- name = "lava"
- desc = "That looks... a bit dangerous"
- icon = 'icons/turf/floors/lava.dmi'
- icon_state = "smooth"
- smooth = SMOOTH_MORE
- canSmoothWith = list(/turf/unsimulated/floor/lava)
- var/lava_damage = 250
- var/lava_fire = 20
- light_range = 2
- light_color = "#FFC040"
-
-/turf/unsimulated/floor/lava/Entered(mob/living/M, atom/OL, ignoreRest = 0)
- if(istype(M))
- M.apply_damage(lava_damage, BURN)
- M.adjust_fire_stacks(lava_fire)
- M.IgniteMob()
-
-/turf/unsimulated/floor/lava/dense
- density = 1
-
/turf/unsimulated/floor/abductor
name = "alien floor"
icon_state = "alienpod1"
@@ -88,3 +48,24 @@
"human" = list('sound/effects/footstep/wood_all.ogg'), //@RonaldVanWonderen of Freesound.org
"xeno" = list('sound/effects/footstep/wood_all.ogg') //@RonaldVanWonderen of Freesound.org
)
+
+/turf/unsimulated/floor/lava
+ name = "lava"
+ desc = "That looks... a bit dangerous"
+ icon = 'icons/turf/floors/lava.dmi'
+ icon_state = "smooth"
+ smooth = SMOOTH_MORE
+ canSmoothWith = list(/turf/unsimulated/floor/lava)
+ var/lava_damage = 250
+ var/lava_fire = 20
+ light_range = 2
+ light_color = "#FFC040"
+
+/turf/unsimulated/floor/lava/Entered(mob/living/M, atom/OL, ignoreRest = 0)
+ if(istype(M))
+ M.apply_damage(lava_damage, BURN)
+ M.adjust_fire_stacks(lava_fire)
+ M.IgniteMob()
+
+/turf/unsimulated/floor/lava/dense
+ density = 1
diff --git a/code/game/turfs/unsimulated/walls.dm b/code/game/turfs/unsimulated/walls.dm
index 4bcc4e90b2f..c7b192366d4 100644
--- a/code/game/turfs/unsimulated/walls.dm
+++ b/code/game/turfs/unsimulated/walls.dm
@@ -32,4 +32,4 @@
/turf/unsimulated/wall/abductor
icon_state = "alien1"
- explosion_block = 50
\ No newline at end of file
+ explosion_block = 50
diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm
index a35047bb9ad..5a2807e8379 100644
--- a/code/game/verbs/ooc.dm
+++ b/code/game/verbs/ooc.dm
@@ -4,7 +4,11 @@ var/global/mentor_ooc_colour = "#0099cc"
var/global/moderator_ooc_colour = "#184880"
var/global/admin_ooc_colour = "#b82e00"
-/client/verb/ooc(msg as text)
+//Checks if the client already has a text input open
+/client/proc/checkTyping()
+ return (prefs.toggles & TYPING_ONCE && typing)
+
+/client/verb/ooc(msg = "" as text)
set name = "OOC"
set category = "OOC"
@@ -14,6 +18,20 @@ var/global/admin_ooc_colour = "#b82e00"
to_chat(src, "Guests may not use OOC.")
return
+ if(!check_rights(R_ADMIN|R_MOD, 0))
+ if(!config.ooc_allowed)
+ to_chat(src, "OOC is globally muted.")
+ return
+ if(!config.dooc_allowed && (mob.stat == DEAD))
+ to_chat(usr, "OOC for dead mobs has been turned off.")
+ return
+ if(prefs.muted & MUTE_OOC)
+ to_chat(src, "You cannot use OOC (muted).")
+ return
+
+ if(!msg)
+ msg = typing_input(src.mob, "", "ooc \"text\"")
+
msg = trim(sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)))
if(!msg)
return
@@ -23,15 +41,6 @@ var/global/admin_ooc_colour = "#b82e00"
return
if(!check_rights(R_ADMIN|R_MOD,0))
- if(!config.ooc_allowed)
- to_chat(src, "OOC is globally muted.")
- return
- if(!config.dooc_allowed && (mob.stat == DEAD))
- to_chat(usr, "OOC for dead mobs has been turned off.")
- return
- if(prefs.muted & MUTE_OOC)
- to_chat(src, "You cannot use OOC (muted).")
- return
if(handle_spam_prevention(msg, MUTE_OOC, OOC_COOLDOWN))
return
if(findtext(msg, "byond://"))
@@ -67,7 +76,7 @@ var/global/admin_ooc_colour = "#b82e00"
var/icon/byond = icon('icons/member_content.dmi', "blag")
display_name = "[bicon(byond)][display_name]"
- if(donator_level >= DONATOR_LEVEL_ONE)
+ if(donator_level > 0)
if((prefs.toggles & DONATOR_PUBLIC))
var/icon/donator = icon('icons/ooc_tag_16x.dmi', "donator")
display_name = "[bicon(donator)][display_name]"
@@ -150,7 +159,7 @@ var/global/admin_ooc_colour = "#b82e00"
feedback_add_details("admin_verb","ROC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/verb/looc(msg as text)
+/client/verb/looc(msg = "" as text)
set name = "LOOC"
set desc = "Local OOC, seen only by those in view."
set category = "OOC"
@@ -161,14 +170,6 @@ var/global/admin_ooc_colour = "#b82e00"
to_chat(src, "Guests may not use OOC.")
return
- msg = trim(sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)))
- if(!msg)
- return
-
- if(!(prefs.toggles & CHAT_LOOC))
- to_chat(src, "You have LOOC muted.")
- return
-
if(!check_rights(R_ADMIN|R_MOD,0))
if(!config.looc_allowed)
to_chat(src, "LOOC is globally muted.")
@@ -179,6 +180,19 @@ var/global/admin_ooc_colour = "#b82e00"
if(prefs.muted & MUTE_OOC)
to_chat(src, "You cannot use LOOC (muted).")
return
+
+ if(!msg)
+ msg = typing_input(src.mob, "Local OOC, seen only by those in view.", "looc \"text\"")
+
+ msg = trim(sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)))
+ if(!msg)
+ return
+
+ if(!(prefs.toggles & CHAT_LOOC))
+ to_chat(src, "You have LOOC muted.")
+ return
+
+ if(!check_rights(R_ADMIN|R_MOD,0))
if(handle_spam_prevention(msg, MUTE_OOC, OOC_COOLDOWN))
return
if(findtext(msg, "byond://"))
diff --git a/code/game/verbs/randomtip.dm b/code/game/verbs/randomtip.dm
new file mode 100644
index 00000000000..25cc996c8fe
--- /dev/null
+++ b/code/game/verbs/randomtip.dm
@@ -0,0 +1,16 @@
+/client/verb/randomtip()
+ set category = "OOC"
+ set name = "Give Random Tip"
+ set desc = "Shows you a random tip"
+
+ var/m
+
+ var/list/randomtips = file2list("strings/tips.txt")
+ var/list/memetips = file2list("strings/sillytips.txt")
+ if(randomtips.len && prob(95))
+ m = pick(randomtips)
+ else if(memetips.len)
+ m = pick(memetips)
+
+ if(m)
+ to_chat(src, "Tip: [html_encode(m)]")
diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm
index 06b168da042..0b171dac199 100644
--- a/code/game/verbs/suicide.dm
+++ b/code/game/verbs/suicide.dm
@@ -1,7 +1,7 @@
/mob/var/suiciding = 0
/mob/living/carbon/human/proc/do_suicide(damagetype, byitem)
- var/threshold = (config.health_threshold_crit + config.health_threshold_dead) / 2
+ var/threshold = check_death_method() ? ((HEALTH_THRESHOLD_CRIT + HEALTH_THRESHOLD_DEAD) / 2) : (HEALTH_THRESHOLD_DEAD - 50)
var/dmgamt = maxHealth - threshold
var/damage_mod = 1
@@ -52,11 +52,14 @@
/mob/living/carbon/human/verb/suicide()
set hidden = 1
+ be_suicidal()
+
+/mob/living/carbon/human/proc/be_suicidal(forced = FALSE)
if(stat == DEAD)
to_chat(src, "You're already dead!")
return
- if(!ticker)
+ if(!SSticker)
to_chat(src, "You can't commit suicide before the game starts!")
return
@@ -69,20 +72,39 @@
to_chat(src, "You're already committing suicide! Be patient!")
return
- var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No")
- if(confirm == "Yes")
- suiciding = 1
+ var/confirm = null
+ if(!forced)
+ confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No")
+
+ if(forced || (confirm == "Yes"))
+ suiciding = TRUE
var/obj/item/held_item = get_active_hand()
if(held_item)
var/damagetype = held_item.suicide_act(src)
if(damagetype)
if(damagetype & SHAME)
adjustStaminaLoss(200)
- suiciding = 0
+ suiciding = FALSE
+ return
+ if(damagetype & OBLITERATION) // Does it gib or something? Don't deal damage
return
do_suicide(damagetype, held_item)
return
+ else
+ for(var/obj/O in orange(1, src))
+ if(O.suicidal_hands)
+ continue
+ var/damagetype = O.suicide_act(src)
+ if(damagetype)
+ if(damagetype & SHAME)
+ adjustStaminaLoss(200)
+ suiciding = FALSE
+ return
+ if(damagetype & OBLITERATION)
+ return
+ do_suicide(damagetype, O)
+ return
to_chat(viewers(src), "[src] [replacetext(pick(dna.species.suicide_messages), "their", p_their())] It looks like [p_theyre()] trying to commit suicide.")
do_suicide(0)
@@ -94,7 +116,7 @@
to_chat(src, "You're already dead!")
return
- if(!ticker)
+ if(!SSticker)
to_chat(src, "You can't commit suicide before the game starts!")
return
@@ -207,3 +229,19 @@
setCloneLoss(100, FALSE)
updatehealth()
+
+/mob/living/simple_animal/mouse/verb/suicide()
+ set hidden = 1
+ if(stat == DEAD)
+ to_chat(src, "You're already dead!")
+ return
+ if(suiciding)
+ to_chat(src, "You're already committing suicide! Be patient!")
+ return
+
+ var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No")
+
+ if(confirm == "Yes")
+ suiciding = TRUE
+ visible_message("[src] is playing dead permanently! It looks like [p_theyre()] trying to commit suicide.")
+ adjustOxyLoss(max(100 - getBruteLoss(100), 0))
\ No newline at end of file
diff --git a/code/game/world.dm b/code/game/world.dm
index 52f12a10c4e..a74870413d3 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -30,25 +30,6 @@ var/global/list/map_transition_config = MAP_TRANSITION_CONFIG
Master.Initialize(10, FALSE)
- processScheduler = new
- master_controller = new /datum/controller/game_controller()
- spawn(1)
- processScheduler.deferSetupFor(/datum/controller/process/ticker)
- processScheduler.setup()
-
- master_controller.setup()
-
- if(using_map && using_map.name)
- map_name = "[using_map.name]"
- else
- map_name = "Unknown"
-
-
- if(config && config.server_name)
- name = "[config.server_name]: [station_name()]"
- else
- name = station_name()
-
#undef RECOMMENDED_VERSION
@@ -117,13 +98,13 @@ var/world_topic_spam_protect_time = world.timeofday
player_count++
s["players"] = player_count
s["admins"] = admin_count
- s["map_name"] = map_name ? map_name : "Unknown"
+ s["map_name"] = GLOB.map_name ? GLOB.map_name : "Unknown"
if(key_valid)
- if(ticker && ticker.mode)
- s["real_mode"] = ticker.mode.name
+ if(SSticker && SSticker.mode)
+ s["real_mode"] = SSticker.mode.name
s["security_level"] = get_security_level()
- s["ticker_state"] = ticker.current_state
+ s["ticker_state"] = SSticker.current_state
if(SSshuttle && SSshuttle.emergency)
// Shuttle status, see /__DEFINES/stat.dm
@@ -299,8 +280,8 @@ var/world_topic_spam_protect_time = world.timeofday
if(!isnull(time))
delay = max(0,time)
else
- delay = ticker.restart_timeout
- if(ticker.delay_end)
+ delay = SSticker.restart_timeout
+ if(SSticker.delay_end)
to_chat(world, "An admin has delayed the round end.")
return
to_chat(world, "Rebooting world in [delay/10] [delay > 10 ? "seconds" : "second"]. [reason]")
@@ -309,19 +290,19 @@ var/world_topic_spam_protect_time = world.timeofday
var/sound_length = GLOB.round_end_sounds[round_end_sound]
if(delay > sound_length) // If there's time, play the round-end sound before rebooting
spawn(delay - sound_length)
- if(!ticker.delay_end)
+ if(!SSticker.delay_end)
world << round_end_sound
sleep(delay)
if(blackbox)
blackbox.save_all_data_to_sql()
- if(ticker.delay_end)
+ if(SSticker.delay_end)
to_chat(world, "Reboot was cancelled by an admin.")
return
feedback_set_details("[feedback_c]","[feedback_r]")
log_game("Rebooting world. [reason]")
//kick_clients_in_lobby("The round came to an end with you in the lobby.", 1)
- processScheduler.stop()
+ Master.Shutdown() //run SS shutdowns
shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
for(var/client/C in GLOB.clients)
@@ -371,66 +352,50 @@ var/world_topic_spam_protect_time = world.timeofday
// apply some settings from config..
/world/proc/update_status()
+ status = get_status_text()
+
+/proc/get_world_status_text()
+ return world.get_status_text()
+
+/world/proc/get_status_text()
var/s = ""
if(config && config.server_name)
s += "[config.server_name] — "
+ s += "[station_name()] "
+ if(config && config.githuburl)
+ s+= "([game_version])"
- s += "[station_name()]";
- s += " ("
- s += "" //Change this to wherever you want the hub to link to.
- s += "[game_version]"
- s += ""
- s += ")"
- s += " The Perfect Mix of RP & Action "
+ if(config && config.server_tag_line)
+ s += " [config.server_tag_line]"
-
-
-
- var/list/features = list()
-
- if(ticker)
- if(master_mode)
- features += master_mode
+ if(SSticker && ROUND_TIME > 0)
+ s += " [round(ROUND_TIME / 36000)]:[add_zero(num2text(ROUND_TIME / 600 % 60), 2)], " + capitalize(get_security_level())
else
- features += "STARTING"
+ s += " STARTING"
+
+ s += " "
+ var/list/features = list()
if(!enter_allowed)
features += "closed"
- features += abandon_allowed ? "respawn" : "no respawn"
+ if(config && config.server_extra_features)
+ features += config.server_extra_features
if(config && config.allow_vote_mode)
features += "vote"
- if(config && config.allow_ai)
- features += "AI allowed"
+ if(config && config.wikiurl)
+ features += "Wiki"
- var/n = 0
- for(var/mob/M in GLOB.player_list)
- if(M.client)
- n++
-
- if(n > 1)
- features += "~[n] players"
- else if(n > 0)
- features += "~[n] player"
-
- /*
- is there a reason for this? the byond site shows 'hosted by X' when there is a proper host already.
- if(host)
- features += "hosted by [host]"
- */
-
-// if(!host && config && config.hostedby)
-// features += "hosted by [config.hostedby]"
+ if(abandon_allowed)
+ features += "respawn"
if(features)
- s += ": [jointext(features, ", ")]"
+ s += "[jointext(features, ", ")]"
- /* does this help? I do not know */
- if(src.status != s)
- src.status = s
+ return s
#define FAILED_DB_CONNECTION_CUTOFF 5
var/failed_db_connections = 0
diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm
index dd46725ff26..1ce6c2b90f0 100644
--- a/code/modules/admin/DB ban/functions.dm
+++ b/code/modules/admin/DB ban/functions.dm
@@ -70,6 +70,11 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
if(banned_mob.client)
computerid = banned_mob.client.computer_id
ip = banned_mob.client.address
+ else
+ if(banned_mob.lastKnownIP)
+ ip = banned_mob.lastKnownIP
+ if(banned_mob.computer_id)
+ computerid = banned_mob.computer_id
else if(banckey)
ckey = ckey(banckey)
computerid = bancid
@@ -145,6 +150,8 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
if(isjobban)
jobban_client_fullban(ckey, job)
+ else
+ flag_account_for_forum_sync(ckey)
datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
@@ -223,6 +230,8 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
DB_ban_unban_by_id(ban_id)
if(isjobban)
jobban_unban_client(ckey, job)
+ else
+ flag_account_for_forum_sync(ckey)
datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
@@ -328,6 +337,8 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
var/DBQuery/query_update = dbcon.NewQuery(sql_update)
query_update.Execute()
+ flag_account_for_forum_sync(pckey)
+
/client/proc/DB_ban_panel()
set category = "Admin"
@@ -561,4 +572,12 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
output += "
"
- usr << browse(output,"window=lookupbans;size=900x700")
\ No newline at end of file
+ usr << browse(output,"window=lookupbans;size=900x700")
+
+/proc/flag_account_for_forum_sync(ckey)
+ if(!dbcon)
+ return
+ var/skey = sanitizeSQL(ckey)
+ var/sql = "UPDATE [format_table_name("player")] SET fupdate = 1 WHERE ckey = '[skey]'"
+ var/DBQuery/adm_query = dbcon.NewQuery(sql)
+ adm_query.Execute()
diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm
index ec9fa9af05e..045819c365b 100644
--- a/code/modules/admin/IsBanned.dm
+++ b/code/modules/admin/IsBanned.dm
@@ -1,5 +1,12 @@
//Blocks an attempt to connect before even creating our client datum thing.
-world/IsBanned(key,address,computer_id)
+world/IsBanned(key, address, computer_id, check_ipintel = TRUE)
+
+ if(!config.ban_legacy_system)
+ if(address)
+ address = sanitizeSQL(address)
+ if(computer_id)
+ computer_id = sanitizeSQL(computer_id)
+
if(!key || !address || !computer_id)
log_adminwarn("Failed Login (invalid data): [key] [address]-[computer_id]")
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.")
@@ -31,6 +38,14 @@ world/IsBanned(key,address,computer_id)
mistakemessage = "\nIf you believe this is a mistake, please request help at [config.banappeals]."
return list("reason"="using Tor", "desc"="\nReason: The network you are using to connect has been banned.[mistakemessage]")
+ //check if the IP address is a known proxy/vpn, and the user is not whitelisted
+ if(check_ipintel && config.ipintel_email && config.ipintel_whitelist && ipintel_is_banned(key, address))
+ log_adminwarn("Failed Login: [key] [computer_id] [address] - Proxy/VPN")
+ var/mistakemessage = ""
+ if(config.banappeals)
+ mistakemessage = "\nIf you have to use one, request whitelisting at: [config.banappeals]"
+ return list("reason"="using proxy or vpn", "desc"="\nReason: Proxies/VPNs are not allowed here. [mistakemessage]")
+
if(config.ban_legacy_system)
//Ban Checking
@@ -93,7 +108,7 @@ world/IsBanned(key,address,computer_id)
var/appealmessage = ""
if(config.banappeals)
appealmessage = " You may appeal it at [config.banappeals]."
- expires = " This is a permanent ban.[appealmessage]"
+ expires = " This ban does not expire automatically and must be appealed.[appealmessage]"
var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]"
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index ce76dc4e282..a6f186dad73 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -21,13 +21,21 @@ var/global/nologevent = 0
to_chat(C, msg)
-/proc/message_adminTicket(var/msg)
- msg = "ADMIN TICKET: [msg]"
+/proc/message_adminTicket(var/msg, var/alt = FALSE)
+ if(alt)
+ msg = "ADMIN TICKET: [msg]"
+ else
+ msg = "ADMIN TICKET: [msg]"
for(var/client/C in GLOB.admins)
if(R_ADMIN & C.holder.rights)
if(C.prefs && !(C.prefs.toggles & CHAT_NO_TICKETLOGS))
to_chat(C, msg)
+/proc/message_mentorTicket(var/msg)
+ for(var/client/C in GLOB.admins)
+ if(check_rights(R_ADMIN | R_MENTOR | R_MOD, 0, C.mob))
+ if(C.prefs && !(C.prefs.toggles & CHAT_NO_MENTORTICKETLOGS))
+ to_chat(C, msg)
/proc/admin_ban_mobsearch(var/mob/M, var/ckey_to_find, var/mob/admin_to_notify)
if(!M || !M.ckey)
@@ -73,7 +81,7 @@ var/global/nologevent = 0
body += "VV - "
body += "[ADMIN_TP(M,"TP")] - "
if(M.client)
- body += "PM - "
+ body += "PM - "
body += "[ADMIN_SM(M,"SM")] - "
if(ishuman(M) && M.mind)
body += "HM -"
@@ -159,7 +167,6 @@ var/global/nologevent = 0
body += "Is an AI "
else if(ishuman(M))
body += {"Make AI |
- Make Mask |
Make Robot |
Make Alien |
Make Slime |
@@ -268,6 +275,15 @@ var/global/nologevent = 0
show_note(key)
+/datum/admins/proc/vpn_whitelist()
+ set category = "Admin"
+ set name = "VPN Ckey Whitelist"
+ if(!check_rights(R_ADMIN))
+ return
+ var/key = stripped_input(usr, "Enter ckey to add/remove, or leave blank to cancel:", "VPN Whitelist add/remove", max_length=32)
+ if(key)
+ vpn_whitelist_panel(key)
+
/datum/admins/proc/access_news_network() //MARKER
set category = "Event"
set name = "Access Newscaster Network"
@@ -316,7 +332,7 @@ var/global/nologevent = 0
if(CHANNEL.is_admin_channel)
dat+="[CHANNEL.channel_name] "
else
- dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()] "
+ dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""] "
dat+={" Refresh Back
"}
@@ -400,7 +416,7 @@ var/global/nologevent = 0
dat+="No feed channels found active... "
else
for(var/datum/feed_channel/CHANNEL in news_network.network_channels)
- dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()] "
+ dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""] "
dat+=" Cancel"
if(11)
dat+={"
@@ -413,7 +429,7 @@ var/global/nologevent = 0
dat+="No feed channels found active... "
else
for(var/datum/feed_channel/CHANNEL in news_network.network_channels)
- dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()] "
+ dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""] "
dat+=" Back"
if(12)
@@ -567,7 +583,7 @@ var/global/nologevent = 0
delay = delay * 10
message_admins("[key_name_admin(usr)] has initiated a server restart with a delay of [delay/10] seconds")
log_admin("[key_name(usr)] has initiated a server restart with a delay of [delay/10] seconds")
- ticker.delay_end = 0
+ SSticker.delay_end = 0
feedback_add_details("admin_verb","R") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
world.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "end_error", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay)
@@ -667,20 +683,26 @@ var/global/nologevent = 0
if(!check_rights(R_SERVER))
return
- if(!ticker)
+ if(!SSticker)
alert("Unable to start the game as it is not set up.")
return
- if(ticker.current_state == GAME_STATE_PREGAME)
- if(alert(usr, "Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
+
+ if(config.start_now_confirmation)
+ if(alert(usr, "This is a live server. Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
return
- ticker.current_state = GAME_STATE_SETTING_UP
- log_admin("[key_name(usr)] has started the game.")
- message_admins("[key_name_admin(usr)] has started the game.")
+
+ if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP)
+ SSticker.force_start = TRUE
+ log_admin("[usr.key] has started the game.")
+ var/msg = ""
+ if(SSticker.current_state == GAME_STATE_STARTUP)
+ msg = " (The server is still setting up, but the round will be started as soon as possible.)"
+ message_admins("[usr.key] has started the game.[msg]")
feedback_add_details("admin_verb","SN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return 1
else
to_chat(usr, "Error: Start Now: Game has already started.")
- return 0
+ return
/datum/admins/proc/toggleenter()
set category = "Server"
@@ -757,10 +779,10 @@ var/global/nologevent = 0
if(!check_rights(R_SERVER))
return
- if(!ticker || ticker.current_state != GAME_STATE_PREGAME)
- ticker.delay_end = !ticker.delay_end
- log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
- message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1)
+ if(!SSticker || SSticker.current_state != GAME_STATE_PREGAME)
+ SSticker.delay_end = !SSticker.delay_end
+ log_admin("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
+ message_admins("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1)
return //alert("Round end delayed", null, null, null, null, null)
going = !( going )
if(!( going ))
@@ -774,32 +796,32 @@ var/global/nologevent = 0
////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS
/proc/is_special_character(mob/M as mob) // returns 1 for specail characters and 2 for heroes of gamemode
- if(!ticker || !ticker.mode)
+ if(!SSticker || !SSticker.mode)
return 0
if(!istype(M))
return 0
- if((M.mind in ticker.mode.head_revolutionaries) || (M.mind in ticker.mode.revolutionaries))
- if(ticker.mode.config_tag == "revolution")
+ if((M.mind in SSticker.mode.head_revolutionaries) || (M.mind in SSticker.mode.revolutionaries))
+ if(SSticker.mode.config_tag == "revolution")
return 2
return 1
- if(M.mind in ticker.mode.cult)
- if(ticker.mode.config_tag == "cult")
+ if(M.mind in SSticker.mode.cult)
+ if(SSticker.mode.config_tag == "cult")
return 2
return 1
- if(M.mind in ticker.mode.syndicates)
- if(ticker.mode.config_tag == "nuclear")
+ if(M.mind in SSticker.mode.syndicates)
+ if(SSticker.mode.config_tag == "nuclear")
return 2
return 1
- if(M.mind in ticker.mode.wizards)
- if(ticker.mode.config_tag == "wizard")
+ if(M.mind in SSticker.mode.wizards)
+ if(SSticker.mode.config_tag == "wizard")
return 2
return 1
- if(M.mind in ticker.mode.changelings)
- if(ticker.mode.config_tag == "changeling")
+ if(M.mind in SSticker.mode.changelings)
+ if(SSticker.mode.config_tag == "changeling")
return 2
return 1
- if(M.mind in ticker.mode.abductors)
- if(ticker.mode.config_tag == "abduction")
+ if(M.mind in SSticker.mode.abductors)
+ if(SSticker.mode.config_tag == "abduction")
return 2
return 1
if(isrobot(M))
@@ -944,9 +966,6 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space
for(var/obj/machinery/mech_bay_recharge_port/P in toArea)
P.update_recharge_turf()
- for(var/obj/machinery/power/apc/A in toArea)
- A.init()
-
if(gamma_ship_location)
gamma_ship_location = 0
else
@@ -1090,7 +1109,7 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space
dat += "
"
- for(var/datum/mind/N in ticker.mode.syndicates)
+ for(var/datum/mind/N in SSticker.mode.syndicates)
var/mob/M = N.current
if(M)
dat += check_antagonists_line(M)
@@ -441,20 +439,20 @@
dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])"
dat += "
"
- for(var/datum/mind/N in ticker.mode.head_revolutionaries)
+ for(var/datum/mind/N in SSticker.mode.head_revolutionaries)
var/mob/M = N.current
if(!M)
dat += "
Head Revolutionary not found!
"
else
dat += check_antagonists_line(M, "(leader)")
- for(var/datum/mind/N in ticker.mode.revolutionaries)
+ for(var/datum/mind/N in SSticker.mode.revolutionaries)
var/mob/M = N.current
if(M)
dat += check_antagonists_line(M)
dat += "
Target(s)
Location
"
- for(var/datum/mind/N in ticker.mode.get_living_heads())
+ for(var/datum/mind/N in SSticker.mode.get_living_heads())
var/mob/M = N.current
if(M)
dat += check_antagonists_line(M)
@@ -465,7 +463,7 @@
dat += "
"
+
+ for(var/message in convo.messages)
+ dat += "
[message]
"
+
+ dat += "
"
+ dat += "
"
+ if(convo.typing)
+ dat += "[current_title] is typing"
+ dat += " "
+ dat += "
"
+ dat += "Reply"
+ dat += "[convo.archived ? "Unarchive" : "Archive"]"
+ if(check_rights(R_ADMIN, FALSE, user))
+ dat += "Ping"
+
+ popup.set_content(dat)
+ popup.open()
+ open = TRUE
+
+/datum/pm_tracker/proc/fancy_title(title)
+ var/client/C = pms[title].client || update_client(title)
+ if(!C)
+ return "[title] (Disconnected)"
+ return "[key_name(C, FALSE)] ([ADMIN_QUE(C.mob,"?")]) ([ADMIN_PP(C.mob,"PP")]) ([ADMIN_VV(C.mob,"VV")]) ([ADMIN_SM(C.mob,"SM")]) ([admin_jump_link(C.mob)]) (CA)"
+
+/datum/pm_tracker/proc/update_client(title)
+ var/client/C = GLOB.directory[ckey(title)]
+ if(C)
+ pms[title].client = C
+ return C
+ return null
+
+/datum/pm_tracker/Topic(href, href_list)
+ if(href_list["archive"])
+ pms[href_list["archive"]].archived = !pms[href_list["archive"]].archived
+ show_ui(usr)
+ return
+
+ if(href_list["refresh"])
+ show_ui(usr)
+ return
+
+ if(href_list["newtitle"])
+ current_title = href_list["newtitle"]
+ show_ui(usr)
+ return
+
+ if(href_list["ping"])
+ var/client/C = pms[href_list["ping"]].client
+ if(C)
+ C.pm_tracker.current_title = usr.key
+ window_flash(C)
+ C.pm_tracker.show_ui(C.mob)
+ to_chat(usr, "Forced open [C]'s messages window.")
+ show_ui(usr)
+ return
+
+ if(href_list["reply"])
+ usr.client.cmd_admin_pm(ckey(href_list["reply"]), null)
+ show_ui(usr)
+ return
+
+ if(href_list["showarchived"])
+ show_archived = !show_archived
+ show_ui(usr)
+ return
+
+ if(href_list["close"])
+ open = FALSE
+ return
diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm
index e3fe5af3263..6f6b3484924 100644
--- a/code/modules/admin/verbs/adminsay.dm
+++ b/code/modules/admin/verbs/adminsay.dm
@@ -17,6 +17,10 @@
feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+/client/proc/get_admin_say()
+ var/msg = input(src, null, "asay \"text\"") as text|null
+ cmd_admin_say(msg)
+
/client/proc/cmd_mentor_say(msg as text)
set category = "Admin"
set name = "Msay"
diff --git a/code/modules/admin/verbs/cinematic.dm b/code/modules/admin/verbs/cinematic.dm
index 3449350e11f..63ebd52d09b 100644
--- a/code/modules/admin/verbs/cinematic.dm
+++ b/code/modules/admin/verbs/cinematic.dm
@@ -3,7 +3,7 @@
set category = "Debug"
set desc = "Shows a cinematic." // Intended for testing but I thought it might be nice for events on the rare occasion Feel free to comment it out if it's not wanted.
set hidden = 1
- if(!ticker)
+ if(!SSticker)
return
switch(cinematic)
if("explosion")
@@ -14,4 +14,4 @@
override = input(src, "mode = ?","Enter Parameter", null) as anything in list("nuclear emergency", "fake", "no override")
if(0)
override = input(src, "mode = ?","Enter Parameter", null) as anything in list("blob", "nuclear emergency", "AI malfunction", "no override")
- ticker.station_explosion_cinematic(parameter, override)
\ No newline at end of file
+ SSticker.station_explosion_cinematic(parameter, override)
\ No newline at end of file
diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm
index 3874e26e9de..e1bbc885c75 100644
--- a/code/modules/admin/verbs/deadsay.dm
+++ b/code/modules/admin/verbs/deadsay.dm
@@ -43,3 +43,7 @@
say_dead_direct("[prefix] says, \"[msg]\"")
feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/get_dead_say()
+ var/msg = input(src, null, "dsay \"text\"") as text
+ dsay(msg)
\ No newline at end of file
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 2b96f7d3290..008eaa4a910 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -68,7 +68,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
target = null
targetselected = 0
- var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
+ var/procname = clean_input("Proc path, eg: /proc/fake_blood","Path:", null)
if(!procname) return
if(targetselected && !hascall(target,procname))
@@ -102,7 +102,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_PROCCALL))
return
- var/procname = input("Proc name, eg: fake_blood","Proc:", null) as text|null
+ var/procname = clean_input("Proc name, eg: fake_blood","Proc:", null)
if(!procname)
return
@@ -149,7 +149,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return null
if("text")
- lst += input("Enter new text:","Text",null) as text
+ lst += clean_input("Enter new text:","Text",null)
if("num")
lst += input("Enter new number:","Num",0) as num
@@ -215,7 +215,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
- if(!ticker)
+ if(!SSticker)
alert("Wait until the game starts")
return
if(istype(M, /mob/living/carbon/human))
@@ -233,7 +233,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
- if(!ticker)
+ if(!SSticker)
alert("Wait until the game starts")
return
@@ -271,7 +271,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return 0
var/obj/item/paicard/card = new(T)
var/mob/living/silicon/pai/pai = new(card)
- var/raw_name = input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text
+ var/raw_name = clean_input("Enter your pAI name:", "pAI Name", "Personal AI", choice)
var/new_name = reject_bad_name(raw_name, 1)
if(new_name)
pai.name = new_name
@@ -293,7 +293,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
- if(!ticker)
+ if(!SSticker)
alert("Wait until the game starts")
return
if(ishuman(M))
@@ -313,7 +313,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
- if(!ticker)
+ if(!SSticker)
alert("Wait until the game starts")
return
if(ishuman(M))
@@ -333,7 +333,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
- if(!ticker)
+ if(!SSticker)
alert("Wait until the game starts")
return
if(ishuman(M))
@@ -405,7 +405,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_EVENT))
return
- if(!ticker)
+ if(!SSticker)
alert("Wait until the game starts")
return
if(istype(M, /mob/living/carbon/human))
@@ -612,7 +612,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/datum/job/jobdatum
if(dresscode == "as job...")
var/jobname = input("Select job", "Robust quick dress shop") as null|anything in get_all_jobs()
- jobdatum = job_master.GetJob(jobname)
+ jobdatum = SSjobs.GetJob(jobname)
feedback_add_details("admin_verb", "SEQ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(dostrip)
@@ -818,7 +818,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
- if(!ticker)
+ if(!SSticker)
alert("Wait until the game starts")
return
if(istype(M, /mob/living/carbon))
@@ -905,8 +905,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_DEBUG))
return
- global.medals_enabled = !global.medals_enabled
+ SSmedals.hub_enabled = !SSmedals.hub_enabled
- message_admins("[key_name_admin(src)] [global.medals_enabled ? "disabled" : "enabled"] the medal hub lockout.")
+ message_admins("[key_name_admin(src)] [SSmedals.hub_enabled ? "disabled" : "enabled"] the medal hub lockout.")
feedback_add_details("admin_verb","TMH") // If...
- log_admin("[key_name(src)] [global.medals_enabled ? "disabled" : "enabled"] the medal hub lockout.")
+ log_admin("[key_name(src)] [SSmedals.hub_enabled ? "disabled" : "enabled"] the medal hub lockout.")
diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index 8b8a2b58a52..23d171e69a0 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -83,9 +83,9 @@
"_default" = "NO_FILTER"
)
var/output = "Radio Report"
- for(var/fq in radio_controller.frequencies)
+ for(var/fq in SSradio.frequencies)
output += "Freq: [fq] "
- var/list/datum/radio_frequency/fqs = radio_controller.frequencies[fq]
+ var/list/datum/radio_frequency/fqs = SSradio.frequencies[fq]
if(!fqs)
output += " ERROR "
continue
@@ -145,7 +145,7 @@
if(!check_rights(R_DEBUG))
return
- var/filter = input("Contains what?","Filter") as text|null
+ var/filter = clean_input("Contains what?","Filter")
if(!filter)
return
@@ -166,7 +166,7 @@
if(!check_rights(R_DEBUG))
return
- var/refstring = input("Which reference?","Ref") as text|null
+ var/refstring = clean_input("Which reference?","Ref")
if(!refstring)
return
diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm
index b21a0c05cc3..209352993a0 100644
--- a/code/modules/admin/verbs/freeze.dm
+++ b/code/modules/admin/verbs/freeze.dm
@@ -28,7 +28,7 @@ var/global/list/frozen_mob_list = list()
/mob/living/proc/admin_Freeze(var/client/admin, skip_overlays = FALSE)
if(istype(admin))
- to_chat(src, "You have been frozen by [key_name(admin)]")
+ to_chat(src, "You have been frozen by [admin]")
message_admins("[key_name_admin(admin)] froze [key_name_admin(src)]")
log_admin("[key_name(admin)] froze [key_name(src)]")
@@ -45,7 +45,7 @@ var/global/list/frozen_mob_list = list()
/mob/living/proc/admin_unFreeze(var/client/admin, skip_overlays = FALSE)
if(istype(admin))
- to_chat(src, "You have been unfrozen by [key_name(admin)]")
+ to_chat(src, "You have been unfrozen by [admin]")
message_admins("[key_name_admin(admin)] unfroze [key_name_admin(src)]")
log_admin("[key_name(admin)] unfroze [key_name(src)]")
diff --git a/code/modules/admin/verbs/gimmick_team.dm b/code/modules/admin/verbs/gimmick_team.dm
index 081c820aaee..cad93e8b880 100644
--- a/code/modules/admin/verbs/gimmick_team.dm
+++ b/code/modules/admin/verbs/gimmick_team.dm
@@ -7,7 +7,7 @@
set desc = "Spawns a group of players in the specified outfit."
if(!check_rights(R_EVENT))
return
- if(!ticker)
+ if(!SSticker)
alert("The game hasn't started yet!")
return
if(alert("Do you want to spawn a Gimmick Team at YOUR CURRENT LOCATION?",,"Yes","No")=="No")
@@ -82,7 +82,7 @@
H.mind.store_memory("[themission]
")
if(is_syndicate)
- ticker.mode.traitors |= H.mind //Adds them to extra antag list
+ SSticker.mode.traitors |= H.mind //Adds them to extra antag list
players_spawned++
if(players_spawned >= teamsize)
diff --git a/code/modules/admin/verbs/honksquad.dm b/code/modules/admin/verbs/honksquad.dm
index b4c0e6a05eb..f4013edbe1e 100644
--- a/code/modules/admin/verbs/honksquad.dm
+++ b/code/modules/admin/verbs/honksquad.dm
@@ -4,7 +4,7 @@ var/const/honksquad_possible = 6 //if more Commandos are needed in the future
var/global/sent_honksquad = 0
/client/proc/honksquad()
- if(!ticker)
+ if(!SSticker)
to_chat(usr, "The game hasn't started yet!")
return
if(world.time < 6000)
@@ -95,7 +95,7 @@ var/global/sent_honksquad = 0
new_honksquad.mind.special_role = SPECIAL_ROLE_HONKSQUAD
new_honksquad.mind.offstation_role = TRUE
new_honksquad.add_language("Clownish")
- ticker.mode.traitors |= new_honksquad.mind//Adds them to current traitor list. Which is really the extra antagonist list.
+ SSticker.mode.traitors |= new_honksquad.mind//Adds them to current traitor list. Which is really the extra antagonist list.
new_honksquad.equip_honksquad(honk_leader_selected)
return new_honksquad
diff --git a/code/modules/admin/verbs/infiltratorteam_syndicate.dm b/code/modules/admin/verbs/infiltratorteam_syndicate.dm
index 551076be62a..a7da1553ec0 100644
--- a/code/modules/admin/verbs/infiltratorteam_syndicate.dm
+++ b/code/modules/admin/verbs/infiltratorteam_syndicate.dm
@@ -10,7 +10,7 @@ var/global/sent_syndicate_infiltration_team = 0
if(!check_rights(R_ADMIN))
to_chat(src, "Only administrators may use this command.")
return
- if(!ticker)
+ if(!SSticker)
alert("The game hasn't started yet!")
return
if(alert("Do you want to send in the Syndicate Infiltration Team?",,"Yes","No")=="No")
@@ -132,7 +132,7 @@ var/global/sent_syndicate_infiltration_team = 0
new_syndicate_infiltrator.mind.assigned_role = "Syndicate Infiltrator"
new_syndicate_infiltrator.mind.special_role = "Syndicate Infiltrator"
new_syndicate_infiltrator.mind.offstation_role = TRUE //they can flee to z2 so make them inelligible as antag targets
- ticker.mode.traitors |= new_syndicate_infiltrator.mind //Adds them to extra antag list
+ SSticker.mode.traitors |= new_syndicate_infiltrator.mind //Adds them to extra antag list
new_syndicate_infiltrator.equip_syndicate_infiltrator(syndicate_leader_selected, uplink_tc, is_mgmt)
return new_syndicate_infiltrator
@@ -170,7 +170,7 @@ var/global/sent_syndicate_infiltration_team = 0
equip_or_collect(new /obj/item/pda(src), slot_in_backpack)
// Other gear
- equip_to_slot_or_del(new /obj/item/clothing/shoes/syndigaloshes(src), slot_shoes)
+ equip_to_slot_or_del(new /obj/item/clothing/shoes/chameleon/noslip(src), slot_shoes)
var/obj/item/card/id/syndicate/W = new(src)
if (flag_mgmt)
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index a87308bb9b1..80a171494ea 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -132,13 +132,13 @@ var/intercom_range_display_status = 0
if(!check_rights(R_DEBUG))
return
- var/level = input("Which z-level?","Level?") as text
+ var/level = clean_input("Which z-level?","Level?")
if(!level) return
var/num_level = text2num(level)
if(!num_level) return
if(!isnum(num_level)) return
- var/type_text = input("Which type path?","Path?") as text
+ var/type_text = clean_input("Which type path?","Path?")
if(!type_text) return
var/type_path = text2path(type_text)
if(!type_path) return
@@ -170,7 +170,7 @@ var/intercom_range_display_status = 0
if(!check_rights(R_DEBUG))
return
- var/type_text = input("Which type path?","") as text
+ var/type_text = clean_input("Which type path?","")
if(!type_text) return
var/type_path = text2path(type_text)
if(!type_path) return
diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm
index 4b3905f37e2..a2a95db957a 100644
--- a/code/modules/admin/verbs/one_click_antag.dm
+++ b/code/modules/admin/verbs/one_click_antag.dm
@@ -29,7 +29,7 @@ client/proc/one_click_antag()
// You pass in ROLE define (optional), the applicant, and the gamemode, and it will return true / false depending on whether the applicant qualify for the candidacy in question
if(jobban_isbanned(M, "Syndicate"))
return FALSE
- if(M.stat || !M.mind || M.mind.special_role)
+ if(M.stat || !M.mind || M.mind.special_role || M.mind.offstation_role)
return FALSE
if(temp)
if((M.mind.assigned_role in temp.restricted_jobs) || (M.client.prefs.species in temp.protected_species))
@@ -175,8 +175,13 @@ client/proc/one_click_antag()
for(var/i = 0, iYou are a Vox Primalis, fresh out of the Shoal. Your ship has arrived at the Tau Ceti system hosting the NSV Exodus... or was it the Luna? NSS? Utopia? Nobody is really sure, but everyong is raring to start pillaging! Your current goal is: [input]")
to_chat(new_vox, "Don't forget to turn on your nitrogen internals!")
diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm
index c2260a051eb..3db8f102320 100644
--- a/code/modules/admin/verbs/onlyone.dm
+++ b/code/modules/admin/verbs/onlyone.dm
@@ -1,5 +1,5 @@
/client/proc/only_one()
- if(!ticker)
+ if(!SSticker)
alert("The game hasn't started yet!")
return
@@ -14,7 +14,7 @@
var/datum/preferences/A = new() // Randomize appearance
A.copy_to(H)
- ticker.mode.traitors += H.mind
+ SSticker.mode.traitors += H.mind
H.mind.special_role = SPECIAL_ROLE_TRAITOR
var/datum/objective/hijack/hijack_objective = new
@@ -58,7 +58,7 @@
world << sound('sound/music/thunderdome.ogg')
/client/proc/only_me()
- if(!ticker)
+ if(!SSticker)
alert("The game hasn't started yet!")
return
@@ -66,7 +66,7 @@
if(H.stat == 2 || !(H.client)) continue
if(is_special_character(H)) continue
- ticker.mode.traitors += H.mind
+ SSticker.mode.traitors += H.mind
H.mind.special_role = "[H.real_name] Prime"
var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone
diff --git a/code/modules/admin/verbs/onlyoneteam.dm b/code/modules/admin/verbs/onlyoneteam.dm
index d2490cdf9c3..846a77c508a 100644
--- a/code/modules/admin/verbs/onlyoneteam.dm
+++ b/code/modules/admin/verbs/onlyoneteam.dm
@@ -1,5 +1,5 @@
/client/proc/only_one_team()
- if(!ticker)
+ if(!SSticker)
alert("The game hasn't started yet!")
return
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index 1c75421f4b7..b6986f4960f 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -18,8 +18,8 @@
var/prayer_type = "PRAYER"
var/deity
if(usr.job == "Chaplain")
- if(ticker && ticker.Bible_deity_name)
- deity = ticker.Bible_deity_name
+ if(SSticker && SSticker.Bible_deity_name)
+ deity = SSticker.Bible_deity_name
cross = image('icons/obj/storage.dmi',"kingyellow")
font_color = "blue"
prayer_type = "CHAPLAIN PRAYER"
@@ -27,7 +27,7 @@
cross = image('icons/obj/storage.dmi',"tome")
font_color = "red"
prayer_type = "CULTIST PRAYER"
- deity = ticker.cultdat.entity_name
+ deity = SSticker.cultdat.entity_name
log_say("(PRAYER) [msg]", usr)
msg = "[bicon(cross)][prayer_type][deity ? " (to [deity])" : ""][mind && mind.isholy ? " (blessings: [mind.num_blessed])" : ""]: [key_name(src, 1)] ([ADMIN_QUE(src,"?")]) ([ADMIN_PP(src,"PP")]) ([ADMIN_VV(src,"VV")]) ([ADMIN_SM(src,"SM")]) ([admin_jump_link(src)]) (CA) ([ADMIN_SC(src,"SC")]) (BLESS) (SMITE): [msg]"
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 24ce21276e7..2c7c6181b1d 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -54,10 +54,13 @@
if(!check_rights(R_SERVER|R_EVENT))
return
- var/msg = input("Message:", text("Subtle PM to [M.key]")) as text
+ var/msg = clean_input("Message:", text("Subtle PM to [M.key]"))
if(!msg)
return
+
+ msg = admin_pencode_to_html(msg)
+
if(usr)
if(usr.client)
if(usr.client.holder)
@@ -109,10 +112,11 @@
if(!check_rights(R_SERVER|R_EVENT))
return
- var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text
+ var/msg = clean_input("Message:", text("Enter the text you wish to appear to everyone:"))
if(!msg)
return
+ msg = pencode_to_html(msg)
to_chat(world, "[msg]")
log_admin("GlobalNarrate: [key_name(usr)] : [msg]")
message_admins("GlobalNarrate: [key_name_admin(usr)]: [msg] ", 1)
@@ -131,10 +135,11 @@
if(!M)
return
- var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text
+ var/msg = clean_input("Message:", text("Enter the text you wish to appear to your target:"))
if( !msg )
return
+ msg = admin_pencode_to_html(msg)
to_chat(M, msg)
log_admin("DirectNarrate: [key_name(usr)] to ([key_name(M)]): [msg]")
@@ -169,7 +174,7 @@
return
message_admins("[key_name_admin(src)] has started answering [key_name_admin(H)]'s [sender] request.")
- var/input = input("Please enter a message to reply to [key_name(H)] via their headset.", "Outgoing message from [sender]", "") as text|null
+ var/input = clean_input("Please enter a message to reply to [key_name(H)] via their headset.", "Outgoing message from [sender]", "")
if(!input)
message_admins("[key_name_admin(src)] decided not to answer [key_name_admin(H)]'s [sender] request.")
return
@@ -435,13 +440,13 @@ Traitors and the like can also be revived with the previous role mostly intact.
//Now for special roles and equipment.
switch(new_character.mind.special_role)
if("traitor")
- job_master.AssignRank(new_character, new_character.mind.assigned_role, 0)
- job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)
- ticker.mode.equip_traitor(new_character)
+ SSjobs.AssignRank(new_character, new_character.mind.assigned_role, 0)
+ SSjobs.EquipRank(new_character, new_character.mind.assigned_role, 1)
+ SSticker.mode.equip_traitor(new_character)
if("Wizard")
new_character.loc = pick(wizardstart)
//ticker.mode.learn_basic_spells(new_character)
- ticker.mode.equip_wizard(new_character)
+ SSticker.mode.equip_wizard(new_character)
if("Syndicate")
var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn")
if(synd_spawn)
@@ -466,8 +471,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
call(/datum/game_mode/proc/add_law_zero)(new_character)
//Add aliens.
else
- job_master.AssignRank(new_character, new_character.mind.assigned_role, 0)
- job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them.
+ SSjobs.AssignRank(new_character, new_character.mind.assigned_role, 0)
+ SSjobs.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them.
//Announces the character on all the systems, based on the record.
if(!issilicon(new_character))//If they are not a cyborg/AI.
@@ -550,7 +555,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_EVENT))
return
- var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null
+ var/input = clean_input("Please enter anything you want the AI to do. Anything. Serious.", "What?", "")
if(!input)
return
@@ -603,9 +608,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/type = input(usr, "Pick a type of report to send", "Report Type", "") as anything in MsgType
if(type == "Custom")
- type = input(usr, "What would you like the report type to be?", "Report Type", "Encrypted Transmission") as text|null
+ type = clean_input("What would you like the report type to be?", "Report Type", "Encrypted Transmission")
- var/customname = input(usr, "Pick a title for the report.", "Title", MsgType[type]) as text|null
+ var/customname = clean_input("Pick a title for the report.", "Title", MsgType[type])
if(!customname)
return
var/input = input(usr, "Please enter anything you want. Anything. Serious.", "What's the message?") as message|null
@@ -651,7 +656,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
feedback_add_details("admin_verb","DEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(isturf(D))
var/turf/T = D
- T.ChangeTurf(/turf/space)
+ T.ChangeTurf(T.baseturf)
else
qdel(D)
@@ -662,11 +667,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_ADMIN))
return
- if(job_master)
+ if(SSjobs)
var/currentpositiontally
var/totalpositiontally
to_chat(src, "Job Name: Filled job slot / Total job slots (Free job slots)")
- for(var/datum/job/job in job_master.occupations)
+ for(var/datum/job/job in SSjobs.occupations)
to_chat(src, "[job.title]: [job.current_positions] / \
[job.total_positions == -1 ? "UNLIMITED" : job.total_positions] \
([job.total_positions == -1 ? "UNLIMITED" : job.total_positions - job.current_positions])")
@@ -858,7 +863,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Admin"
set name = "Toggle Deny Shuttle"
- if(!ticker)
+ if(!SSticker)
return
if(!check_rights(R_ADMIN))
@@ -891,12 +896,12 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_SERVER|R_EVENT))
return
- if(ticker && ticker.mode)
+ if(SSticker && SSticker.mode)
to_chat(usr, "Nope you can't do this, the game's already started. This only works before rounds!")
return
- if(ticker.random_players)
- ticker.random_players = 0
+ if(SSticker.random_players)
+ SSticker.random_players = 0
message_admins("Admin [key_name_admin(usr)] has disabled \"Everyone is Special\" mode.", 1)
to_chat(usr, "Disabled.")
return
@@ -914,7 +919,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
to_chat(usr, "Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet.")
- ticker.random_players = 1
+ SSticker.random_players = 1
feedback_add_details("admin_verb","MER") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_random_events()
@@ -1001,6 +1006,57 @@ Traitors and the like can also be revived with the previous role mostly intact.
msg += "