=0) {
+ elem.className = elem.className.replace('visible','hidden');
+ this.className = this.className.replace('open','closed');
+ this.innerHTML = this.innerHTML.replace('-','+');
+ }
+ else {
+ elem.className = elem.className.replace('hidden','visible');
+ this.className = this.className.replace('closed','open');
+ this.innerHTML = this.innerHTML.replace('+','-');
+ }
+ return false;
+ }
+ })(links\[i\]);
+ }
+ }
}
"}
\ No newline at end of file
diff --git a/code/_onclick/adjacent.dm b/code/_onclick/adjacent.dm
index ddff0b6bd3..9485ea3374 100644
--- a/code/_onclick/adjacent.dm
+++ b/code/_onclick/adjacent.dm
@@ -68,9 +68,10 @@
/atom/movable/Adjacent(var/atom/neighbor)
if(neighbor == loc)
return TRUE
- if(!isturf(loc))
+ var/turf/T = loc
+ if(!istype(T))
return FALSE
- if(loc.Adjacent(neighbor,target = neighbor, mover = src))
+ if(T.Adjacent(neighbor, neighbor, src))
return TRUE
return FALSE
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 58eabbdbcf..e9f50d9212 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -321,8 +321,7 @@
return
/atom/proc/ShiftClick(mob/user)
SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user)
- if(user.client && user.client.eye == user || user.client.eye == user.loc)
- user.examinate(src)
+ user.examinate(src)
return
/*
diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm
index 8ee837a202..b2bc05924c 100644
--- a/code/_onclick/hud/plane_master.dm
+++ b/code/_onclick/hud/plane_master.dm
@@ -16,6 +16,28 @@
//Trust me, you need one. Period. If you don't think you do, you're doing something extremely wrong.
/obj/screen/plane_master/proc/backdrop(mob/mymob)
+/obj/screen/plane_master/openspace
+ name = "open space plane master"
+ plane = FLOOR_OPENSPACE_PLANE
+ appearance_flags = PLANE_MASTER
+ blend_mode = BLEND_MULTIPLY
+ alpha = 255
+
+/obj/screen/plane_master/openspace/backdrop(mob/mymob)
+ filters = list()
+ filters += filter(type = "drop_shadow", color = "#04080FAA", size = -10)
+ filters += filter(type = "drop_shadow", color = "#04080FAA", size = -15)
+ filters += filter(type = "drop_shadow", color = "#04080FAA", size = -20)
+
+/obj/screen/plane_master/proc/outline(_size, _color)
+ filters += filter(type = "outline", size = _size, color = _color)
+
+/obj/screen/plane_master/proc/shadow(_size, _offset = 0, _x = 0, _y = 0, _color = "#04080FAA")
+ filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset)
+
+/obj/screen/plane_master/proc/clear_filters()
+ filters = list()
+
/obj/screen/plane_master/floor
name = "floor plane master"
plane = FLOOR_PLANE
diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm
index ea2919f342..a5d27819b8 100644
--- a/code/controllers/configuration/configuration.dm
+++ b/code/controllers/configuration/configuration.dm
@@ -34,7 +34,7 @@
if(_directory)
directory = _directory
if(entries)
- CRASH("[THIS_PROC_TYPE_WEIRD] called more than once!")
+ CRASH("/datum/controller/configuration/Load() called more than once!")
InitEntries()
LoadModes()
if(fexists("[directory]/config.txt") && LoadEntries("config.txt") <= 1)
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index 36b57a4b7c..ed3cca587d 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -139,6 +139,14 @@
min_val = 0
max_val = 1
+/datum/config_entry/number/suicide_reenter_round_timer
+ config_entry_value = 30
+ min_val = 0
+
+/datum/config_entry/number/roundstart_suicide_time_limit
+ config_entry_value = 30
+ min_val = 0
+
/datum/config_entry/number/shuttle_refuel_delay
config_entry_value = 12000
min_val = 0
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index aab71fd015..a412ad2f48 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -141,6 +141,11 @@
/datum/config_entry/flag/load_legacy_ranks_only //Loads admin ranks only from legacy admin_ranks.txt, while enabled ranks are mirrored to the database
protection = CONFIG_ENTRY_LOCKED
+/datum/config_entry/flag/mentors_mobname_only
+
+/datum/config_entry/flag/mentor_legacy_system //Defines whether the server uses the legacy mentor system with mentors.txt or the SQL system
+ protection = CONFIG_ENTRY_LOCKED
+
/datum/config_entry/string/hostedby
/datum/config_entry/flag/norespawn
diff --git a/code/controllers/subsystem/adjacent_air.dm b/code/controllers/subsystem/adjacent_air.dm
new file mode 100644
index 0000000000..8395eda708
--- /dev/null
+++ b/code/controllers/subsystem/adjacent_air.dm
@@ -0,0 +1,35 @@
+SUBSYSTEM_DEF(adjacent_air)
+ name = "Atmos Adjacency"
+ flags = SS_BACKGROUND
+ runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ wait = 10
+ priority = FIRE_PRIORITY_ATMOS_ADJACENCY
+ var/list/queue = list()
+
+/datum/controller/subsystem/adjacent_air/stat_entry()
+#ifdef TESTING
+ ..("P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]")
+#else
+ ..("P:[length(queue)]")
+#endif
+
+/datum/controller/subsystem/adjacent_air/Initialize()
+ while(length(queue))
+ fire(mc_check = FALSE)
+ return ..()
+
+/datum/controller/subsystem/adjacent_air/fire(resumed = FALSE, mc_check = TRUE)
+
+ var/list/queue = src.queue
+
+ while (length(queue))
+ var/turf/currT = queue[1]
+ queue.Cut(1,2)
+
+ currT.ImmediateCalculateAdjacentTurfs()
+
+ if(mc_check)
+ if(MC_TICK_CHECK)
+ break
+ else
+ CHECK_TICK
\ No newline at end of file
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index efa6b8b59d..af7ae825f4 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -658,6 +658,46 @@ SUBSYSTEM_DEF(job)
message_admins(msg)
CRASH(msg)
+/datum/controller/subsystem/job/proc/equip_loadout(mob/dead/new_player/N, mob/living/M, equipbackpackstuff)
+ var/mob/the_mob = N
+ if(!the_mob)
+ the_mob = M // cause this doesn't get assigned if player is a latejoiner
+ if(the_mob.client && the_mob.client.prefs && (the_mob.client.prefs.chosen_gear && the_mob.client.prefs.chosen_gear.len))
+ if(!ishuman(M))//no silicons allowed
+ return
+ for(var/i in the_mob.client.prefs.chosen_gear)
+ var/datum/gear/G = i
+ G = GLOB.loadout_items[slot_to_string(initial(G.category))][initial(G.name)]
+ if(!G)
+ continue
+ var/permitted = TRUE
+ if(G.restricted_roles && G.restricted_roles.len && !(M.mind.assigned_role in G.restricted_roles))
+ permitted = FALSE
+ if(G.donoritem && !G.donator_ckey_check(the_mob.client.ckey))
+ permitted = FALSE
+ if(!equipbackpackstuff && G.category == SLOT_IN_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs
+ permitted = FALSE
+ if(equipbackpackstuff && G.category != SLOT_IN_BACKPACK)//ditto
+ permitted = FALSE
+ if(!permitted)
+ continue
+ var/obj/item/I = new G.path
+ if(!M.equip_to_slot_if_possible(I, G.category, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // If the job's dresscode compliant, try to put it in its slot, first
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ var/obj/item/storage/backpack/B = C.back
+ if(!B || !SEND_SIGNAL(B, COMSIG_TRY_STORAGE_INSERT, I, null, TRUE, TRUE)) // Otherwise, try to put it in the backpack, for carbons.
+ I.forceMove(get_turf(C))
+ else if(!M.equip_to_slot_if_possible(I, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // Otherwise, try to put it in the backpack
+ I.forceMove(get_turf(M)) // If everything fails, just put it on the floor under the mob.
+
+/datum/controller/subsystem/job/proc/FreeRole(rank)
+ if(!rank)
+ return
+ var/datum/job/job = GetJob(rank)
+ if(!job)
+ return FALSE
+ job.current_positions = max(0, job.current_positions - 1)
///////////////////////////////////
//Keeps track of all living heads//
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index dec6cf8466..ceb2fae998 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -14,6 +14,7 @@ SUBSYSTEM_DEF(mapping)
var/list/ruins_templates = list()
var/list/space_ruins_templates = list()
var/list/lava_ruins_templates = list()
+ var/datum/space_level/isolated_ruins_z //Created on demand during ruin loading.
var/list/shuttle_templates = list()
var/list/shelter_templates = list()
@@ -25,6 +26,7 @@ SUBSYSTEM_DEF(mapping)
var/list/datum/turf_reservations //list of turf reservations
var/list/used_turfs = list() //list of turf = datum/turf_reservation
+ var/list/reservation_ready = list()
var/clearing_reserved_turfs = FALSE
// Z-manager stuff
@@ -95,7 +97,7 @@ SUBSYSTEM_DEF(mapping)
// Set up Z-level transitions.
setup_map_transitions()
generate_station_area_list()
- initialize_reserved_level()
+ initialize_reserved_level(transit.z_value)
return ..()
/* Nuke threats, for making the blue tiles on the station go RED
@@ -442,7 +444,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
GLOB.the_gateway.wait = world.time
/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override, border_type_override)
- UNTIL(initialized && !clearing_reserved_turfs)
+ UNTIL(reservation_ready["[z]"] && !clearing_reserved_turfs)
var/datum/turf_reservation/reserve = new type
if(turf_type_override)
reserve.turf_type = turf_type_override
@@ -454,8 +456,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
return reserve
//If we didn't return at this point, theres a good chance we ran out of room on the exisiting reserved z levels, so lets try a new one
num_of_res_levels += 1
- var/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
- if(reserve.Reserve(width, height, newReserved))
+ var/datum/space_level/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
+ initialize_reserved_level(newReserved.z_value)
+ if(reserve.Reserve(width, height, newReserved.z_value))
return reserve
else
if(!level_trait(z, ZTRAIT_RESERVED))
@@ -467,19 +470,22 @@ GLOBAL_LIST_EMPTY(the_station_areas)
QDEL_NULL(reserve)
//This is not for wiping reserved levels, use wipe_reservations() for that.
-/datum/controller/subsystem/mapping/proc/initialize_reserved_level()
+/datum/controller/subsystem/mapping/proc/initialize_reserved_level(z)
UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case.
clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it.
- for(var/i in levels_by_trait(ZTRAIT_RESERVED))
- var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,i))
- var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,i))
- var/block = block(A, B)
- for(var/t in block)
- // No need to empty() these, because it's world init and they're
- // already /turf/open/space/basic.
- var/turf/T = t
- T.flags_1 |= UNUSED_RESERVATION_TURF_1
- unused_turfs["[i]"] = block
+ if(!level_trait(z,ZTRAIT_RESERVED))
+ clearing_reserved_turfs = FALSE
+ CRASH("Invalid z level prepared for reservations.")
+ var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z))
+ var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z))
+ var/block = block(A, B)
+ for(var/t in block)
+ // No need to empty() these, because it's world init and they're
+ // already /turf/open/space/basic.
+ var/turf/T = t
+ T.flags_1 |= UNUSED_RESERVATION_TURF_1
+ unused_turfs["[z]"] = block
+ reservation_ready["[z]"] = TRUE
clearing_reserved_turfs = FALSE
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
@@ -513,3 +519,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
for(var/B in areas)
var/area/A = B
A.reg_in_areas_in_z()
+
+/datum/controller/subsystem/mapping/proc/get_isolated_ruin_z()
+ if(!isolated_ruins_z)
+ isolated_ruins_z = add_new_zlevel("Isolated Ruins/Reserved", list(ZTRAIT_RESERVED = TRUE, ZTRAIT_ISOLATED_RUINS = TRUE))
+ initialize_reserved_level(isolated_ruins_z.z_value)
+ return isolated_ruins_z.z_value
\ No newline at end of file
diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm
index 2e2f7edd99..18667053d4 100644
--- a/code/controllers/subsystem/pai.dm
+++ b/code/controllers/subsystem/pai.dm
@@ -69,6 +69,10 @@ SUBSYSTEM_DEF(pai)
candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN)
if("submit")
+ if(isobserver(usr))
+ var/mob/dead/observer/O = usr
+ if(!O.can_reenter_round())
+ return FALSE
if(candidate)
candidate.ready = 1
for(var/obj/item/paicard/p in pai_card_list)
@@ -148,6 +152,8 @@ SUBSYSTEM_DEF(pai)
continue
if(!(ROLE_PAI in G.client.prefs.be_special))
continue
+ if(!G.can_reenter_round()) // this should use notify_ghosts() instead one day.
+ return FALSE
to_chat(G, "[user] is requesting a pAI personality! Use the pAI button to submit yourself as one.")
addtimer(CALLBACK(src, .proc/spam_again), spam_delay)
var/list/available = list()
diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm
index 05c76619d9..ab27658efd 100644
--- a/code/controllers/subsystem/research.dm
+++ b/code/controllers/subsystem/research.dm
@@ -4,24 +4,32 @@ SUBSYSTEM_DEF(research)
priority = FIRE_PRIORITY_RESEARCH
wait = 10
init_order = INIT_ORDER_RESEARCH
+ //TECHWEB STATIC
+ var/list/techweb_nodes = list() //associative id = node datum
+ var/list/techweb_designs = list() //associative id = node datum
+ var/list/datum/techweb/techwebs = list()
+ var/datum/techweb/science/science_tech
+ var/datum/techweb/admin/admin_tech
+ var/datum/techweb_node/error_node/error_node //These two are what you get if a node/design is deleted and somehow still stored in a console.
+ var/datum/design/error_design/error_design
+
+ //ERROR LOGGING
var/list/invalid_design_ids = list() //associative id = number of times
var/list/invalid_node_ids = list() //associative id = number of times
var/list/invalid_node_boost = list() //associative id = error message
+
var/list/obj/machinery/rnd/server/servers = list()
- var/datum/techweb/science/science_tech
- var/datum/techweb/admin/admin_tech
- var/list/techweb_nodes = list() //associative id = node datum
- var/list/techweb_categories = list() //category name = list(node.id = node)
- var/list/techweb_designs = list() //associative id = node datum
- var/list/techweb_nodes_starting = list() //associative id = node datum
+
+ var/list/techweb_nodes_starting = list() //associative id = TRUE
+ var/list/techweb_categories = list() //category name = list(node.id = TRUE)
var/list/techweb_boost_items = list() //associative double-layer path = list(id = list(point_type = point_discount))
- var/list/techweb_nodes_hidden = list() //Nodes that should be hidden by default.
+ var/list/techweb_nodes_hidden = list() //Node ids that should be hidden by default.
var/list/techweb_point_items = list( //path = list(point type = value)
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 2500),
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 5000), // Cit three more anomalys anomalys
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 7500),
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000),
- // - Slime Extracts! -
+ // - Slime Extracts! -
/obj/item/slime_extract/grey = list(TECHWEB_POINT_TYPE_GENERIC = 500), // Adds in slime core deconing
/obj/item/slime_extract/metal = list(TECHWEB_POINT_TYPE_GENERIC = 750),
/obj/item/slime_extract/purple = list(TECHWEB_POINT_TYPE_GENERIC = 750),
@@ -294,6 +302,8 @@ SUBSYSTEM_DEF(research)
science_tech = new /datum/techweb/science
admin_tech = new /datum/techweb/admin
autosort_categories()
+ error_design = new
+ error_node = new
return ..()
/datum/controller/subsystem/research/fire()
@@ -330,6 +340,191 @@ SUBSYSTEM_DEF(research)
for(var/i in techweb_nodes)
var/datum/techweb_node/I = techweb_nodes[i]
if(techweb_categories[I.category])
- techweb_categories[I.category][I.id] = I
+ techweb_categories[I.category][I.id] = TRUE
else
- techweb_categories[I.category] = list(I.id = I)
+ techweb_categories[I.category] = list(I.id = TRUE)
+
+/datum/controller/subsystem/research/proc/techweb_node_by_id(id)
+ return techweb_nodes[id] || error_node
+
+/datum/controller/subsystem/research/proc/techweb_design_by_id(id)
+ return techweb_designs[id] || error_design
+
+/datum/controller/subsystem/research/proc/on_design_deletion(datum/design/D)
+ for(var/i in techweb_nodes)
+ var/datum/techweb_node/TN = techwebs[i]
+ TN.on_design_deletion(TN)
+ for(var/i in techwebs)
+ var/datum/techweb/T = i
+ T.recalculate_nodes(TRUE)
+
+/datum/controller/subsystem/research/proc/on_node_deletion(datum/techweb_node/TN)
+ for(var/i in techweb_nodes)
+ var/datum/techweb_node/TN2 = techwebs[i]
+ TN2.on_node_deletion(TN)
+ for(var/i in techwebs)
+ var/datum/techweb/T = i
+ T.recalculate_nodes(TRUE)
+
+/datum/controller/subsystem/research/proc/initialize_all_techweb_nodes(clearall = FALSE)
+ if(islist(techweb_nodes) && clearall)
+ QDEL_LIST(techweb_nodes)
+ if(islist(techweb_nodes_starting && clearall))
+ techweb_nodes_starting.Cut()
+ var/list/returned = list()
+ for(var/path in subtypesof(/datum/techweb_node))
+ var/datum/techweb_node/TN = path
+ if(isnull(initial(TN.id)))
+ continue
+ TN = new path
+ if(returned[initial(TN.id)])
+ stack_trace("WARNING: Techweb node ID clash with ID [initial(TN.id)] detected! Path: [path]")
+ errored_datums[TN] = initial(TN.id)
+ continue
+ returned[initial(TN.id)] = TN
+ if(TN.starting_node)
+ techweb_nodes_starting[TN.id] = TRUE
+ for(var/id in techweb_nodes)
+ var/datum/techweb_node/TN = techweb_nodes[id]
+ TN.Initialize()
+ techweb_nodes = returned
+ if (!verify_techweb_nodes()) //Verify all nodes have ids and such.
+ stack_trace("Invalid techweb nodes detected")
+ calculate_techweb_nodes()
+ calculate_techweb_boost_list()
+ if (!verify_techweb_nodes()) //Verify nodes and designs have been crosslinked properly.
+ CRASH("Invalid techweb nodes detected")
+
+/datum/controller/subsystem/research/proc/initialize_all_techweb_designs(clearall = FALSE)
+ if(islist(techweb_designs) && clearall)
+ QDEL_LIST(techweb_designs)
+ var/list/returned = list()
+ for(var/path in subtypesof(/datum/design))
+ var/datum/design/DN = path
+ if(isnull(initial(DN.id)))
+ stack_trace("WARNING: Design with null ID detected. Build path: [initial(DN.build_path)]")
+ continue
+ else if(initial(DN.id) == DESIGN_ID_IGNORE)
+ continue
+ DN = new path
+ if(returned[initial(DN.id)])
+ stack_trace("WARNING: Design ID clash with ID [initial(DN.id)] detected! Path: [path]")
+ errored_datums[DN] = initial(DN.id)
+ continue
+ returned[initial(DN.id)] = DN
+ techweb_designs = returned
+ verify_techweb_designs()
+
+/datum/controller/subsystem/research/proc/verify_techweb_nodes()
+ . = TRUE
+ for(var/n in techweb_nodes)
+ var/datum/techweb_node/N = techweb_nodes[n]
+ if(!istype(N))
+ WARNING("Invalid research node with ID [n] detected and removed.")
+ techweb_nodes -= n
+ research_node_id_error(n)
+ . = FALSE
+ for(var/p in N.prereq_ids)
+ var/datum/techweb_node/P = techweb_nodes[p]
+ if(!istype(P))
+ WARNING("Invalid research prerequisite node with ID [p] detected in node [N.display_name]\[[N.id]\] removed.")
+ N.prereq_ids -= p
+ research_node_id_error(p)
+ . = FALSE
+ for(var/d in N.design_ids)
+ var/datum/design/D = techweb_designs[d]
+ if(!istype(D))
+ WARNING("Invalid research design with ID [d] detected in node [N.display_name]\[[N.id]\] removed.")
+ N.design_ids -= d
+ design_id_error(d)
+ . = FALSE
+ for(var/u in N.unlock_ids)
+ var/datum/techweb_node/U = techweb_nodes[u]
+ if(!istype(U))
+ WARNING("Invalid research unlock node with ID [u] detected in node [N.display_name]\[[N.id]\] removed.")
+ N.unlock_ids -= u
+ research_node_id_error(u)
+ . = FALSE
+ for(var/p in N.boost_item_paths)
+ if(!ispath(p))
+ N.boost_item_paths -= p
+ WARNING("[p] is not a valid path.")
+ node_boost_error(N.id, "[p] is not a valid path.")
+ . = FALSE
+ var/list/points = N.boost_item_paths[p]
+ if(islist(points))
+ for(var/i in points)
+ if(!isnum(points[i]))
+ WARNING("[points[i]] is not a valid number.")
+ node_boost_error(N.id, "[points[i]] is not a valid number.")
+ . = FALSE
+ else if(!point_types[i])
+ WARNING("[i] is not a valid point type.")
+ node_boost_error(N.id, "[i] is not a valid point type.")
+ . = FALSE
+ else if(!isnull(points))
+ N.boost_item_paths -= p
+ node_boost_error(N.id, "No valid list.")
+ WARNING("No valid list.")
+ . = FALSE
+ CHECK_TICK
+
+/datum/controller/subsystem/research/proc/verify_techweb_designs()
+ for(var/d in techweb_designs)
+ var/datum/design/D = techweb_designs[d]
+ if(!istype(D))
+ stack_trace("WARNING: Invalid research design with ID [d] detected and removed.")
+ techweb_designs -= d
+ CHECK_TICK
+
+/datum/controller/subsystem/research/proc/research_node_id_error(id)
+ if(invalid_node_ids[id])
+ invalid_node_ids[id]++
+ else
+ invalid_node_ids[id] = 1
+
+/datum/controller/subsystem/research/proc/design_id_error(id)
+ if(invalid_design_ids[id])
+ invalid_design_ids[id]++
+ else
+ invalid_design_ids[id] = 1
+
+/datum/controller/subsystem/research/proc/calculate_techweb_nodes()
+ for(var/design_id in techweb_designs)
+ var/datum/design/D = techweb_designs[design_id]
+ D.unlocked_by.Cut()
+ for(var/node_id in techweb_nodes)
+ var/datum/techweb_node/node = techweb_nodes[node_id]
+ node.unlock_ids = list()
+ for(var/i in node.design_ids)
+ var/datum/design/D = techweb_designs[i]
+ node.design_ids[i] = TRUE
+ D.unlocked_by += node.id
+ if(node.hidden)
+ techweb_nodes_hidden[node.id] = TRUE
+ CHECK_TICK
+ generate_techweb_unlock_linking()
+
+/datum/controller/subsystem/research/proc/generate_techweb_unlock_linking()
+ for(var/node_id in techweb_nodes) //Clear all unlock links to avoid duplication.
+ var/datum/techweb_node/node = techweb_nodes[node_id]
+ node.unlock_ids = list()
+ for(var/node_id in techweb_nodes)
+ var/datum/techweb_node/node = techweb_nodes[node_id]
+ for(var/prereq_id in node.prereq_ids)
+ var/datum/techweb_node/prereq_node = techweb_node_by_id(prereq_id)
+ prereq_node.unlock_ids[node.id] = node
+
+/datum/controller/subsystem/research/proc/calculate_techweb_boost_list(clearall = FALSE)
+ if(clearall)
+ techweb_boost_items = list()
+ for(var/node_id in techweb_nodes)
+ var/datum/techweb_node/node = techweb_nodes[node_id]
+ for(var/path in node.boost_item_paths)
+ if(!ispath(path))
+ continue
+ if(length(techweb_boost_items[path]))
+ techweb_boost_items[path][node.id] = node.boost_item_paths[path]
+ else
+ techweb_boost_items[path] = list(node.id = node.boost_item_paths[path])
+ CHECK_TICK
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index 51a2761f74..fe40b3f01f 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -638,3 +638,11 @@ SUBSYSTEM_DEF(shuttle)
C.update_hidden_docking_ports(remove_images, add_images)
QDEL_LIST(remove_images)
+
+/datum/controller/subsystem/shuttle/proc/autoEnd() //CIT CHANGE - allows shift to end after 2 hours have passed.
+ if((world.realtime - SSshuttle.realtimeofstart) > auto_call && EMERGENCY_IDLE_OR_RECALLED) //2 hours
+ SSshuttle.emergency.request(silent = TRUE)
+ priority_announce("The shift has come to an end and the shuttle called. [seclevel2num(get_security_level()) == SEC_LEVEL_RED ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [emergency.timeLeft(600)] minutes.", null, "shuttlecalled", "Priority")
+ log_game("Round time limit reached. Shuttle has been auto-called.")
+ message_admins("Round time limit reached. Shuttle called.")
+ emergencyNoRecall = TRUE
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index 4b91944ec8..48da15f67e 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -147,6 +147,11 @@ SUBSYSTEM_DEF(throwing)
if (callback)
callback.Invoke()
+ if(!thrownthing.zfalling) // I don't think you can zfall while thrown but hey, just in case.
+ var/turf/T = get_turf(thrownthing)
+ if(T && thrownthing.has_gravity(T))
+ T.zFall(thrownthing)
+
qdel(src)
/datum/thrownthing/proc/hit_atom(atom/A)
diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm
index ee1f5b8c3d..33798d74f7 100644
--- a/code/controllers/subsystem/traumas.dm
+++ b/code/controllers/subsystem/traumas.dm
@@ -40,7 +40,7 @@ SUBSYSTEM_DEF(traumas)
"cats" = strings(PHOBIA_FILE, "cats"),
"syndicate"= strings(PHOBIA_FILE, "syndicate"),
"eye" = strings(PHOBIA_FILE, "eye")
- )
+ )
phobia_mobs = list("spiders" = typecacheof(list(/mob/living/simple_animal/hostile/poison/giant_spider)),
"security" = typecacheof(list(/mob/living/simple_animal/bot/secbot, /mob/living/simple_animal/bot/ed209)),
@@ -166,7 +166,7 @@ SUBSYSTEM_DEF(traumas)
"syndicate" = typecacheof(list(/obj/item/stack/tile/mineral/plastitanium, /obj/machinery/computer/shuttle/syndicate, /obj/machinery/computer/shuttle/syndicate/recall, /obj/machinery/computer/shuttle/syndicate/drop_pod, /obj/machinery/computer/camera_advanced/shuttle_docker/syndicate, /obj/machinery/recharge_station,
/obj/machinery/porta_turret/syndicate, /obj/structure/closet/syndicate, /obj/machinery/suit_storage_unit/syndicate, /obj/item/clothing/under/syndicate, /obj/item/folder/syndicate, /obj/item/documents/syndicate, /obj/item/clothing/glasses/phantomthief/syndicate, /obj/item/antag_spawner/nuke_ops, /obj/item/storage/box/syndicate,
- /obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver/syndie,
+ /obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver,
/obj/item/gun/ballistic/automatic/shotgun/bulldog, /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/automatic/m90, /obj/item/gun/ballistic/automatic/l6_saw, /obj/item/storage/belt/grenade/full, /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate, /obj/item/gun/energy/kinetic_accelerator/crossbow,
/obj/item/melee/transforming/energy/sword/saber, /obj/item/twohanded/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm,
/obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/mecha/combat/gygax/dark, /obj/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index 2391b4c839..5e44f2e4c3 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -74,10 +74,10 @@ SUBSYSTEM_DEF(weather)
next_hit_by_zlevel["[z]"] = null
/datum/controller/subsystem/weather/proc/get_weather(z, area/active_area)
- var/datum/weather/A
- for(var/V in processing)
- var/datum/weather/W = V
- if((z in W.impacted_z_levels) && W.area_type == active_area.type)
- A = W
- break
- return A
+ var/datum/weather/A
+ for(var/V in processing)
+ var/datum/weather/W = V
+ if((z in W.impacted_z_levels) && W.area_type == active_area.type)
+ A = W
+ break
+ return A
diff --git a/code/datums/armor.dm b/code/datums/armor.dm
index cbf4b76c60..85915395f8 100644
--- a/code/datums/armor.dm
+++ b/code/datums/armor.dm
@@ -1,70 +1,70 @@
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]"
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
- . = locate(ARMORID)
- if (!.)
- . = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
+ . = locate(ARMORID)
+ if (!.)
+ . = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
/datum/armor
- datum_flags = DF_USE_TAG
- var/melee
- var/bullet
- var/laser
- var/energy
- var/bomb
- var/bio
- var/rad
- var/fire
- var/acid
- var/magic
+ datum_flags = DF_USE_TAG
+ var/melee
+ var/bullet
+ var/laser
+ var/energy
+ var/bomb
+ var/bio
+ var/rad
+ var/fire
+ var/acid
+ var/magic
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
- src.melee = melee
- src.bullet = bullet
- src.laser = laser
- src.energy = energy
- src.bomb = bomb
- src.bio = bio
- src.rad = rad
- src.fire = fire
- src.acid = acid
- src.magic = magic
- tag = ARMORID
+ src.melee = melee
+ src.bullet = bullet
+ src.laser = laser
+ src.energy = energy
+ src.bomb = bomb
+ src.bio = bio
+ src.rad = rad
+ src.fire = fire
+ src.acid = acid
+ src.magic = magic
+ tag = ARMORID
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
- return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic)
+ return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic)
/datum/armor/proc/modifyAllRatings(modifier = 0)
- return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier)
+ return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier)
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
- return getArmor((isnull(melee) ? src.melee : melee),\
- (isnull(bullet) ? src.bullet : bullet),\
- (isnull(laser) ? src.laser : laser),\
- (isnull(energy) ? src.energy : energy),\
- (isnull(bomb) ? src.bomb : bomb),\
- (isnull(bio) ? src.bio : bio),\
- (isnull(rad) ? src.rad : rad),\
- (isnull(fire) ? src.fire : fire),\
- (isnull(acid) ? src.acid : acid),\
- (isnull(magic) ? src.magic : magic))
+ return getArmor((isnull(melee) ? src.melee : melee),\
+ (isnull(bullet) ? src.bullet : bullet),\
+ (isnull(laser) ? src.laser : laser),\
+ (isnull(energy) ? src.energy : energy),\
+ (isnull(bomb) ? src.bomb : bomb),\
+ (isnull(bio) ? src.bio : bio),\
+ (isnull(rad) ? src.rad : rad),\
+ (isnull(fire) ? src.fire : fire),\
+ (isnull(acid) ? src.acid : acid),\
+ (isnull(magic) ? src.magic : magic))
/datum/armor/proc/getRating(rating)
- return vars[rating]
+ return vars[rating]
/datum/armor/proc/getList()
- return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
+ return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
/datum/armor/proc/attachArmor(datum/armor/AA)
- return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic)
+ return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic)
/datum/armor/proc/detachArmor(datum/armor/AA)
- return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic)
+ return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic)
/datum/armor/vv_edit_var(var_name, var_value)
- if (var_name == NAMEOF(src, tag))
- return FALSE
- . = ..()
- tag = ARMORID // update tag in case armor values were edited
+ if (var_name == NAMEOF(src, tag))
+ return FALSE
+ . = ..()
+ tag = ARMORID // update tag in case armor values were edited
#undef ARMORID
diff --git a/code/datums/browser.dm b/code/datums/browser.dm
index 4c501a3e7f..60434d2766 100644
--- a/code/datums/browser.dm
+++ b/code/datums/browser.dm
@@ -194,7 +194,7 @@
.=..()
opentime = 0
-/datum/browser/modal/open()
+/datum/browser/modal/open(use_onclose = 1)
set waitfor = 0
opentime = world.time
diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm
index 8c6013aeab..b46919a6c6 100644
--- a/code/datums/components/mood.dm
+++ b/code/datums/components/mood.dm
@@ -8,7 +8,7 @@
var/mood_level = 5 //To track what stage of moodies they're on
var/sanity_level = 5 //To track what stage of sanity they're on
var/mood_modifier = 1 //Modifier to allow certain mobs to be less affected by moodlets
- var/datum/mood_event/list/mood_events = list()
+ var/list/datum/mood_event/mood_events = list()
var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much?
var/obj/screen/mood/screen_obj
@@ -125,6 +125,9 @@
screen_obj.icon_state = "mood[mood_level]"
/datum/component/mood/process() //Called on SSmood process
+ if(QDELETED(parent)) // workaround to an obnoxious sneaky periodical runtime.
+ qdel(src)
+ return
var/mob/living/owner = parent
switch(mood_level)
@@ -249,7 +252,7 @@
RegisterSignal(screen_obj, COMSIG_CLICK, .proc/hud_click)
/datum/component/mood/proc/unmodify_hud(datum/source)
- if(!screen_obj)
+ if(!screen_obj || !parent)
return
var/mob/living/owner = parent
var/datum/hud/hud = owner.hud_used
diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm
index dcdbd5ca4b..c05b07a693 100644
--- a/code/datums/components/riding.dm
+++ b/code/datums/components/riding.dm
@@ -310,10 +310,10 @@
if(!user.put_in_hands(inhand, TRUE))
qdel(inhand) // it isn't going to be added to offhands anyway
break
- LAZYADD(equipped, src)
+ LAZYADD(equipped, inhand)
var/amount_equipped = LAZYLEN(equipped)
if(amount_equipped)
- LAZYADD(offhands[L], amount_equipped)
+ LAZYADD(offhands[L], equipped)
if(amount_equipped >= amount_required)
return TRUE
unequip_buckle_inhands(L)
diff --git a/code/datums/components/storage/concrete/special.dm b/code/datums/components/storage/concrete/special.dm
index 556e9e9fc9..9f2c435642 100644
--- a/code/datums/components/storage/concrete/special.dm
+++ b/code/datums/components/storage/concrete/special.dm
@@ -1,5 +1,5 @@
-/datum/component/storage/concrete/secret_satchel/can_be_inserted(I,msg,user)
+/datum/component/storage/concrete/secret_satchel/can_be_inserted(obj/item/I, stop_messages = FALSE, mob/M)
if(SSpersistence.spawned_objects[I])
- to_chat(user, "[I] is unstable after its journey through space and time, it wouldn't survive another trip.")
+ to_chat(M, "[I] is unstable after its journey through space and time, it wouldn't survive another trip.")
return FALSE
return ..()
diff --git a/code/datums/components/waddling.dm b/code/datums/components/waddling.dm
index a1f538e4dd..f09a92c91c 100644
--- a/code/datums/components/waddling.dm
+++ b/code/datums/components/waddling.dm
@@ -1,15 +1,15 @@
/datum/component/waddling
- dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
/datum/component/waddling/Initialize()
- if(!isliving(parent))
- return COMPONENT_INCOMPATIBLE
- RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle)
+ 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)
+ 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/components/wet_floor.dm b/code/datums/components/wet_floor.dm
index 84b0320375..38b17993d8 100644
--- a/code/datums/components/wet_floor.dm
+++ b/code/datums/components/wet_floor.dm
@@ -88,6 +88,9 @@
if(TURF_WET_PERMAFROST)
intensity = 120
lube_flags = SLIDE_ICE | GALOSHES_DONT_HELP
+ if(TURF_WET_SUPERLUBE)
+ intensity = 120
+ lube_flags = SLIDE | GALOSHES_DONT_HELP | SLIP_WHEN_CRAWLING
else
qdel(parent.GetComponent(/datum/component/slippery))
return
@@ -159,7 +162,7 @@
//NB it's possible we get deleted after this, due to inherit
/datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE)
- var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST)
+ var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST, TURF_WET_SUPERLUBE)
if(duration_minimum <= 0 || !type)
return FALSE
if(type in allowed_types)
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index cdb195dd82..8737cd8feb 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -4,7 +4,7 @@
var/list/datum_components //for /datum/components
var/list/status_traits
var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register
- var/list/signal_procs
+ var/list/list/datum/callback/signal_procs
var/signal_enabled = FALSE
var/datum_flags = NONE
var/datum/weakref/weak_reference
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index cfbd8be32c..e44134f01f 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -875,14 +875,14 @@
return
// text2num conveniently returns a null on invalid values
O.armor = O.armor.setRating(melee = text2num(result["values"]["melee"]),\
- bullet = text2num(result["values"]["bullet"]),\
- laser = text2num(result["values"]["laser"]),\
- energy = text2num(result["values"]["energy"]),\
- bomb = text2num(result["values"]["bomb"]),\
- bio = text2num(result["values"]["bio"]),\
- rad = text2num(result["values"]["rad"]),\
- fire = text2num(result["values"]["fire"]),\
- acid = text2num(result["values"]["acid"]))
+ bullet = text2num(result["values"]["bullet"]),\
+ laser = text2num(result["values"]["laser"]),\
+ energy = text2num(result["values"]["energy"]),\
+ bomb = text2num(result["values"]["bomb"]),\
+ bio = text2num(result["values"]["bio"]),\
+ rad = text2num(result["values"]["rad"]),\
+ fire = text2num(result["values"]["fire"]),\
+ acid = text2num(result["values"]["acid"]))
log_admin("[key_name(usr)] modified the armor on [O] ([O.type]) to melee: [O.armor.melee], bullet: [O.armor.bullet], laser: [O.armor.laser], energy: [O.armor.energy], bomb: [O.armor.bomb], bio: [O.armor.bio], rad: [O.armor.rad], fire: [O.armor.fire], acid: [O.armor.acid]")
message_admins("[key_name_admin(usr)] modified the armor on [O] ([O.type]) to melee: [O.armor.melee], bullet: [O.armor.bullet], laser: [O.armor.laser], energy: [O.armor.energy], bomb: [O.armor.bomb], bio: [O.armor.bio], rad: [O.armor.rad], fire: [O.armor.fire], acid: [O.armor.acid]")
else
diff --git a/code/datums/embedding_behavior.dm b/code/datums/embedding_behavior.dm
index f631b9b1c4..a261ea48c6 100644
--- a/code/datums/embedding_behavior.dm
+++ b/code/datums/embedding_behavior.dm
@@ -1,53 +1,53 @@
#define EMBEDID "embed-[embed_chance]-[embedded_fall_chance]-[embedded_pain_chance]-[embedded_pain_multiplier]-[embedded_fall_pain_multiplier]-[embedded_impact_pain_multiplier]-[embedded_unsafe_removal_pain_multiplier]-[embedded_unsafe_removal_time]"
/proc/getEmbeddingBehavior(embed_chance = EMBED_CHANCE,
- embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
- embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
- embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
- embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
- embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
- embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
- embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
- . = locate(EMBEDID)
- if (!.)
- . = new /datum/embedding_behavior(embed_chance, embedded_fall_chance, embedded_pain_chance, embedded_pain_multiplier, embedded_fall_pain_multiplier, embedded_impact_pain_multiplier, embedded_unsafe_removal_pain_multiplier, embedded_unsafe_removal_time)
+ embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
+ embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
+ embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
+ embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
+ embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
+ embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
+ embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
+ . = locate(EMBEDID)
+ if (!.)
+ . = new /datum/embedding_behavior(embed_chance, embedded_fall_chance, embedded_pain_chance, embedded_pain_multiplier, embedded_fall_pain_multiplier, embedded_impact_pain_multiplier, embedded_unsafe_removal_pain_multiplier, embedded_unsafe_removal_time)
/datum/embedding_behavior
- var/embed_chance
- var/embedded_fall_chance
- var/embedded_pain_chance
- var/embedded_pain_multiplier //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
- var/embedded_fall_pain_multiplier //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
- var/embedded_impact_pain_multiplier //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
- var/embedded_unsafe_removal_pain_multiplier //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
- var/embedded_unsafe_removal_time //A time in ticks, multiplied by the w_class.
+ var/embed_chance
+ var/embedded_fall_chance
+ var/embedded_pain_chance
+ var/embedded_pain_multiplier //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
+ var/embedded_fall_pain_multiplier //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
+ var/embedded_impact_pain_multiplier //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
+ var/embedded_unsafe_removal_pain_multiplier //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
+ var/embedded_unsafe_removal_time //A time in ticks, multiplied by the w_class.
/datum/embedding_behavior/New(embed_chance = EMBED_CHANCE,
- embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
- embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
- embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
- embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
- embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
- embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
- embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
- src.embed_chance = embed_chance
- src.embedded_fall_chance = embedded_fall_chance
- src.embedded_pain_chance = embedded_pain_chance
- src.embedded_pain_multiplier = embedded_pain_multiplier
- src.embedded_fall_pain_multiplier = embedded_fall_pain_multiplier
- src.embedded_impact_pain_multiplier = embedded_impact_pain_multiplier
- src.embedded_unsafe_removal_pain_multiplier = embedded_unsafe_removal_pain_multiplier
- src.embedded_unsafe_removal_time = embedded_unsafe_removal_time
- tag = EMBEDID
+ embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
+ embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
+ embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
+ embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
+ embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
+ embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
+ embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
+ src.embed_chance = embed_chance
+ src.embedded_fall_chance = embedded_fall_chance
+ src.embedded_pain_chance = embedded_pain_chance
+ src.embedded_pain_multiplier = embedded_pain_multiplier
+ src.embedded_fall_pain_multiplier = embedded_fall_pain_multiplier
+ src.embedded_impact_pain_multiplier = embedded_impact_pain_multiplier
+ src.embedded_unsafe_removal_pain_multiplier = embedded_unsafe_removal_pain_multiplier
+ src.embedded_unsafe_removal_time = embedded_unsafe_removal_time
+ tag = EMBEDID
/datum/embedding_behavior/proc/setRating(embed_chance, embedded_fall_chance, embedded_pain_chance, embedded_pain_multiplier, embedded_fall_pain_multiplier, embedded_impact_pain_multiplier, embedded_unsafe_removal_pain_multiplier, embedded_unsafe_removal_time)
- return getEmbeddingBehavior((isnull(embed_chance) ? src.embed_chance : embed_chance),\
- (isnull(embedded_fall_chance) ? src.embedded_fall_chance : embedded_fall_chance),\
- (isnull(embedded_pain_chance) ? src.embedded_pain_chance : embedded_pain_chance),\
- (isnull(embedded_pain_multiplier) ? src.embedded_pain_multiplier : embedded_pain_multiplier),\
- (isnull(embedded_fall_pain_multiplier) ? src.embedded_fall_pain_multiplier : embedded_fall_pain_multiplier),\
- (isnull(embedded_impact_pain_multiplier) ? src.embedded_impact_pain_multiplier : embedded_impact_pain_multiplier),\
- (isnull(embedded_unsafe_removal_pain_multiplier) ? src.embedded_unsafe_removal_pain_multiplier : embedded_unsafe_removal_pain_multiplier),\
- (isnull(embedded_unsafe_removal_time) ? src.embedded_unsafe_removal_time : embedded_unsafe_removal_time))
+ return getEmbeddingBehavior((isnull(embed_chance) ? src.embed_chance : embed_chance),\
+ (isnull(embedded_fall_chance) ? src.embedded_fall_chance : embedded_fall_chance),\
+ (isnull(embedded_pain_chance) ? src.embedded_pain_chance : embedded_pain_chance),\
+ (isnull(embedded_pain_multiplier) ? src.embedded_pain_multiplier : embedded_pain_multiplier),\
+ (isnull(embedded_fall_pain_multiplier) ? src.embedded_fall_pain_multiplier : embedded_fall_pain_multiplier),\
+ (isnull(embedded_impact_pain_multiplier) ? src.embedded_impact_pain_multiplier : embedded_impact_pain_multiplier),\
+ (isnull(embedded_unsafe_removal_pain_multiplier) ? src.embedded_unsafe_removal_pain_multiplier : embedded_unsafe_removal_pain_multiplier),\
+ (isnull(embedded_unsafe_removal_time) ? src.embedded_unsafe_removal_time : embedded_unsafe_removal_time))
#undef EMBEDID
diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm
index e07fa27ef5..81ec0bf977 100644
--- a/code/datums/martial/wrestling.dm
+++ b/code/datums/martial/wrestling.dm
@@ -192,7 +192,7 @@
if (T && isturf(T))
if (!D.stat)
D.emote("scream")
- D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human/.Knockdown, 20))
+ D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human.proc/Knockdown, 20))
log_combat(A, D, "has thrown with wrestling")
return 0
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index f747c563ad..f4ca3a8ebd 100644
--- a/code/datums/mood_events/generic_negative_events.dm
+++ b/code/datums/mood_events/generic_negative_events.dm
@@ -5,8 +5,8 @@
mood_change = -1
/datum/mood_event/broken_vow //Used for when mimes break their vow of silence
- description = "I have brought shame upon my name, and betrayed my fellow mimes by breaking our sacred vow...\n"
- mood_change = -8
+ description = "I have brought shame upon my name, and betrayed my fellow mimes by breaking our sacred vow...\n"
+ mood_change = -8
/datum/mood_event/on_fire
description = "I'M ON FIRE!!!\n"
@@ -55,14 +55,14 @@
timeout = 2 MINUTES
/datum/mood_event/shameful_suicide //suicide_acts that return SHAME, like sord
- description = "I can't even end it all!\n"
- mood_change = -10
- timeout = 1 MINUTES
+ description = "I can't even end it all!\n"
+ mood_change = -10
+ timeout = 1 MINUTES
/datum/mood_event/dismembered
- description = "AHH! I WAS USING THAT LIMB!\n"
- mood_change = -8
- timeout = 2400
+ description = "AHH! I WAS USING THAT LIMB!\n"
+ mood_change = -8
+ timeout = 2400
/datum/mood_event/noshoes
description = "I am a disgrace to comedy everywhere!\n"
@@ -92,20 +92,20 @@
mood_change = 2
/datum/mood_event/brain_damage
- mood_change = -3
+ mood_change = -3
/datum/mood_event/brain_damage/add_effects()
- var/damage_message = pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage")
- description = "Hurr durr... [damage_message]\n"
+ var/damage_message = pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage")
+ description = "Hurr durr... [damage_message]\n"
/datum/mood_event/hulk //Entire duration of having the hulk mutation
- description = "HULK SMASH!\n"
- mood_change = -4
+ description = "HULK SMASH!\n"
+ mood_change = -4
/datum/mood_event/epilepsy //Only when the mutation causes a seizure
- description = "I should have paid attention to the epilepsy warning.\n"
- mood_change = -3
- timeout = 3000
+ description = "I should have paid attention to the epilepsy warning.\n"
+ mood_change = -3
+ timeout = 3000
/datum/mood_event/nyctophobia
description = "It sure is dark around here...\n"
diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm
index 422ec4476c..678802aed9 100644
--- a/code/datums/mood_events/generic_positive_events.dm
+++ b/code/datums/mood_events/generic_positive_events.dm
@@ -80,12 +80,12 @@
description = "Heh...hehehe...hehe...\n"
mood_change = 4
- /datum/mood_event/chemical_laughter
+/datum/mood_event/chemical_laughter
description = "Laughter really is the best medicine! Or is it?\n"
mood_change = 4
timeout = 3 MINUTES
- /datum/mood_event/chemical_superlaughter
+/datum/mood_event/chemical_superlaughter
description = "*WHEEZE*\n"
mood_change = 12
timeout = 3 MINUTES
diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm
index efa248b4f0..f689ff903e 100644
--- a/code/datums/mutations.dm
+++ b/code/datums/mutations.dm
@@ -30,7 +30,7 @@ GLOBAL_LIST_EMPTY(mutations_list)
. = on_losing(owner)
/datum/mutation/human/proc/set_se(se_string, on = 1)
- if(!se_string || lentext(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
+ if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
return
var/before = copytext(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1)
var/injection = num2hex(on ? rand(lowest_value, (256 * 16) - 1) : rand(0, lowest_value - 1), DNA_BLOCK_SIZE)
@@ -42,7 +42,7 @@ GLOBAL_LIST_EMPTY(mutations_list)
owner.dna.struc_enzymes = set_se(owner.dna.struc_enzymes, on)
/datum/mutation/human/proc/check_block_string(se_string)
- if(!se_string || lentext(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
+ if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
return 0
if(hex2num(getblock(se_string, dna_block)) >= lowest_value)
return 1
diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm
index 18efae955e..4f18e6fd62 100644
--- a/code/datums/ruins/lavaland.dm
+++ b/code/datums/ruins/lavaland.dm
@@ -163,6 +163,13 @@
suffix = "lavaland_surface_xeno_nest.dmm"
cost = 20 */
+/datum/map_template/ruin/lavaland/alien_nest
+ name = "Alien Nest"
+ id = "alien-nest"
+ description = "Not even Necropolis is safe from alien infestation. The competition for hosts has locked the legion and aliens in an endless conflict that can only be resolved by a PKA."
+ suffix = "lavaland_surface_alien_nest.dmm"
+ cost = 20
+
/datum/map_template/ruin/lavaland/fountain
name = "Fountain Hall"
id = "fountain"
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 563d06ca57..5c4fc61827 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -170,7 +170,7 @@
tick_interval = 4
alert_type = /obj/screen/alert/status_effect/his_grace
var/bloodlust = 0
-
+
/obj/screen/alert/status_effect/his_grace
name = "His Grace"
desc = "His Grace hungers, and you must feed Him."
@@ -356,7 +356,7 @@
var/new_staminaloss = owner.getStaminaLoss()
if(new_staminaloss < last_staminaloss)
var/heal_amount = -5 // CIT CHANGE - makes blood drunk status effect not exhaust you
- owner.adjustStaminaLoss(heal_amount, updating_health = FALSE)
+ owner.adjustStaminaLoss(heal_amount, FALSE)
new_staminaloss = owner.getStaminaLoss()
needs_health_update = TRUE
last_staminaloss = new_staminaloss
diff --git a/code/datums/verbs.dm b/code/datums/verbs.dm
index 79fe256bb4..d8d7ee7433 100644
--- a/code/datums/verbs.dm
+++ b/code/datums/verbs.dm
@@ -11,7 +11,7 @@
//do things for each entry in Generate_list
//return value sets Generate_list[verbpath]
-/datum/verbs/proc/HandleVerb(list/entry, atom/verb/verbpath, ...)
+/datum/verbs/proc/HandleVerb(list/entry, procpath/verbpath, ...)
return entry
/datum/verbs/New()
@@ -82,7 +82,7 @@
. += childlist
for (var/thing in verblist)
- var/atom/verb/verbpath = thing
+ var/procpath/verbpath = thing
if (!verbpath)
stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
var/list/entry = list()
diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm
index 345212cc1b..3247b890c6 100644
--- a/code/datums/weather/weather_types/ash_storm.dm
+++ b/code/datums/weather/weather_types/ash_storm.dm
@@ -80,7 +80,7 @@
return TRUE
if(ishuman(L)) //Are you immune?
var/mob/living/carbon/human/H = L
- var/thermal_protection = H.get_thermal_protection()
+ var/thermal_protection = H.easy_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
return TRUE
if(isliving(L))// if we're a non immune mob inside an immune mob we have to reconsider if that mob is immune to protect ourselves
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index 26942a1ba6..db6d80f9bb 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -1,10 +1,35 @@
/datum/wires/airlock
holder_type = /obj/machinery/door/airlock
- proper_name = "Airlock"
+ proper_name = "Generic Airlock"
+ var/wiretype
/datum/wires/airlock/secure
randomize = TRUE
+/datum/wires/airlock/command
+ proper_name = "Command Airlock"
+ wiretype = "commandairlock"
+
+/datum/wires/airlock/security
+ proper_name = "Security Airlock"
+ wiretype = "securityairlock"
+
+/datum/wires/airlock/engineering
+ proper_name = "Engineering Airlock"
+ wiretype = "engineeringairlock"
+
+/datum/wires/airlock/science
+ proper_name = "Science Airlock"
+ wiretype = "scienceairlock"
+
+/datum/wires/airlock/medical
+ proper_name = "Medical Airlock"
+ wiretype = "medicalairlock"
+
+/datum/wires/airlock/cargo
+ proper_name = "Cargo Airlock"
+ wiretype = "cargoairlock"
+
/datum/wires/airlock/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
@@ -14,7 +39,16 @@
WIRE_ZAP1, WIRE_ZAP2
)
add_duds(2)
- ..()
+ . = ..()
+ if(randomize || !wiretype)
+ return
+ if(!GLOB.wire_color_directory[wiretype])
+ colors = list()
+ randomize()
+ GLOB.wire_color_directory[wiretype] = colors
+ GLOB.wire_name_directory[wiretype] = proper_name
+ else
+ colors = GLOB.wire_color_directory[wiretype]
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm
index 798cd9c026..fa66306302 100644
--- a/code/game/area/Space_Station_13_areas.dm
+++ b/code/game/area/Space_Station_13_areas.dm
@@ -250,7 +250,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/disposal/incinerator
name = "Incinerator"
icon_state = "disposal"
+/area/maintenance/bar
+ name = "Maintenance Bar"
+ icon_state = "maintbar"
+/area/maintenance/bar/cafe
+ name = "Abandoned Cafe"
//Hallway
@@ -499,6 +504,16 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Abandoned Theatre"
icon_state = "Theatre"
+/area/crew_quarters/theatre/clown
+ name = "Clown's Office"
+
+/area/crew_quarters/theatre/mime
+ name = "Mime's Office"
+
+/area/crew_quarters/cryopod
+ name = "Cryogenics"
+ icon_state = "cryosleep"
+
/area/library
name = "Library"
icon_state = "library"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index dfbb59811b..612c3cba42 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -53,8 +53,6 @@
var/parallax_movedir = 0
- var/global/global_uid = 0
- var/uid
var/list/ambientsounds = GENERIC
flags_1 = CAN_BE_DIRTY_1
@@ -96,7 +94,6 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/area/Initialize()
icon_state = ""
layer = AREA_LAYER
- uid = ++global_uid
map_name = name // Save the initial (the name set in the map) name of the area.
canSmoothWithAreas = typecacheof(canSmoothWithAreas)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 68f22242e1..e8651ba93d 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -186,6 +186,10 @@
else
M.forceMove(src)
+//common name
+/atom/proc/update_multiz(prune_on_fail = FALSE)
+ return FALSE
+
/atom/proc/assume_air(datum/gas_mixture/giver)
qdel(giver)
return null
@@ -266,7 +270,7 @@
if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
should_override = TRUE
-
+
if(blood_DNA && !istype(src, /obj/effect/decal))
override[EXAMINE_POSITION_BEFORE] = " blood-stained "
should_override = TRUE
@@ -563,7 +567,7 @@
//Hook for running code when a dir change occurs
-/atom/proc/setDir(newdir)
+/atom/proc/setDir(newdir, ismousemovement=FALSE)
SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir)
dir = newdir
@@ -832,4 +836,7 @@ Proc for attack log creation, because really why not
if(filter_data && filter_data[name])
filter_data -= name
update_filters()
- return TRUE
\ No newline at end of file
+ return TRUE
+
+/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
+ . |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
\ No newline at end of file
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 0957db5fcb..ef20b6e35e 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -34,6 +34,51 @@
var/datum/component/orbiter/orbiting
var/can_be_z_moved = TRUE
+ var/zfalling = FALSE
+
+/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction)
+ if(!direction)
+ direction = DOWN
+ if(!source)
+ source = get_turf(src)
+ if(!source)
+ return FALSE
+ if(!target)
+ target = get_step_multiz(source, direction)
+ if(!target)
+ return FALSE
+ return !(movement_type & FLYING) && has_gravity(source) && !throwing
+
+/atom/movable/proc/onZImpact(turf/T, levels)
+ var/atom/highest = T
+ for(var/i in T.contents)
+ var/atom/A = i
+ if(!A.density)
+ continue
+ if(isobj(A) || ismob(A))
+ if(A.layer > highest.layer)
+ highest = A
+ INVOKE_ASYNC(src, .proc/SpinAnimation, 5, 2)
+ throw_impact(highest)
+ return TRUE
+
+//For physical constraints to travelling up/down.
+/atom/movable/proc/can_zTravel(turf/destination, direction)
+ var/turf/T = get_turf(src)
+ if(!T)
+ return FALSE
+ if(!direction)
+ if(!destination)
+ return FALSE
+ direction = get_dir(T, destination)
+ if(direction != UP && direction != DOWN)
+ return FALSE
+ if(!destination)
+ destination = get_step_multiz(src, direction)
+ if(!destination)
+ return FALSE
+ return T.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, T)
+
/atom/movable/vv_edit_var(var_name, var_value)
var/static/list/banned_edits = list("step_x", "step_y", "step_size")
var/static/list/careful_edits = list("bound_x", "bound_y", "bound_width", "bound_height")
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 51a34f4194..76e6268977 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -167,6 +167,7 @@ Credit where due:
number_players -= 30
starter_servants += round(number_players / 10)
starter_servants = min(starter_servants, 8) //max 8 servants (that sould only happen with a ton of players)
+ GLOB.clockwork_vitality += 50 * starter_servants //some starter Vitality to help recover from initial fuck ups
while(starter_servants)
var/datum/mind/servant = antag_pick(antag_candidates)
servants_to_serve += servant
diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm
index 79890e4cdd..ee96d1fa10 100644
--- a/code/game/gamemodes/clown_ops/clown_weapons.dm
+++ b/code/game/gamemodes/clown_ops/clown_weapons.dm
@@ -138,7 +138,7 @@
var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.signal_enabled = active
-/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1)
+/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
if(active)
if(iscarbon(thrower))
var/mob/living/carbon/C = thrower
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
index f24301d716..cc90821618 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
@@ -29,10 +29,10 @@
// So for example you can get the list of all current dead players with var/list/dead_players = candidates[CURRENT_DEAD_PLAYERS]
// Make sure to properly typecheck the mobs in those lists, as the dead_players list could contain ghosts, or dead players still in their bodies.
// We're still gonna trim the obvious (mobs without clients, jobbanned players, etc)
- living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
- living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS])
- dead_players = trim_list(mode.current_players[CURRENT_DEAD_PLAYERS])
- list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS])
+ living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
+ living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS])
+ dead_players = trim_list(mode.current_players[CURRENT_DEAD_PLAYERS])
+ list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS])
/datum/dynamic_ruleset/midround/proc/trim_list(list/L = list())
var/list/trimmed_list = L.Copy()
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
index 6a9aefa996..abca269eeb 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
@@ -126,7 +126,7 @@
/datum/dynamic_ruleset/roundstart/changeling/execute()
var/team_mode = FALSE
- if(prob(team_mode_probability))
+ if(prob(team_mode_probability))
team_mode = TRUE
var/list/team_objectives = subtypesof(/datum/objective/changeling_team_objective)
var/list/possible_team_objectives = list()
@@ -174,14 +174,14 @@
/datum/dynamic_ruleset/roundstart/wizard/pre_execute()
if(GLOB.wizardstart.len == 0)
return FALSE
-
+
var/mob/M = pick(candidates)
if (M)
candidates -= M
assigned += M.mind
M.mind.assigned_role = ROLE_WIZARD
M.mind.special_role = ROLE_WIZARD
-
+
return TRUE
/datum/dynamic_ruleset/roundstart/wizard/execute()
@@ -189,7 +189,7 @@
M.current.forceMove(pick(GLOB.wizardstart))
M.add_antag_datum(new antag_datum())
return TRUE
-
+
//////////////////////////////////////////////
// //
// BLOOD CULT //
@@ -238,7 +238,7 @@
var/datum/antagonist/cult/new_cultist = new antag_datum()
new_cultist.cult_team = main_cult
new_cultist.give_equipment = TRUE
- M.add_antag_datum(new_cultist)
+ M.add_antag_datum(new_cultist)
main_cult.setup_objectives()
return TRUE
@@ -390,7 +390,7 @@
SSshuttle.registerHostileEnvironment(src)
return TRUE
-
+
/datum/dynamic_ruleset/roundstart/delayed/revs/rule_process()
if(check_rev_victory())
finished = 1
@@ -492,6 +492,7 @@
number_players -= 30
starter_servants += round(number_players / 10)
starter_servants = min(starter_servants, 8)
+ GLOB.clockwork_vitality += 50 * starter_servants //some starter Vitality to help recover from initial fuck ups
for (var/i in 1 to starter_servants)
var/mob/servant = pick(candidates)
candidates -= servant
@@ -605,7 +606,7 @@
high_population_requirement = 101
var/devil_limit = 4 // Hard limit on devils if scaling is turned off
-/datum/dynamic_ruleset/roundstart/devil/pre_execute()
+/datum/dynamic_ruleset/roundstart/devil/pre_execute()
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
var/num_devils = 1
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 17e26e66af..4d7b346241 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -31,7 +31,7 @@
var/recommended_enemies = 0
var/antag_flag = null //preferences flag such as BE_WIZARD that need to be turned on for players to be antag
var/mob/living/living_antag_player = null
- var/list/datum/game_mode/replacementmode = null
+ var/datum/game_mode/replacementmode = null
var/round_converted = 0 //0: round not converted, 1: round going to convert, 2: round converted
var/reroll_friendly //During mode conversion only these are in the running
var/continuous_sanity_checked //Catches some cases where config options could be used to suggest that modes without antagonists should end when all antagonists die
diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm
index 64aaeebacd..d54dda5353 100644
--- a/code/game/gamemodes/sandbox/h_sandbox.dm
+++ b/code/game/gamemodes/sandbox/h_sandbox.dm
@@ -25,14 +25,14 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
var/canisterinfo = null
var/hsbinfo = null
//items that shouldn't spawn on the floor because they would bug or act weird
- var/global/list/spawn_forbidden = list(
+ var/static/list/spawn_forbidden = list(
/obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you
/obj/item/assembly, /obj/item/onetankbomb, /obj/item/pda/ai,
/obj/item/smallDelivery, /obj/item/projectile,
/obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module)
/datum/hSB/proc/update()
- var/global/list/hrefs = list(
+ var/static/list/hrefs = list(
"Space Gear",
"Suit Up (Space Travel Gear)" = "hsbsuit",
"Spawn Gas Mask" = "hsbspawn&path=[/obj/item/clothing/mask/gas]",
diff --git a/code/game/machinery/aug_manipulator.dm b/code/game/machinery/aug_manipulator.dm
index 99200e510e..8419f5803c 100644
--- a/code/game/machinery/aug_manipulator.dm
+++ b/code/game/machinery/aug_manipulator.dm
@@ -16,8 +16,8 @@
to_chat(user, "Alt-click to eject the limb.")
/obj/machinery/aug_manipulator/Initialize()
- initial_icon_state = initial(icon_state)
- return ..()
+ initial_icon_state = initial(icon_state)
+ return ..()
/obj/machinery/aug_manipulator/update_icon()
cut_overlays()
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 1c6e21491c..bdb90c4c97 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -176,7 +176,7 @@
matching_designs.Cut()
for(var/v in stored_research.researched_designs)
- var/datum/design/D = stored_research.researched_designs[v]
+ var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(findtext(D.name,href_list["to_search"]))
matching_designs.Add(D)
updateUsrDialog()
@@ -252,7 +252,7 @@
dat += materials_printout()
for(var/v in stored_research.researched_designs)
- var/datum/design/D = stored_research.researched_designs[v]
+ var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(!(selected_category in D.category))
continue
@@ -366,7 +366,7 @@
/obj/machinery/autolathe/proc/adjust_hacked(state)
hacked = state
for(var/id in SSresearch.techweb_designs)
- var/datum/design/D = SSresearch.techweb_designs[id]
+ var/datum/design/D = SSresearch.techweb_design_by_id(id)
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
if(hacked)
stored_research.add_design(D)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 89c5e56b71..e65da0fcff 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -354,7 +354,8 @@
O.organ_flags &= ~ORGAN_FROZEN
unattached_flesh.Cut()
mess = FALSE
- new /obj/effect/gibspawner/generic(get_turf(src))
+ if(mob_occupant)
+ mob_occupant.spawn_gibs()
audible_message("You hear a splat.")
update_icon()
return
@@ -474,8 +475,6 @@
flesh_number = unattached_flesh.len
-#define CRYOMOBS 'icons/obj/cryo_mobs.dmi'
-
/obj/machinery/clonepod/update_icon()
cut_overlays()
diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm
index c317cbba0d..858a0a995b 100644
--- a/code/game/machinery/computer/Operating.dm
+++ b/code/game/machinery/computer/Operating.dm
@@ -32,7 +32,7 @@
/obj/machinery/computer/operating/proc/sync_surgeries()
for(var/i in linked_techweb.researched_designs)
- var/datum/design/surgery/D = linked_techweb.researched_designs[i]
+ var/datum/design/surgery/D = SSresearch.techweb_design_by_id(i)
if(!istype(D))
continue
advanced_surgeries |= D.surgery
diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm
index 9d49574317..394cc4593d 100644
--- a/code/game/machinery/computer/dna_console.dm
+++ b/code/game/machinery/computer/dna_console.dm
@@ -468,7 +468,7 @@
var/len = length(viable_occupant.dna.uni_identity)
num = WRAP(num, 1, len+1)
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2
- //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
+ //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
var/subblock = num - block*DNA_BLOCK_SIZE
last_change = "UI #[block]-[subblock]; "
diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm
index 67407d220e..75e4a866f0 100644
--- a/code/game/machinery/computer/telecrystalconsoles.dm
+++ b/code/game/machinery/computer/telecrystalconsoles.dm
@@ -148,7 +148,6 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
virgin = 0
/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population.
- ..()
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
var/danger = GLOB.joined_player_list.len - nukeops.len
danger = CEILING(danger, 10)
diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm
index b5869ef36b..21fb70c38c 100644
--- a/code/game/machinery/computer/teleporter.dm
+++ b/code/game/machinery/computer/teleporter.dm
@@ -130,12 +130,12 @@
L[avoid_assoc_duplicate_keys(A.name, areaindex)] = R
for(var/obj/item/implant/tracking/I in GLOB.tracked_implants)
- if(!I.imp_in || !isliving(I.imp_in))
+ if(!I.imp_in || !I.allow_teleport || !isliving(I.imp_in))
continue
else
var/mob/living/M = I.imp_in
if(M.stat == DEAD)
- if(M.timeofdeath + 6000 < world.time)
+ if(M.timeofdeath + I.lifespan_postmortem < world.time)
continue
if(is_eligible(M))
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = M
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 4d252f1a46..98dd91d3bd 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -307,7 +307,6 @@
//Handle Borg stuff first
if(iscyborg(mob_occupant))
var/mob/living/silicon/robot/R = mob_occupant
- if(!istype(R)) return ..()
R.contents -= R.mmi
qdel(R.mmi)
@@ -409,7 +408,7 @@
// Ghost and delete the mob.
if(!mob_occupant.get_ghost(1))
- mob_occupant.ghostize(0) // Players who cryo out may not re-enter the round
+ mob_occupant.ghostize(FALSE, penalize = TRUE)
QDEL_NULL(occupant)
open_machine()
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 1c6d713437..91306585b8 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -364,7 +364,7 @@
//for(var/mob/living/carbon/NS in rangers)
// NS.resting = !NS.resting
// NS.update_canmove()
- time--
+ time--
/obj/machinery/jukebox/disco/proc/dance5(var/mob/living/M)
animate(M, transform = matrix(180, MATRIX_ROTATE), time = 1, loop = 0)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 365d19b826..f85fb3f310 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -83,6 +83,7 @@
var/boltDown = 'sound/machines/boltsdown.ogg'
var/noPower = 'sound/machines/doorclick.ogg'
var/previous_airlock = /obj/structure/door_assembly //what airlock assembly mineral plating was applied to
+ var/wiretypepath = /datum/wires/airlock // which set of per round randomized wires this airlock type has.
var/airlock_material //material of inner filling; if its an airlock with glass, this should be set to "glass"
var/overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
var/note_overlay_file = 'icons/obj/doors/airlocks/station/overlays.dmi' //Used for papers and photos pinned to the airlock
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index becd89063f..59b49d5828 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -8,16 +8,19 @@
/obj/machinery/door/airlock/command
icon = 'icons/obj/doors/airlocks/station/command.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_com
+ wiretypepath = /datum/wires/airlock/command
normal_integrity = 450
/obj/machinery/door/airlock/security
icon = 'icons/obj/doors/airlocks/station/security.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_sec
+ wiretypepath = /datum/wires/airlock/security
normal_integrity = 450
/obj/machinery/door/airlock/engineering
icon = 'icons/obj/doors/airlocks/station/engineering.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_eng
+ wiretypepath = /datum/wires/airlock/engineering
/obj/machinery/door/airlock/engineering/abandoned
abandoned = TRUE
@@ -25,6 +28,7 @@
/obj/machinery/door/airlock/medical
icon = 'icons/obj/doors/airlocks/station/medical.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_med
+ wiretypepath = /datum/wires/airlock/medical
/obj/machinery/door/airlock/maintenance
name = "maintenance access"
@@ -44,11 +48,13 @@
name = "mining airlock"
icon = 'icons/obj/doors/airlocks/station/mining.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_min
+ wiretypepath = /datum/wires/airlock/cargo
/obj/machinery/door/airlock/atmos
name = "atmospherics airlock"
icon = 'icons/obj/doors/airlocks/station/atmos.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_atmo
+ wiretypepath = /datum/wires/airlock/engineering
/obj/machinery/door/airlock/atmos/abandoned
abandoned = TRUE
@@ -56,6 +62,7 @@
/obj/machinery/door/airlock/research
icon = 'icons/obj/doors/airlocks/station/research.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_research
+ wiretypepath = /datum/wires/airlock/science
/obj/machinery/door/airlock/freezer
name = "freezer airlock"
@@ -65,10 +72,12 @@
/obj/machinery/door/airlock/science
icon = 'icons/obj/doors/airlocks/station/science.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_science
+ wiretypepath = /datum/wires/airlock/science
/obj/machinery/door/airlock/virology
icon = 'icons/obj/doors/airlocks/station/virology.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_viro
+ wiretypepath = /datum/wires/airlock/medical
//////////////////////////////////
/*
@@ -376,6 +385,7 @@
icon = 'icons/obj/doors/airlocks/vault/vault.dmi'
overlays_file = 'icons/obj/doors/airlocks/vault/overlays.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_vault
+ wiretypepath = /datum/wires/airlock/secure
explosion_block = 2
normal_integrity = 400 // reverse engieneerd: 400 * 1.5 (sec lvl 6) = 600 = original
security_level = 6
diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm
index db59f3f413..5418dcdb97 100644
--- a/code/game/machinery/launch_pad.dm
+++ b/code/game/machinery/launch_pad.dm
@@ -153,11 +153,11 @@
var/obj/item/storage/briefcase/launchpad/briefcase
/obj/machinery/launchpad/briefcase/Initialize(mapload, briefcase)
- . = ..()
- if(!briefcase)
- log_game("[src] has been spawned without a briefcase.")
- return INITIALIZE_HINT_QDEL
- src.briefcase = briefcase
+ . = ..()
+ if(!briefcase)
+ log_game("[src] has been spawned without a briefcase.")
+ return INITIALIZE_HINT_QDEL
+ src.briefcase = briefcase
/obj/machinery/launchpad/briefcase/Destroy()
QDEL_NULL(briefcase)
diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm
index 88ab4ec6f8..794509801b 100644
--- a/code/game/machinery/limbgrower.dm
+++ b/code/game/machinery/limbgrower.dm
@@ -178,7 +178,7 @@
dat += materials_printout()
for(var/v in stored_research.researched_designs)
- var/datum/design/D = stored_research.researched_designs[v]
+ var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(!(selected_category in D.category))
continue
if(disabled || !can_build(D))
@@ -221,7 +221,7 @@
if(obj_flags & EMAGGED)
return
for(var/id in SSresearch.techweb_designs)
- var/datum/design/D = SSresearch.techweb_designs[id]
+ var/datum/design/D = SSresearch.techweb_design_by_id(id)
if((D.build_type & LIMBGROWER) && ("emagged" in D.category))
stored_research.add_design(D)
to_chat(user, "A warning flashes onto the screen, stating that safety overrides have been deactivated!")
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index c37c607a6e..6bf9930eec 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -515,7 +515,7 @@ GLOBAL_LIST_EMPTY(allCasters)
if(href_list["set_channel_name"])
channel_name = stripped_input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "", MAX_NAME_LEN)
while (findtext(channel_name," ") == 1)
- channel_name = copytext(channel_name,2,lentext(channel_name)+1)
+ channel_name = copytext(channel_name,2,length(channel_name)+1)
updateUsrDialog()
else if(href_list["set_channel_lock"])
c_locked = !c_locked
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 7aaab0d8ea..289f075302 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -647,6 +647,7 @@
has_cover = 0
scan_range = 9
req_access = list(ACCESS_SYNDICATE)
+ mode = TURRET_LETHAL
stun_projectile = /obj/item/projectile/bullet
lethal_projectile = /obj/item/projectile/bullet
lethal_projectile_sound = 'sound/weapons/gunshot.ogg'
@@ -695,6 +696,24 @@
stun_projectile = /obj/item/projectile/bullet/syndicate_turret
lethal_projectile = /obj/item/projectile/bullet/syndicate_turret
+/obj/machinery/porta_turret/syndicate/shuttle
+ scan_range = 9
+ shot_delay = 3
+ stun_projectile = /obj/item/projectile/bullet/p50/penetrator/shuttle
+ lethal_projectile = /obj/item/projectile/bullet/p50/penetrator/shuttle
+ lethal_projectile_sound = 'sound/weapons/gunshot_smg.ogg'
+ stun_projectile_sound = 'sound/weapons/gunshot_smg.ogg'
+ armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 80, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
+
+/obj/machinery/porta_turret/syndicate/shuttle/target(atom/movable/target)
+ if(target)
+ setDir(get_dir(base, target))//even if you can't shoot, follow the target
+ shootAt(target)
+ addtimer(CALLBACK(src, .proc/shootAt, target), 5)
+ addtimer(CALLBACK(src, .proc/shootAt, target), 10)
+ addtimer(CALLBACK(src, .proc/shootAt, target), 15)
+ return TRUE
+
/obj/machinery/porta_turret/ai
faction = list("silicon")
nonlethal_projectile = /obj/item/projectile/beam/disabler
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 1a8bc7ece4..73aadc99d0 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -109,7 +109,7 @@
var/atom/movable/AM = i
var/obj/item/bodypart/head/as_head = AM
var/obj/item/mmi/as_mmi = AM
- var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || isbrain(AM)
+ var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || isbrain(AM) || istype(AM, /obj/item/dullahan_relay)
if(brain_holder)
emergency_stop(AM)
else if(isliving(AM))
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index e9216ca736..ec53cc3210 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -243,7 +243,7 @@
else
line1 = "CARGO"
line2 = SSshuttle.supply.getTimerStr()
- if(lentext(line2) > CHARS_PER_LINE)
+ if(length(line2) > CHARS_PER_LINE)
line2 = "Error"
update_display(line1, line2)
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index d7c2a5734b..4a97aa1775 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -1,5 +1,5 @@
#define BUTTON_COOLDOWN 60 // cant delay the bomb forever
-#define BUTTON_DELAY 50 //five seconds
+#define BUTTON_DELAY 20 // two seconds
/obj/machinery/syndicatebomb
icon = 'icons/obj/assemblies.dmi'
@@ -500,7 +500,7 @@
/obj/item/syndicatedetonator
name = "big red button"
- desc = "Your standard issue bomb synchronizing button. Five second safety delay to prevent 'accidents'."
+ desc = "Your standard issue bomb synchronizing button. Two second safety delay to prevent 'accidents'."
icon = 'icons/obj/assemblies.dmi'
icon_state = "bigred"
item_state = "electronic"
diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm
index ed29809f91..3a3d98ad1e 100644
--- a/code/game/mecha/combat/honker.dm
+++ b/code/game/mecha/combat/honker.dm
@@ -57,19 +57,19 @@
[js_byjax]
[js_dropdowns]
function SSticker() {
- setInterval(function(){
- window.location='byond://?src=[REF(src)]&update_content=1';
- document.body.style.color = get_rand_color_string();
- document.body.style.background = get_rand_color_string();
- }, 1000);
+ setInterval(function(){
+ window.location='byond://?src=[REF(src)]&update_content=1';
+ document.body.style.color = get_rand_color_string();
+ document.body.style.background = get_rand_color_string();
+ }, 1000);
}
function get_rand_color_string() {
- var color = new Array;
- for(var i=0;i<3;i++){
- color.push(Math.floor(Math.random()*255));
- }
- return "rgb("+color.toString()+")";
+ var color = new Array;
+ for(var i=0;i<3;i++){
+ color.push(Math.floor(Math.random()*255));
+ }
+ return "rgb("+color.toString()+")";
}
window.onload = function() {
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 4acf7981bc..417fefce6e 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -34,12 +34,12 @@
)
/obj/machinery/mecha_part_fabricator/Initialize()
- var/datum/component/material_container/materials = AddComponent(/datum/component/material_container,
- list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), 0,
- TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
- materials.precise_insertion = TRUE
- stored_research = new
- return ..()
+ var/datum/component/material_container/materials = AddComponent(/datum/component/material_container,
+ list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), 0,
+ TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
+ materials.precise_insertion = TRUE
+ stored_research = new
+ return ..()
/obj/machinery/mecha_part_fabricator/RefreshParts()
var/T = 0
@@ -85,7 +85,7 @@
/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name)
var/output = ""
for(var/v in stored_research.researched_designs)
- var/datum/design/D = stored_research.researched_designs[v]
+ var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(!(set_name in D.category))
continue
@@ -166,7 +166,7 @@
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name)
if(set_name in part_sets)
for(var/v in stored_research.researched_designs)
- var/datum/design/D = stored_research.researched_designs[v]
+ var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(set_name in D.category)
add_to_queue(D)
@@ -324,7 +324,7 @@
if(href_list["part"])
var/T = afilter.getStr("part")
for(var/v in stored_research.researched_designs)
- var/datum/design/D = stored_research.researched_designs[v]
+ var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(D.id == T)
if(!processing_queue)
@@ -335,7 +335,7 @@
if(href_list["add_to_queue"])
var/T = afilter.getStr("add_to_queue")
for(var/v in stored_research.researched_designs)
- var/datum/design/D = stored_research.researched_designs[v]
+ var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(D.id == T)
add_to_queue(D)
@@ -373,7 +373,7 @@
if(href_list["part_desc"])
var/T = afilter.getStr("part_desc")
for(var/v in stored_research.researched_designs)
- var/datum/design/D = stored_research.researched_designs[v]
+ var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(D.id == T)
var/obj/part = D.build_path
diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm
index 79ee7435e4..f9e04990fc 100644
--- a/code/game/mecha/mecha_topic.dm
+++ b/code/game/mecha/mecha_topic.dm
@@ -21,9 +21,9 @@
[js_byjax]
[js_dropdowns]
function SSticker() {
- setInterval(function(){
- window.location='byond://?src=[REF(src)]&update_content=1';
- }, 1000);
+ setInterval(function(){
+ window.location='byond://?src=[REF(src)]&update_content=1';
+ }, 1000);
}
window.onload = function() {
diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm
index b6a3c7cfef..2fa7277d8b 100644
--- a/code/game/objects/effects/decals/decal.dm
+++ b/code/game/objects/effects/decals/decal.dm
@@ -15,7 +15,7 @@
qdel(src)
/obj/effect/decal/proc/NeverShouldHaveComeHere(turf/T)
- return isspaceturf(T) || isclosedturf(T) || islava(T) || istype(T, /turf/open/water) || ischasm(T)
+ return isclosedturf(T) || isgroundlessturf(T)
/obj/effect/decal/ex_act(severity, target)
qdel(src)
diff --git a/code/game/objects/effects/decals/turfdecal/weather.dm b/code/game/objects/effects/decals/turfdecal/weather.dm
index 9e8da6a3f8..52c1a165f2 100644
--- a/code/game/objects/effects/decals/turfdecal/weather.dm
+++ b/code/game/objects/effects/decals/turfdecal/weather.dm
@@ -9,4 +9,17 @@
/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
+ icon_state = "snow_corner"
+
+/obj/effect/turf_decal/weather/dirt
+ name = "dirt siding"
+ icon = 'icons/turf/decals.dmi'
+ icon_state = "dirt_side"
+
+/obj/effect/turf_decal/weather/sand
+ name = "sand siding"
+ icon = 'icons/misc/beach.dmi'
+ icon_state = "sand_side"
+
+/obj/effect/turf_decal/weather/sand/light
+ icon_state = "lightsand_side"
diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm
index 410923fe25..d48013d472 100644
--- a/code/game/objects/effects/effects.dm
+++ b/code/game/objects/effects/effects.dm
@@ -57,6 +57,9 @@
/obj/effect/abstract/singularity_act()
return
+/obj/effect/abstract/has_gravity(turf/T)
+ return FALSE
+
/obj/effect/dummy/singularity_pull()
return
diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm
index dd39bc567a..fe1590caba 100644
--- a/code/game/objects/effects/spawners/gibspawner.dm
+++ b/code/game/objects/effects/spawners/gibspawner.dm
@@ -32,7 +32,8 @@
var/list/dna_to_add //find the dna to pass to the spawned gibs. do note this can be null if the mob doesn't have blood. add_blood_DNA() has built in null handling.
var/body_coloring = ""
if(source_mob)
- dna_to_add = source_mob.get_blood_dna_list() //ez pz
+ if(!issilicon(source_mob))
+ dna_to_add = source_mob.get_blood_dna_list() //ez pz
if(ishuman(source_mob))
var/mob/living/carbon/human/H = source_mob
if(H.dna.species.use_skintones)
@@ -51,15 +52,11 @@
body_coloring = "#[skintone2hex(H.skin_tone)]"
else
body_coloring = "#[H.dna.features["mcolor"]]"
- qdel(H)
else
dna_to_add = temp_mob.get_blood_dna_list()
- qdel(temp_mob)
else if(!issilicon(temp_mob))
dna_to_add = temp_mob.get_blood_dna_list()
- qdel(temp_mob)
- else
- qdel(temp_mob)
+ qdel(temp_mob)
else
dna_to_add = list("Non-human DNA" = random_blood_type()) //else, generate a random bloodtype for it.
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index c92721082c..08a3501be6 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -201,7 +201,7 @@
S.directive = directive
if(player_spiders)
S.playable_spider = TRUE
- notify_ghosts("Spider [S.name] can be controlled", null, enter_link="(Click to play)", source=S, action=NOTIFY_ATTACK, ignore_key = POLL_IGNORE_SPIDER)
+ notify_ghosts("Spider [S.name] can be controlled", null, enter_link="(Click to play)", source=S, action=NOTIFY_ATTACK, ignore_key = POLL_IGNORE_SPIDER, ignore_dnr_observers = TRUE)
qdel(src)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 953036e970..4f472c6477 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -202,7 +202,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/list/boostable_nodes = techweb_item_boost_check(src)
if (boostable_nodes)
for(var/id in boostable_nodes)
- var/datum/techweb_node/node = SSresearch.techweb_nodes[id]
+ var/datum/techweb_node/node = SSresearch.techweb_node_by_id(id)
+ if(!node)
+ continue
research_msg += sep
research_msg += node.display_name
sep = ", "
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index 8763089464..134b921666 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -163,6 +163,8 @@ RLD
var/use_one_access = 0 //If the airlock should require ALL or only ONE of the listed accesses.
var/delay_mod = 1
var/canRturf = FALSE //Variable for R walls to deconstruct them
+ var/adjacency_check = TRUE //Wheter it checks if the tool has to be in our hands or not. Wsed for the aux base construction drone's internal RCD
+
/obj/item/construction/rcd/suicide_act(mob/user)
user.visible_message("[user] sets the RCD to 'Wall' and points it down [user.p_their()] throat! It looks like [user.p_theyre()] trying to commit suicide..")
@@ -273,7 +275,7 @@ RLD
/obj/item/construction/rcd/proc/check_menu(mob/living/user)
if(!istype(user))
return FALSE
- if(user.incapacitated() || !user.Adjacent(src))
+ if(user.incapacitated() || (adjacency_check && !user.Adjacent(src)))
return FALSE
return TRUE
@@ -286,7 +288,7 @@ RLD
"SOUTH" = image(icon = 'icons/mob/radial.dmi', icon_state = "csouth"),
"WEST" = image(icon = 'icons/mob/radial.dmi', icon_state = "cwest")
)
- var/computerdirs = show_radial_menu(user, src, computer_dirs, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
+ var/computerdirs = show_radial_menu(user, src, computer_dirs, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = adjacency_check, tooltips = TRUE)
if(!check_menu(user))
return
switch(computerdirs)
@@ -345,13 +347,13 @@ RLD
"External Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/external/glass)
)
- var/airlockcat = show_radial_menu(user, src, solid_or_glass_choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE)
+ var/airlockcat = show_radial_menu(user, src, solid_or_glass_choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = adjacency_check)
if(!check_menu(user))
return
switch(airlockcat)
if("Solid")
if(advanced_airlock_setting == 1)
- var/airlockpaint = show_radial_menu(user, src, solid_choices, radius = 42, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE)
+ var/airlockpaint = show_radial_menu(user, src, solid_choices, radius = 42, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = adjacency_check)
if(!check_menu(user))
return
switch(airlockpaint)
@@ -396,7 +398,7 @@ RLD
if("Glass")
if(advanced_airlock_setting == 1)
- var/airlockpaint = show_radial_menu(user, src , glass_choices, radius = 42, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE)
+ var/airlockpaint = show_radial_menu(user, src , glass_choices, radius = 42, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = adjacency_check)
if(!check_menu(user))
return
switch(airlockpaint)
diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm
index f0d20afbbd..59a5c50bf6 100644
--- a/code/game/objects/items/body_egg.dm
+++ b/code/game/objects/items/body_egg.dm
@@ -14,7 +14,7 @@
src.Insert(loc)
return ..()
-/obj/item/organ/body_egg/Insert(var/mob/living/carbon/M, special = 0)
+/obj/item/organ/body_egg/Insert(var/mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
ADD_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC)
owner.med_hud_set_status()
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 1059a310eb..6989557127 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -983,3 +983,12 @@
name = "Ore Silo (Machine Board)"
build_path = /obj/machinery/ore_silo
req_components = list()
+
+/obj/item/circuitboard/machine/autobottler
+ name = "Auto-Bottler (Machine Board)"
+ build_path = /obj/machinery/rnd/production/protolathe/department/autobottler //Manips make you print things cheaper, even chems
+ req_components = list(/obj/item/stock_parts/matter_bin = 5,
+ /obj/item/stack/sheet/glass = 2,
+ /obj/item/stock_parts/capacitor = 1,
+ /obj/item/stack/cable_coil = 5,
+ /obj/item/reagent_containers/glass/beaker = 6) //So it can hold lots of chems
\ No newline at end of file
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 24cfe98397..0c9ac4bb60 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -140,7 +140,7 @@ GLOBAL_LIST_EMPTY(PDAs)
var/choice = input(M, "Choose the a reskin for [src]","Reskin Object") as null|anything in GLOB.pda_reskins
var/new_icon = GLOB.pda_reskins[choice]
- if(QDELETED(src) || isnull(new_icon) || new_icon == icon || M.incapacitated() || !in_range(M,src))
+ if(QDELETED(src) || isnull(new_icon) || new_icon == icon || !M.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
icon = new_icon
update_icon(FALSE, TRUE)
diff --git a/code/game/objects/items/devices/PDA/PDA_types.dm b/code/game/objects/items/devices/PDA/PDA_types.dm
index 54b82d8e07..2da47d481e 100644
--- a/code/game/objects/items/devices/PDA/PDA_types.dm
+++ b/code/game/objects/items/devices/PDA/PDA_types.dm
@@ -10,7 +10,7 @@
/obj/item/pda/clown/Initialize()
. = ..()
- AddComponent(/datum/component/slippery, 120, NO_SLIP_WHEN_WALKING, CALLBACK(src, .proc/AfterSlip))
+ AddComponent(/datum/component/slippery, 120, NO_SLIP_WHEN_WALKING|SLIP_WHEN_JOGGING, CALLBACK(src, .proc/AfterSlip))
/obj/item/pda/clown/proc/AfterSlip(mob/living/carbon/human/M)
if (istype(M) && (M.real_name != owner))
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index 3885a1f4d9..8be18a5f61 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -697,7 +697,7 @@ Code:
if(href_list["mule"]) //MULEbots are special snowflakes, and need different args due to how they work.
- active_bot.bot_control(command= href_list["mule"], user= usr, pda= 1)
+ active_bot.bot_control(href_list["mule"], usr, TRUE)
if(!host_pda)
return
@@ -772,4 +772,4 @@ Code:
return ""
//This is called for special abilities of cartridges
-/obj/item/cartridge/proc/special(mov/living/user, list/params)
+/obj/item/cartridge/proc/special(mob/living/user, list/params)
diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm
index 9d1b670e71..1ba0e525fa 100644
--- a/code/game/objects/items/devices/gps.dm
+++ b/code/game/objects/items/devices/gps.dm
@@ -15,6 +15,8 @@ GLOBAL_LIST_EMPTY(GPS_list)
/obj/item/gps/examine(mob/user)
..()
+ var/turf/curr = get_turf(src)
+ to_chat(user, "The screen says: [get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])")
to_chat(user, "Alt-click to switch it [tracking ? "off":"on"].")
/obj/item/gps/Initialize()
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 5ad5b41e95..d6737b94e9 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -651,7 +651,7 @@ SLIME SCANNER
/proc/atmosanalyzer_scan(mixture, mob/living/user, atom/target = src)
var/icon = target
- user.visible_message("[user] has used the analyzer on [icon2html(icon, viewers(src))] [target].", "You use the analyzer on [icon2html(icon, user)] [target].")
+ user.visible_message("[user] has used the analyzer on [icon2html(icon, viewers(user))] [target].", "You use the analyzer on [icon2html(icon, user)] [target].")
to_chat(user, "Results of analysis of [icon2html(icon, user)] [target].")
var/list/airs = islist(mixture) ? mixture : list(mixture)
diff --git a/code/game/objects/items/implants/implant_track.dm b/code/game/objects/items/implants/implant_track.dm
index 4b7ae3bbac..4f81432a39 100644
--- a/code/game/objects/items/implants/implant_track.dm
+++ b/code/game/objects/items/implants/implant_track.dm
@@ -1,7 +1,19 @@
/obj/item/implant/tracking
name = "tracking implant"
desc = "Track with this."
- activated = 0
+ activated = FALSE
+ var/lifespan_postmortem = 10 MINUTES //for how many deciseconds after user death will the implant work?
+ var/allow_teleport = TRUE //will people implanted with this act as teleporter beacons?
+
+/obj/item/implant/tracking/c38
+ name = "TRAC implant"
+ desc = "A smaller tracking implant that supplies power for only a few minutes."
+ var/lifespan = 5 MINUTES //how many deciseconds does the implant last?
+ allow_teleport = FALSE
+
+/obj/item/implant/tracking/c38/Initialize()
+ . = ..()
+ QDEL_IN(src, lifespan)
/obj/item/implant/tracking/Initialize()
. = ..()
@@ -45,7 +57,7 @@
var/dat = {"Implant Specifications:
Name: Tracking Beacon
Life: 10 minutes after death of host
- Important Notes: None
+ Important Notes: Implant also works as a teleporter beacon.
Implant Details:
Function: Continuously transmits low power signal. Useful for tracking.
diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm
index 6ae34e9ca2..d038ea7b4a 100644
--- a/code/game/objects/items/manuals.dm
+++ b/code/game/objects/items/manuals.dm
@@ -260,7 +260,7 @@
function pageloaded(myframe) {
document.getElementById("loading").style.display = "none";
myframe.style.display = "inline";
- }
+ }
You start skimming through the manual...
@@ -295,7 +295,7 @@
function pageloaded(myframe) {
document.getElementById("loading").style.display = "none";
myframe.style.display = "block";
- }
+ }
You start skimming through the manual...
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 10b84917bb..d7c2f7f4f6 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -265,7 +265,7 @@
if (B && !QDELETED(B))
H.internal_organs -= B
qdel(B)
- new /obj/effect/gibspawner/generic(get_turf(H), H.dna)
+ H.spawn_gibs()
return (BRUTELOSS)
/obj/item/melee/classic_baton/telescopic/attack_self(mob/user)
diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm
index 973fb0c0ab..90e2efabc4 100644
--- a/code/game/objects/items/plushes.dm
+++ b/code/game/objects/items/plushes.dm
@@ -558,6 +558,37 @@
item_state = "almaz"
squeak_override = list('modular_citadel/sound/voice/raptor_purr.ogg' = 1)
+/obj/item/toy/plush/lizardplushie/garou
+ icon_state = "garou"
+ item_state = "garou"
+
+/obj/item/toy/plush/lizardplushie/augments
+ icon_state = "augments"
+ item_state = "augments"
+ squeak_override = list('modular_citadel/sound/voice/weh.ogg' = 1) //I have no mouth and I must weh
+ attack_verb = list("hugged", "patted", "snugged", "booped")
+
+/obj/item/toy/plush/lizardplushie/xekov
+ icon_state = "xekov"
+ item_state = "xekov"
+
+/obj/item/toy/plush/lizardplushie/greg
+ icon_state = "greg"
+ item_state = "greg"
+
+/obj/item/toy/plush/lizardplushie/sin
+ icon_state = "sin"
+ item_state = "sin"
+ desc = "An adorable stuffed toy that resembles a lizardperson.. It faintly smells of sulfur."
+
+/obj/item/toy/plush/lizardplushie/ends
+ icon_state = "ends"
+ item_state = "ends"
+
+/obj/item/toy/plush/lizardplushie/lyssa
+ icon_state = "lyssa"
+ item_state = "lyssa"
+
/obj/item/toy/plush/snakeplushie
name = "snake plushie"
desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing."
@@ -715,6 +746,14 @@
item_state = "bhijn"
attack_verb = list("closed", "reworked", "merged")
+/obj/item/toy/plush/aiplush
+ name = "AI plushie"
+ desc = "A little stuffed toy AI core... it appears to be malfunctioning."
+ icon_state = "exo"
+ item_state = "exo"
+ attack_verb = list("hacked", "detonated", "overloaded")
+ squeak_override = list('sound/machines/beep.ogg' = 9, 'sound/machines/buzz-two.ogg' = 1)
+
/obj/item/toy/plush/bird
name = "bird plushie"
desc = "An adorable stuffed plushie that resembles an avian."
@@ -862,6 +901,18 @@
item_state = "redwood"
attack_verb = list("ordered", "bapped", "reprimanded")
+/obj/item/toy/plush/mammal/marisol
+ desc = "An adorable stuffed toy resembling a demi-wolf security officer."
+ icon_state = "marisol"
+ item_state = "marisol"
+ attack_verb = list("arrested", "harmbattoned", "lasered")
+
+/obj/item/toy/plush/mammal/minty
+ desc = "An adorable stuffed toy resembling some sort of crew member. It smells like mint.."
+ icon_state = "minty"
+ item_state = "minty"
+ attack_verb = list("freshened", "brushed")
+
/obj/item/toy/plush/mammal/dog
desc = "An adorable stuffed toy that resembles a canine."
icon_state = "katlin"
@@ -929,8 +980,8 @@
/obj/item/toy/plush/catgirl/skylar
desc = "An adorable stuffed toy that resembles a degenerate."
- icon_state = "skylar"
- item_state = "skylar"
+ icon_state = "skylar2"
+ item_state = "skylar2"
attack_verb = list("powergamed", "merged", "tabled")
squeak_override = list('sound/effects/meow1.ogg' = 1)
@@ -942,15 +993,15 @@
desc = "A masked stuffed toy that resembles a feline scientist."
icon_state = "trilby"
item_state = "trilby"
- attack_verb = list("pred", "coded", "remembered")
+ attack_verb = list("PR'd", "coded", "remembered")
/obj/item/toy/plush/catgirl/fermis
- name = "medcat plushie"
- desc = "An affectionate stuffed toy that resembles a certain medcat, comes complete with battery operated wagging tail!! You get the impression she's cheering you on to to find happiness and be kind to people."
- icon_state = "fermis"
- item_state = "fermis"
- attack_verb = list("cuddled", "petpatted", "wigglepurred")
- squeak_override = list('modular_citadel/sound/voice/merowr.ogg' = 1)
+ name = "medcat plushie"
+ desc = "An affectionate stuffed toy that resembles a certain medcat, comes complete with battery operated wagging tail!! You get the impression she's cheering you on to to find happiness and be kind to people."
+ icon_state = "fermis"
+ item_state = "fermis"
+ attack_verb = list("cuddled", "petpatted", "wigglepurred")
+ squeak_override = list('modular_citadel/sound/voice/merowr.ogg' = 1)
/obj/item/toy/plush/catgirl/mariaf
desc = "An adorable stuffed toy that resembles a very tall cat girl."
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index c085306892..0aa19b13ef 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -10,6 +10,7 @@
* Runed Metal (cult)
* Brass (clockwork cult)
* Bronze (bake brass)
+ * Cotton/Duracotton
*/
/*
@@ -186,31 +187,37 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \
*/
GLOBAL_LIST_INIT(wood_recipes, list ( \
new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1), \
+ new/datum/stack_recipe("tiki mask", /obj/item/clothing/mask/gas/tiki_mask, 2), \
new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), \
new/datum/stack_recipe("wood table frame", /obj/structure/table_frame/wood, 2, time = 10), \
+ null, \
new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \
+ new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
+ new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\
+ null, \
new/datum/stack_recipe("wooden chair", /obj/structure/chair/wood/, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("winged wooden chair", /obj/structure/chair/wood/wings, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("plywood chair", /obj/structure/chair/comfy/plywood, 4, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
+ null, \
new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("rustic wooden door", /obj/structure/mineral_door/woodrustic, 10, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
+ null, \
+ new/datum/stack_recipe("wooden barrel", /obj/structure/fermenting_barrel, 10, time = 20, one_per_turf = TRUE, on_floor = TRUE),\
new/datum/stack_recipe("coffin", /obj/structure/closet/crate/coffin, 5, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("book case", /obj/structure/bookcase, 4, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("drying rack", /obj/machinery/smartfridge/drying_rack, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("dog bed", /obj/structure/bed/dogbed, 10, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("dresser", /obj/structure/dresser, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
- new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 10),\
- new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = TRUE, on_floor = TRUE), \
- new/datum/stack_recipe("loom", /obj/structure/loom, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
- new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
- new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\
- new/datum/stack_recipe("tiki mask", /obj/item/clothing/mask/gas/tiki_mask, 2), \
- new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),\
new/datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE),\
new/datum/stack_recipe("wooden crate", /obj/structure/closet/crate/wooden, 6, time = 50, one_per_turf = TRUE, on_floor = TRUE),\
- new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\
+ new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = TRUE, on_floor = TRUE), \
+ new/datum/stack_recipe("loom", /obj/structure/loom, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
+ new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\
+ null, \
+ new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 10),\
+ new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),\
))
/obj/item/stack/sheet/mineral/wood
@@ -272,6 +279,9 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
resistance_flags = FLAMMABLE
force = 0
throwforce = 0
+ pull_effort = 90
+ is_fabric = TRUE
+ loom_result = /obj/item/stack/sheet/silk
merge_type = /obj/item/stack/sheet/cloth
/obj/item/stack/sheet/cloth/Initialize(mapload, new_amount, merge = TRUE)
@@ -281,6 +291,22 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
/obj/item/stack/sheet/cloth/ten
amount = 10
+/obj/item/stack/sheet/cloth/thirty
+ amount = 30
+
+/obj/item/stack/sheet/silk
+ name = "silk"
+ desc = "A long soft material. This one is just made out of cotton rather then any spiders or wyrms"
+ singular_name = "silk sheet"
+ icon_state = "sheet-silk"
+ item_state = "sheet-cloth"
+ novariants = TRUE
+ merge_type = /obj/item/stack/sheet/silk
+
+//obj/item/stack/sheet/silk/Initialize(mapload, new_amount, merge = TRUE)
+// recipes = GLOB.silk_recipes
+// return ..()
+
//Durathread fuck slash-asterisk comments
GLOBAL_LIST_INIT(durathread_recipes, list ( \
new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/durathread, 4, time = 40),
@@ -649,6 +675,12 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
pull_effort = 30
loom_result = /obj/item/stack/sheet/cloth
+/obj/item/stack/sheet/cotton/ten
+ amount = 10
+
+/obj/item/stack/sheet/cotton/thirty
+ amount = 30
+
/obj/item/stack/sheet/cotton/durathread
name = "raw durathread bundle"
desc = "A bundle of raw durathread ready to be spun on the loom."
diff --git a/code/game/objects/items/storage/dakis.dm b/code/game/objects/items/storage/dakis.dm
index 2703581a94..1939593c8e 100644
--- a/code/game/objects/items/storage/dakis.dm
+++ b/code/game/objects/items/storage/dakis.dm
@@ -7,7 +7,7 @@
desc = "A large pillow depicting a girl in a compromising position. Featuring as many dimensions as you."
icon = 'icons/obj/daki.dmi'
icon_state = "daki_base"
- slot_flags = SLOT_BACK
+ slot_flags = ITEM_SLOT_BACK
var/cooldowntime = 20
var/static/list/dakimakura_options = list("Callie","Casca","Chaika","Elisabeth","Foxy Grandpa","Haruko","Holo","Ian","Jolyne","Kurisu","Marie","Mugi","Nar'Sie","Patchouli","Plutia","Rei","Reisen","Naga","Squid","Squigly","Tomoko","Toriel","Umaru","Yaranaika","Yoko") //Kurisu is the ideal girl." - Me, Logos.
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
index 251703f907..ca7f7fe31a 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -288,7 +288,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
generate_rubber_toolbox_icon()
icon = GLOB.rubber_toolbox_icons[icon_state]
AddComponent(/datum/component/bouncy)
- . = ..()
/obj/item/storage/toolbox/proc/generate_rubber_toolbox_icon()
var/icon/new_icon = icon(icon, icon_state)
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index ee126971a7..47d9af2795 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -191,7 +191,7 @@
L.Knockdown(stunpwr)
- L.adjustStaminaLoss(stunpwr*0.1, affected_zone = (istype(user) ? user.zone_selected : BODY_ZONE_CHEST))//CIT CHANGE - makes stunbatons deal extra staminaloss. Todo: make this also deal pain when pain gets implemented.
+ L.adjustStaminaLoss(stunpwr*0.1)//CIT CHANGE - makes stunbatons deal extra staminaloss. Todo: make this also deal pain when pain gets implemented.
L.apply_effect(EFFECT_STUTTER, stunforce)
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
if(user)
diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm
index e16b0dd690..e0e875b739 100644
--- a/code/game/objects/items/teleportation.dm
+++ b/code/game/objects/items/teleportation.dm
@@ -79,7 +79,7 @@
continue
var/mob/living/M = W.imp_in
if (M.stat == DEAD)
- if (M.timeofdeath + 6000 < world.time)
+ if (M.timeofdeath + W.lifespan_postmortem < world.time)
continue
var/turf/tr = get_turf(M)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index de5a53fd9c..d78338d390 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1293,8 +1293,8 @@
var/toysound = 'sound/machines/click.ogg'
/obj/item/toy/figure/New()
- desc = "A \"Space Life\" brand [src]."
- ..()
+ desc = "A \"Space Life\" brand [src]."
+ ..()
/obj/item/toy/figure/attack_self(mob/user as mob)
if(cooldown <= world.time)
@@ -1517,3 +1517,18 @@
/obj/item/toy/dummy/GetVoice()
return doll_name
+
+/obj/item/toy/seashell
+ name = "seashell"
+ desc = "May you always have a shell in your pocket and sand in your shoes. Whatever that's supposed to mean."
+ icon = 'icons/misc/beach.dmi'
+ icon_state = "shell1"
+ var/static/list/possible_colors = list("" = 2, COLOR_PURPLE_GRAY = 1, COLOR_OLIVE = 1, COLOR_PALE_BLUE_GRAY = 1, COLOR_RED_GRAY = 1)
+
+/obj/item/toy/seashell/Initialize()
+ . = ..()
+ pixel_x = rand(-5, 5)
+ pixel_y = rand(-5, 5)
+ icon_state = "shell[rand(1,3)]"
+ color = pickweight(possible_colors)
+ setDir(pick(GLOB.cardinals))
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 172120861b..b9b08802d0 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -44,7 +44,7 @@
update_icon()
PopulateContents()
if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents
- take_contents()
+ addtimer(CALLBACK(src, .proc/take_contents), 0)
if(secure)
lockerelectronics = new(src)
lockerelectronics.accesses = req_access
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 9dab3679fa..dd72eb6b5d 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
@@ -61,6 +61,11 @@
..()
for(var/i = 0, i < 4, i++)
new /obj/item/reagent_containers/food/snacks/meat/slab/monkey(src)
+
+/obj/structure/closet/secure_closet/freezer/meat/open
+ req_access = null
+ locked = FALSE
+
/obj/structure/closet/secure_closet/freezer/fridge
name = "refrigerator"
@@ -73,6 +78,10 @@
for(var/i = 0, i < 2, i++)
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"
desc = "This contains cold hard cash."
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 585f60a347..6ef6f2d5ce 100644
--- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
@@ -26,7 +26,7 @@
if (prob(40))
new /obj/item/storage/toolbox/emergency(src)
- switch (pickweight(list("small" = 40, "aid" = 25, "tank" = 20, "both" = 10, "nothing" = 4, "delete" = 1)))
+ switch (pickweight(list("small" = 40, "aid" = 25, "tank" = 20, "both" = 10, "nothing" = 5)))
if ("small")
new /obj/item/tank/internals/emergency_oxygen(src)
new /obj/item/tank/internals/emergency_oxygen(src)
@@ -49,9 +49,7 @@
if ("nothing")
// doot
- // teehee
- if ("delete")
- qdel(src)
+ return
/*
* Fire Closet
diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm
index baf0cf312f..736e58143e 100644
--- a/code/game/objects/structures/fluff.dm
+++ b/code/game/objects/structures/fluff.dm
@@ -182,3 +182,59 @@
icon_state = "snowlegion"
anchored = TRUE
deconstructible = FALSE
+
+/obj/structure/fluff/big_chain
+ name = "giant chain"
+ desc = "A towering link of chains leading up to the ceiling."
+ icon = 'icons/effects/32x96.dmi'
+ icon_state = "chain"
+ layer = ABOVE_OBJ_LAYER
+ anchored = TRUE
+ density = TRUE
+ deconstructible = FALSE
+
+/obj/structure/fluff/railing
+ name = "railing"
+ desc = "Basic railing meant to protect idiots like you from falling."
+ icon = 'icons/obj/fluff.dmi'
+ icon_state = "railing"
+ density = TRUE
+ anchored = TRUE
+ deconstructible = FALSE
+
+/obj/structure/fluff/railing/corner
+ icon_state = "railing_corner"
+ density = FALSE
+
+/obj/structure/fluff/beach_towel
+ name = "beach towel"
+ desc = "A towel decorated in various beach-themed designs."
+ icon = 'icons/obj/fluff.dmi'
+ icon_state = "railing"
+ density = FALSE
+ anchored = TRUE
+ deconstructible = FALSE
+
+/obj/structure/fluff/beach_umbrella
+ name = "beach umbrella"
+ desc = "A fancy umbrella designed to keep the sun off beach-goers."
+ icon = 'icons/obj/fluff.dmi'
+ icon_state = "brella"
+ density = FALSE
+ anchored = TRUE
+ deconstructible = FALSE
+
+/obj/structure/fluff/beach_umbrella/security
+ icon_state = "hos_brella"
+
+/obj/structure/fluff/beach_umbrella/science
+ icon_state = "rd_brella"
+
+/obj/structure/fluff/beach_umbrella/engine
+ icon_state = "ce_brella"
+
+/obj/structure/fluff/beach_umbrella/cap
+ icon_state = "cap_brella"
+
+/obj/structure/fluff/beach_umbrella/syndi
+ icon_state = "syndi_brella"
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index b820e93c7b..10f1f30e13 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -66,7 +66,7 @@
. = ..()
var/area/A = get_area(src)
if(A)
- notify_ghosts("An ash walker egg is ready to hatch in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_ASHWALKER)
+ notify_ghosts("An ash walker egg is ready to hatch in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_ASHWALKER, ignore_dnr_observers = TRUE)
/datum/outfit/ashwalker
name ="Ashwalker"
@@ -133,7 +133,7 @@
. = ..()
var/area/A = get_area(src)
if(!mapload && A)
- notify_ghosts("\A [initial(species.prefix)] golem shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_GOLEM)
+ notify_ghosts("\A [initial(species.prefix)] golem shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_GOLEM, ignore_dnr_observers = TRUE)
if(has_owner && creator)
flavour_text = "You are a Golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. \
Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost."
@@ -372,7 +372,7 @@
flavour_text = "You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil. Be aware that if you do not live up to [owner.name]'s expectations, they can send you back to hell with a single thought. [owner.name]'s death will also return you to hell."
var/area/A = get_area(src)
if(!mapload && A)
- notify_ghosts("\A friendship shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE)
+ notify_ghosts("\A friendship shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
objectives = "Be [owner.name]'s friend, and keep [owner.name] alive, so you don't get sent back to hell."
spell = summoning_spell
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index d6f304653d..a6ba6424b1 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -100,6 +100,7 @@
number_of_rods = 2
smooth = SMOOTH_TRUE
canSmoothWith = null
+ obj_flags = CAN_BE_HIT | BLOCK_Z_FALL
/obj/structure/lattice/catwalk/deconstruction_hints(mob/user)
to_chat(user, "The supporting rods look like they could be cut.")
diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm
index 0e2f951f38..36dbcc1e28 100644
--- a/code/game/objects/structures/musician.dm
+++ b/code/game/objects/structures/musician.dm
@@ -104,12 +104,12 @@
playing = FALSE
hearing_mobs = null
return
- if(!lentext(note))
+ if(!length(note))
continue
var/cur_note = text2ascii(note) - 96
if(cur_note < 1 || cur_note > 7)
continue
- for(var/i=2 to lentext(note))
+ for(var/i=2 to length(note))
var/ni = copytext(note,i,i+1)
if(!text2num(ni))
if(ni == "#" || ni == "b" || ni == "n")
@@ -209,7 +209,7 @@
lines.Cut(MUSIC_MAXLINES + 1)
var/linenum = 1
for(var/l in lines)
- if(lentext(l) > MUSIC_MAXLINECHARS)
+ if(length(l) > MUSIC_MAXLINECHARS)
to_chat(usr, "Line [linenum] too long!")
lines.Remove(l)
else
@@ -236,11 +236,11 @@
if(!in_range(instrumentObj, usr))
return
- if(lentext(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
+ if(length(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no")
if(cont == "no")
break
- while(lentext(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
+ while(length(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
ParseSong(t)
else if(href_list["help"])
@@ -272,7 +272,7 @@
return
if(lines.len > MUSIC_MAXLINES)
return
- if(lentext(newline) > MUSIC_MAXLINECHARS)
+ if(length(newline) > MUSIC_MAXLINECHARS)
newline = copytext(newline, 1, MUSIC_MAXLINECHARS)
lines.Add(newline)
@@ -287,7 +287,7 @@
var/content = html_encode(input("Enter your line: ", instrumentObj.name, lines[num]) as text|null)
if(!content || !in_range(instrumentObj, usr))
return
- if(lentext(content) > MUSIC_MAXLINECHARS)
+ if(length(content) > MUSIC_MAXLINECHARS)
content = copytext(content, 1, MUSIC_MAXLINECHARS)
if(num > lines.len || num < 1)
return
diff --git a/code/game/objects/structures/signs/signs_maps.dm b/code/game/objects/structures/signs/signs_maps.dm
index f3188b90c2..1e3bfd6d36 100644
--- a/code/game/objects/structures/signs/signs_maps.dm
+++ b/code/game/objects/structures/signs/signs_maps.dm
@@ -50,7 +50,8 @@
name = "bar"
desc = "A direction sign, pointing out which way the Bar is."
icon_state = "direction_bar"
- /obj/structure/sign/directions/cafe
+
+/obj/structure/sign/directions/cafe
name = "cafe"
desc = "A direction sign, pointing out which way the Cafe is."
icon_state = "direction_cafe"
diff --git a/code/game/objects/structures/stairs.dm b/code/game/objects/structures/stairs.dm
new file mode 100644
index 0000000000..bd657fe1e8
--- /dev/null
+++ b/code/game/objects/structures/stairs.dm
@@ -0,0 +1,130 @@
+#define STAIR_TERMINATOR_AUTOMATIC 0
+#define STAIR_TERMINATOR_NO 1
+#define STAIR_TERMINATOR_YES 2
+
+// dir determines the direction of travel to go upwards (due to lack of sprites, currently only 1 and 2 make sense)
+// stairs require /turf/open/openspace as the tile above them to work
+// multiple stair objects can be chained together; the Z level transition will happen on the final stair object in the chain
+
+/obj/structure/stairs
+ name = "stairs"
+ icon = 'icons/obj/stairs.dmi'
+ icon_state = "stairs"
+ anchored = TRUE
+
+ var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/openspace
+ var/terminator_mode = STAIR_TERMINATOR_AUTOMATIC
+ var/turf/listeningTo
+
+/obj/structure/stairs/Initialize(mapload)
+ if(force_open_above)
+ force_open_above()
+ build_signal_listener()
+ update_surrounding()
+ return ..()
+
+/obj/structure/stairs/Destroy()
+ listeningTo = null
+ return ..()
+
+/obj/structure/stairs/Move() //Look this should never happen but...
+ . = ..()
+ if(force_open_above)
+ build_signal_listener()
+ update_surrounding()
+
+/obj/structure/stairs/proc/update_surrounding()
+ update_icon()
+ for(var/i in GLOB.cardinals)
+ var/turf/T = get_step(get_turf(src), i)
+ var/obj/structure/stairs/S = locate() in T
+ if(S)
+ S.update_icon()
+
+/obj/structure/stairs/Uncross(atom/movable/AM, turf/newloc)
+ if(!newloc || !AM)
+ return ..()
+ if(!isobserver(AM) && isTerminator() && (get_dir(src, newloc) == dir))
+ stair_ascend(AM)
+ return FALSE
+ return ..()
+
+/obj/structure/stairs/Cross(atom/movable/AM)
+ if(isTerminator() && (get_dir(src, AM) == dir))
+ return FALSE
+ return ..()
+
+/obj/structure/stairs/update_icon()
+ if(isTerminator())
+ icon_state = "stairs_t"
+ else
+ icon_state = "stairs"
+
+/obj/structure/stairs/proc/stair_ascend(atom/movable/AM)
+ var/turf/checking = get_step_multiz(get_turf(src), UP)
+ if(!istype(checking))
+ return
+ if(!checking.zPassIn(AM, UP, get_turf(src)))
+ return
+ var/turf/target = get_step_multiz(get_turf(src), (dir|UP))
+ if(istype(target) && !target.can_zFall(AM, null, get_step_multiz(target, DOWN))) //Don't throw them into a tile that will just dump them back down.
+ if(isliving(AM))
+ var/mob/living/L = AM
+ var/pulling = L.pulling
+ if(pulling)
+ L.pulling.forceMove(target)
+ L.forceMove(target)
+ L.start_pulling(pulling)
+ else
+ AM.forceMove(target)
+
+/obj/structure/stairs/vv_edit_var(var_name, var_value)
+ . = ..()
+ if(!.)
+ return
+ if(var_name != NAMEOF(src, force_open_above))
+ return
+ if(!var_value)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_TURF_MULTIZ_NEW)
+ listeningTo = null
+ else
+ build_signal_listener()
+ force_open_above()
+
+/obj/structure/stairs/proc/build_signal_listener()
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_TURF_MULTIZ_NEW)
+ var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
+ RegisterSignal(T, COMSIG_TURF_MULTIZ_NEW, .proc/on_multiz_new)
+ listeningTo = T
+
+/obj/structure/stairs/proc/force_open_above()
+ var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
+ if(T && !istype(T))
+ T.ChangeTurf(/turf/open/openspace)
+
+/obj/structure/stairs/proc/on_multiz_new(turf/source, dir)
+ if(dir == UP)
+ var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
+ if(T && !istype(T))
+ T.ChangeTurf(/turf/open/openspace)
+
+/obj/structure/stairs/intercept_zImpact(atom/movable/AM, levels = 1)
+ . = ..()
+ if(isTerminator())
+ . |= FALL_INTERCEPTED | FALL_NO_MESSAGE
+
+/obj/structure/stairs/proc/isTerminator() //If this is the last stair in a chain and should move mobs up
+ if(terminator_mode != STAIR_TERMINATOR_AUTOMATIC)
+ return (terminator_mode == STAIR_TERMINATOR_YES)
+ var/turf/T = get_turf(src)
+ if(!T)
+ return FALSE
+ var/turf/them = get_step(T, dir)
+ if(!them)
+ return FALSE
+ for(var/obj/structure/stairs/S in them)
+ if(S.dir == dir)
+ return FALSE
+ return TRUE
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index f1c5080c8f..6a055bbd35 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -15,7 +15,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
if(turf_type)
var/turf/newT = ChangeTurf(turf_type, baseturf_type, flags)
SSair.remove_from_active(newT)
- newT.CalculateAdjacentTurfs()
+ CALCULATE_ADJACENT_TURFS(newT)
SSair.add_to_active(newT,1)
/turf/proc/copyTurf(turf/T)
@@ -140,6 +140,8 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
newTurf.air = stashed_air
SSair.add_to_active(newTurf)
else
+ if(ispath(path,/turf/closed))
+ flags |= CHANGETURF_RECALC_ADJACENT
return ..()
// Take off the top layer turf and replace it with the next baseturf down
@@ -263,7 +265,10 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
//If you modify this function, ensure it works correctly with lateloaded map templates.
/turf/proc/AfterChange(flags) //called after a turf has been replaced in ChangeTurf()
levelupdate()
- CalculateAdjacentTurfs()
+ if(flags & CHANGETURF_RECALC_ADJACENT)
+ ImmediateCalculateAdjacentTurfs()
+ else
+ CALCULATE_ADJACENT_TURFS(src)
//update firedoor adjacency
var/list/turfs_to_check = get_adjacent_open_turfs(src) | src
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index bd24e0ff93..efee9cfa5a 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -16,6 +16,22 @@
if(wet)
AddComponent(/datum/component/wet_floor, wet, INFINITY, 0, INFINITY, TRUE)
+//direction is direction of travel of A
+/turf/open/zPassIn(atom/movable/A, direction, turf/source)
+ return (direction == DOWN)
+
+//direction is direction of travel of A
+/turf/open/zPassOut(atom/movable/A, direction, turf/destination)
+ return (direction == UP)
+
+//direction is direction of travel of air
+/turf/open/zAirIn(direction, turf/source)
+ return (direction == DOWN)
+
+//direction is direction of travel of air
+/turf/open/zAirOut(direction, turf/source)
+ return (direction == UP)
+
/turf/open/MouseDrop_T(atom/dropping, mob/user)
. = ..()
if(dropping == user && isliving(user))
@@ -184,43 +200,14 @@
update_visuals()
current_cycle = times_fired
-
- //cache some vars
- var/list/atmos_adjacent_turfs = src.atmos_adjacent_turfs
-
- for(var/direction in GLOB.cardinals)
- var/turf/open/enemy_tile = get_step(src, direction)
- if(!istype(enemy_tile))
- if (atmos_adjacent_turfs)
- atmos_adjacent_turfs -= enemy_tile
- continue
+ ImmediateCalculateAdjacentTurfs()
+ for(var/i in atmos_adjacent_turfs)
+ var/turf/open/enemy_tile = i
var/datum/gas_mixture/enemy_air = enemy_tile.return_air()
-
- //only check this turf, if it didn't check us when it was initalized
- if(enemy_tile.current_cycle < times_fired)
- if(CANATMOSPASS(src, enemy_tile))
- LAZYINITLIST(atmos_adjacent_turfs)
- LAZYINITLIST(enemy_tile.atmos_adjacent_turfs)
- atmos_adjacent_turfs[enemy_tile] = TRUE
- enemy_tile.atmos_adjacent_turfs[src] = TRUE
- else
- if (atmos_adjacent_turfs)
- atmos_adjacent_turfs -= enemy_tile
- if (enemy_tile.atmos_adjacent_turfs)
- enemy_tile.atmos_adjacent_turfs -= src
- UNSETEMPTY(enemy_tile.atmos_adjacent_turfs)
- continue
- else
- if (!atmos_adjacent_turfs || !atmos_adjacent_turfs[enemy_tile])
- continue
-
if(!excited && air.compare(enemy_air))
//testing("Active turf found. Return value of compare(): [is_active]")
excited = TRUE
SSair.active_turfs |= src
- UNSETEMPTY(atmos_adjacent_turfs)
- if (atmos_adjacent_turfs)
- src.atmos_adjacent_turfs = atmos_adjacent_turfs
/turf/open/proc/GetHeatCapacity()
. = air.heat_capacity()
@@ -267,14 +254,15 @@
if(!(lube&GALOSHES_DONT_HELP)) //can't slip while buckled unless it's lube.
return 0
else
- if(C.lying || !(C.status_flags & CANKNOCKDOWN)) // can't slip unbuckled mob if they're lying or can't fall.
+ if(!(lube&SLIP_WHEN_CRAWLING) && (C.lying || !(C.status_flags & CANKNOCKDOWN))) // can't slip unbuckled mob if they're lying or can't fall.
return 0
- if(C.m_intent == MOVE_INTENT_WALK && (lube&NO_SLIP_WHEN_WALKING))
- return 0
- if(ishuman(C) && (lube&NO_SLIP_WHEN_WALKING))
- var/mob/living/carbon/human/H = C
- if(!H.sprinting && H.getStaminaLoss() <= 20)
+ if(lube & NO_SLIP_WHEN_WALKING)
+ if(C.m_intent == MOVE_INTENT_WALK)
return 0
+ if(ishuman(C) && !(lube & SLIP_WHEN_JOGGING))
+ var/mob/living/carbon/human/H = C
+ if(!H.sprinting && H.getStaminaLoss() <= 20)
+ return 0
if(!(lube&SLIDE_ICE))
to_chat(C, "You slipped[ O ? " on the [O.name]" : ""]!")
playsound(C.loc, 'sound/misc/slip.ogg', 50, 1, -3)
diff --git a/code/game/turfs/openspace/openspace.dm b/code/game/turfs/openspace/openspace.dm
new file mode 100644
index 0000000000..e68aabcd08
--- /dev/null
+++ b/code/game/turfs/openspace/openspace.dm
@@ -0,0 +1,134 @@
+/turf/open/openspace
+ name = "open space"
+ desc = "Watch your step!"
+ icon_state = "grey"
+ baseturfs = /turf/open/openspace
+ CanAtmosPassVertical = ATMOS_PASS_YES
+ //mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ var/can_cover_up = TRUE
+ var/can_build_on = TRUE
+
+/turf/open/openspace/debug/update_multiz()
+ ..()
+ return TRUE
+
+/turf/open/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
+ . = ..()
+ plane = FLOOR_OPENSPACE_PLANE
+ layer = OPENSPACE_LAYER
+ return INITIALIZE_HINT_LATELOAD
+
+/turf/open/openspace/LateInitialize()
+ update_multiz(TRUE, TRUE)
+
+/turf/open/openspace/Destroy()
+ vis_contents.len = 0
+ return ..()
+
+/turf/open/openspace/update_multiz(prune_on_fail = FALSE, init = FALSE)
+ . = ..()
+ var/turf/T = below()
+ if(!T)
+ vis_contents.len = 0
+ if(prune_on_fail)
+ ChangeTurf(/turf/open/floor/plating)
+ return FALSE
+ if(init)
+ vis_contents += T
+ return TRUE
+
+/turf/open/openspace/multiz_turf_del(turf/T, dir)
+ if(dir != DOWN)
+ return
+ update_multiz()
+
+/turf/open/openspace/multiz_turf_new(turf/T, dir)
+ if(dir != DOWN)
+ return
+ update_multiz()
+
+/turf/open/openspace/zAirIn()
+ return TRUE
+
+/turf/open/openspace/zAirOut()
+ return TRUE
+
+/turf/open/openspace/zPassIn(atom/movable/A, direction, turf/source)
+ return TRUE
+
+/turf/open/openspace/zPassOut(atom/movable/A, direction, turf/destination)
+ if(A.anchored)
+ return FALSE
+ for(var/obj/O in contents)
+ if(O.obj_flags & BLOCK_Z_FALL)
+ return FALSE
+ return TRUE
+
+/turf/open/openspace/proc/CanCoverUp()
+ return can_cover_up
+
+/turf/open/openspace/proc/CanBuildHere()
+ return can_build_on
+
+/turf/open/openspace/attackby(obj/item/C, mob/user, params)
+ ..()
+ if(!CanBuildHere())
+ return
+ 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 construct a catwalk.")
+ playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
+ new/obj/structure/lattice/catwalk(src)
+ else
+ to_chat(user, "You need two rods to build a catwalk!")
+ return
+ 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))
+ if(!CanCoverUp())
+ return
+ 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.")
+ PlaceOnTop(/turf/open/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/open/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
+ if(!CanBuildHere())
+ return FALSE
+
+ switch(the_rcd.mode)
+ if(RCD_FLOORWALL)
+ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ if(L)
+ return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 1)
+ else
+ return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3)
+ return FALSE
+
+/turf/open/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
+ switch(passed_mode)
+ if(RCD_FLOORWALL)
+ to_chat(user, "You build a floor.")
+ PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
+ return TRUE
+ return FALSE
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 036f54c710..191d9b0242 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -144,5 +144,5 @@
..()
ScrapeAway()
-/turf/open/floor/plating/foam/tool_act(mob/living/user, obj/tool/I, tool_type)
+/turf/open/floor/plating/foam/tool_act(mob/living/user, obj/item/I, tool_type)
return
diff --git a/code/game/turfs/simulated/wall/reinf_walls.dm b/code/game/turfs/simulated/wall/reinf_walls.dm
index d52a3bcc23..0d9bff1bdf 100644
--- a/code/game/turfs/simulated/wall/reinf_walls.dm
+++ b/code/game/turfs/simulated/wall/reinf_walls.dm
@@ -227,3 +227,29 @@
/turf/closed/wall/r_wall/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
if(the_rcd.canRturf)
return ..()
+
+/turf/closed/wall/r_wall/syndicate
+ name = "hull"
+ desc = "The armored hull of an ominous looking ship."
+ icon = 'icons/turf/walls/plastitanium_wall.dmi'
+ icon_state = "map-shuttle"
+ explosion_block = 20
+ sheet_type = /obj/item/stack/sheet/mineral/plastitanium
+ smooth = SMOOTH_MORE|SMOOTH_DIAGONAL
+ canSmoothWith = list(/turf/closed/wall/r_wall/syndicate, /turf/closed/wall/mineral/plastitanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/plastitanium, /obj/structure/shuttle/engine, /obj/structure/falsewall/plastitanium)
+
+/turf/closed/wall/r_wall/syndicate/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
+ return FALSE
+
+/turf/closed/wall/r_wall/syndicate/nodiagonal
+ smooth = SMOOTH_MORE
+ icon_state = "map-shuttle_nd"
+
+/turf/closed/wall/r_wall/syndicate/nosmooth
+ icon = 'icons/turf/shuttle.dmi'
+ icon_state = "wall"
+ smooth = SMOOTH_FALSE
+
+/turf/closed/wall/r_wall/syndicate/overspace
+ icon_state = "map-overspace"
+ fixed_underlay = list("space"=1)
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 9ebe8f3c19..a5931abf9d 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -12,7 +12,7 @@
var/destination_x
var/destination_y
- var/global/datum/gas_mixture/immutable/space/space_gas = new
+ var/static/datum/gas_mixture/immutable/space/space_gas = new
plane = PLANE_SPACE
layer = SPACE_LAYER
light_power = 0.25
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index ebf6f6626c..d618e457b0 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -39,7 +39,7 @@
return FALSE
. = ..()
-/turf/Initialize()
+/turf/Initialize(mapload)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
@@ -62,12 +62,21 @@
add_overlay(/obj/effect/fullbright)
if(requires_activation)
- CalculateAdjacentTurfs()
+ CALCULATE_ADJACENT_TURFS(src)
SSair.add_to_active(src)
if (light_power && light_range)
update_light()
+ var/turf/T = SSmapping.get_turf_above(src)
+ if(T)
+ T.multiz_turf_new(src, DOWN)
+ SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, DOWN)
+ T = SSmapping.get_turf_below(src)
+ if(T)
+ T.multiz_turf_new(src, UP)
+ SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, UP)
+
if (opacity)
has_opaque_atom = TRUE
@@ -76,13 +85,19 @@
return INITIALIZE_HINT_NORMAL
/turf/proc/Initalize_Atmos(times_fired)
- CalculateAdjacentTurfs()
+ CALCULATE_ADJACENT_TURFS(src)
/turf/Destroy(force)
. = QDEL_HINT_IWILLGC
if(!changing_turf)
stack_trace("Incorrect turf deletion")
changing_turf = FALSE
+ var/turf/T = SSmapping.get_turf_above(src)
+ if(T)
+ T.multiz_turf_del(src, DOWN)
+ T = SSmapping.get_turf_below(src)
+ if(T)
+ T.multiz_turf_del(src, UP)
if(force)
..()
//this will completely wipe turf state
@@ -105,6 +120,60 @@
return
user.Move_Pulled(src)
+/turf/proc/multiz_turf_del(turf/T, dir)
+
+/turf/proc/multiz_turf_new(turf/T, dir)
+
+//zPassIn doesn't necessarily pass an atom!
+//direction is direction of travel of air
+/turf/proc/zPassIn(atom/movable/A, direction, turf/source)
+ return FALSE
+
+//direction is direction of travel of air
+/turf/proc/zPassOut(atom/movable/A, direction, turf/destination)
+ return FALSE
+
+//direction is direction of travel of air
+/turf/proc/zAirIn(direction, turf/source)
+ return FALSE
+
+//direction is direction of travel of air
+/turf/proc/zAirOut(direction, turf/source)
+ return FALSE
+
+/turf/proc/zImpact(atom/movable/A, levels = 1, turf/prev_turf)
+ var/flags = NONE
+ var/mov_name = A.name
+ for(var/i in contents)
+ var/atom/thing = i
+ flags |= thing.intercept_zImpact(A, levels)
+ if(flags & FALL_STOP_INTERCEPTING)
+ break
+ if(prev_turf && !(flags & FALL_NO_MESSAGE))
+ prev_turf.visible_message("[mov_name] falls through [prev_turf]!")
+ if(flags & FALL_INTERCEPTED)
+ return
+ if(zFall(A, ++levels))
+ return FALSE
+ A.visible_message("[A] crashes into [src]!")
+ A.onZImpact(src, levels)
+ return TRUE
+
+/turf/proc/can_zFall(atom/movable/A, levels = 1, turf/target)
+ return zPassOut(A, DOWN, target) && target.zPassIn(A, DOWN, src)
+
+/turf/proc/zFall(atom/movable/A, levels = 1, force = FALSE)
+ var/turf/target = get_step_multiz(src, DOWN)
+ if(!target || (!isobj(A) && !ismob(A)))
+ return FALSE
+ if(!force && (!can_zFall(A, levels, target) || !A.can_zFall(src, levels, target, DOWN)))
+ return FALSE
+ A.zfalling = TRUE
+ A.forceMove(target)
+ A.zfalling = FALSE
+ target.zImpact(A, levels, src)
+ return TRUE
+
/turf/proc/handleRCL(obj/item/twohanded/rcl/C, mob/user)
if(C.loaded)
for(var/obj/structure/cable/LC in src)
@@ -196,6 +265,9 @@
if(O.obj_flags & FROZEN)
O.make_unfrozen()
+ if(!AM.zfalling)
+ zFall(AM)
+
/turf/proc/is_plasteel_floor()
return FALSE
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 626fa7f66f..cb5b33ae08 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -1,7 +1,7 @@
//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless
//the procs are cause you can't put the comments in the GLOB var define
-GLOBAL_PROTECT(admin_verbs_default)
GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
+GLOBAL_PROTECT(admin_verbs_default)
/world/proc/AVerbsDefault()
return list(
/client/proc/deadmin, /*destroys our own admin datum so we can play as a regular player*/
@@ -13,8 +13,8 @@ GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
/client/proc/toggleprayers,
/client/proc/toggleadminhelpsound
)
-GLOBAL_PROTECT(admin_verbs_admin)
GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
+GLOBAL_PROTECT(admin_verbs_admin)
/world/proc/AVerbsAdmin()
return list(
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
@@ -78,11 +78,10 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
/client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/
/datum/admins/proc/open_borgopanel
)
-GLOBAL_PROTECT(admin_verbs_ban)
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/DB_ban_panel, /client/proc/stickybanpanel))
-GLOBAL_PROTECT(admin_verbs_sounds)
+GLOBAL_PROTECT(admin_verbs_ban)
GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_sound, /client/proc/set_round_end_sound))
-GLOBAL_PROTECT(admin_verbs_fun)
+GLOBAL_PROTECT(admin_verbs_sounds)
GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/cmd_admin_dress,
/client/proc/cmd_admin_gib_self,
@@ -108,9 +107,9 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/admin_away,
/client/proc/roll_dices //CIT CHANGE - Adds dice verb
))
-GLOBAL_PROTECT(admin_verbs_spawn)
+GLOBAL_PROTECT(admin_verbs_fun)
GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character))
-GLOBAL_PROTECT(admin_verbs_server)
+GLOBAL_PROTECT(admin_verbs_spawn)
GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
/world/proc/AVerbsServer()
return list(
@@ -129,7 +128,7 @@ GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
/client/proc/adminchangemap,
/client/proc/toggle_hub
)
-GLOBAL_PROTECT(admin_verbs_debug)
+GLOBAL_PROTECT(admin_verbs_server)
GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
/world/proc/AVerbsDebug()
return list(
@@ -171,15 +170,15 @@ GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
/datum/admins/proc/create_or_modify_area,
/client/proc/generate_wikichem_list //DO NOT PRESS UNLESS YOU WANT SUPERLAG
)
-GLOBAL_PROTECT(admin_verbs_possess)
+GLOBAL_PROTECT(admin_verbs_debug)
GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release))
-GLOBAL_PROTECT(admin_verbs_permissions)
+GLOBAL_PROTECT(admin_verbs_possess)
GLOBAL_LIST_INIT(admin_verbs_permissions, list(/client/proc/edit_admin_permissions))
-GLOBAL_PROTECT(admin_verbs_poll)
+GLOBAL_PROTECT(admin_verbs_permissions)
GLOBAL_LIST_INIT(admin_verbs_poll, list(/client/proc/create_poll))
//verbs which can be hidden - needs work
-GLOBAL_PROTECT(admin_verbs_hideable)
+GLOBAL_PROTECT(admin_verbs_poll)
GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/set_ooc,
/client/proc/reset_ooc,
@@ -247,6 +246,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/cmd_admin_man_up, //CIT CHANGE - adds man up verb
/client/proc/cmd_admin_man_up_global //CIT CHANGE - ditto
))
+GLOBAL_PROTECT(admin_verbs_hideable)
/client/proc/add_admin_verbs()
if(holder)
diff --git a/code/modules/admin/sql_message_system.dm b/code/modules/admin/sql_message_system.dm
index 72ec3da8f9..7b59e72403 100644
--- a/code/modules/admin/sql_message_system.dm
+++ b/code/modules/admin/sql_message_system.dm
@@ -504,7 +504,7 @@
output += ruler
var/datum/browser/browser = new(usr, "Note panel", "Manage player notes", 1000, 500)
var/datum/asset/notes_assets = get_asset_datum(/datum/asset/simple/notes)
- notes_assets.send(src)
+ notes_assets.send(usr.client)
browser.set_content(jointext(output, ""))
browser.open()
@@ -556,7 +556,7 @@
/proc/convert_notes_sql(ckey)
if(!fexists(NOTESFILE))
return
-
+
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile)
log_game("Error: Cannot access [NOTESFILE]")
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index b0b9190556..8b105da43b 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1347,7 +1347,7 @@
else if(href_list["f_secret"])
return HandleFSecret()
-
+
else if(href_list["f_dynamic_roundstart"])
if(!check_rights(R_ADMIN))
return
@@ -1593,7 +1593,7 @@
GLOB.dynamic_stacking_limit = input(usr,"Change the threat limit at which round-endings rulesets will start to stack.", "Change stacking limit", null) as num
log_admin("[key_name(usr)] set 'stacking_limit' to [GLOB.dynamic_stacking_limit].")
message_admins("[key_name(usr)] set 'stacking_limit' to [GLOB.dynamic_stacking_limit].")
- dynamic_mode_options(usr)
+ dynamic_mode_options(usr)
else if(href_list["f_dynamic_high_pop_limit"])
if(!check_rights(R_ADMIN))
@@ -1612,7 +1612,7 @@
log_admin("[key_name(usr)] set 'high_pop_limit' to [GLOB.dynamic_high_pop_limit].")
message_admins("[key_name(usr)] set 'high_pop_limit' to [GLOB.dynamic_high_pop_limit].")
- dynamic_mode_options(usr)
+ dynamic_mode_options(usr)
else if(href_list["f_dynamic_forced_threat"])
if(!check_rights(R_ADMIN))
@@ -1631,7 +1631,7 @@
log_admin("[key_name(usr)] set 'forced_threat_level' to [GLOB.dynamic_forced_threat_level].")
message_admins("[key_name(usr)] set 'forced_threat_level' to [GLOB.dynamic_forced_threat_level].")
- dynamic_mode_options(usr)
+ dynamic_mode_options(usr)
else if(href_list["c_mode2"])
if(!check_rights(R_ADMIN|R_SERVER))
@@ -2442,7 +2442,7 @@
return
src.admincaster_feed_channel.channel_name = stripped_input(usr, "Provide a Feed Channel Name.", "Network Channel Handler", "")
while (findtext(src.admincaster_feed_channel.channel_name," ") == 1)
- src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,lentext(src.admincaster_feed_channel.channel_name)+1)
+ src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,length(src.admincaster_feed_channel.channel_name)+1)
src.access_news_network()
else if(href_list["ac_set_channel_lock"])
@@ -2484,7 +2484,7 @@
return
src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story.", "Network Channel Handler", ""))
while (findtext(src.admincaster_feed_message.returnBody(-1)," ") == 1)
- src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.returnBody(-1),2,lentext(src.admincaster_feed_message.returnBody(-1))+1)
+ src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.returnBody(-1),2,length(src.admincaster_feed_message.returnBody(-1))+1)
src.access_news_network()
else if(href_list["ac_submit_new_message"])
@@ -2545,7 +2545,7 @@
return
src.admincaster_wanted_message.criminal = adminscrub(input(usr, "Provide the name of the Wanted person.", "Network Security Handler", ""))
while(findtext(src.admincaster_wanted_message.criminal," ") == 1)
- src.admincaster_wanted_message.criminal = copytext(admincaster_wanted_message.criminal,2,lentext(admincaster_wanted_message.criminal)+1)
+ src.admincaster_wanted_message.criminal = copytext(admincaster_wanted_message.criminal,2,length(admincaster_wanted_message.criminal)+1)
src.access_news_network()
else if(href_list["ac_set_wanted_desc"])
@@ -2553,7 +2553,7 @@
return
src.admincaster_wanted_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important.", "Network Security Handler", ""))
while (findtext(src.admincaster_wanted_message.body," ") == 1)
- src.admincaster_wanted_message.body = copytext(src.admincaster_wanted_message.body,2,lentext(src.admincaster_wanted_message.body)+1)
+ src.admincaster_wanted_message.body = copytext(src.admincaster_wanted_message.body,2,length(src.admincaster_wanted_message.body)+1)
src.access_news_network()
else if(href_list["ac_submit_wanted"])
diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index b19b2a91d8..072fbaa123 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -61,7 +61,7 @@
var/output = "Radio Report
"
for (var/fq in SSradio.frequencies)
output += "Freq: [fq]
"
- var/list/datum/radio_frequency/fqs = SSradio.frequencies[fq]
+ var/datum/radio_frequency/fqs = SSradio.frequencies[fq]
if (!fqs)
output += " ERROR
"
continue
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 8559a3235e..2b8d365e15 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -19,7 +19,6 @@
//- Identify how hard it is to break into the area and where the weak points are
//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels.
-GLOBAL_PROTECT(admin_verbs_debug_mapping)
GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/camera_view, //-errorage
/client/proc/sec_camera_report, //-errorage
@@ -50,6 +49,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/debug_z_levels,
/client/proc/place_ruin
))
+GLOBAL_PROTECT(admin_verbs_debug_mapping)
/obj/effect/debugging/mapfix_marker
name = "map fix marker"
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index e70ea1c1b3..644b2729e0 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -307,11 +307,11 @@ GLOBAL_PROTECT(VVpixelmovement)
// the type with the base type removed from the begaining
var/fancytype = types[D.type]
if (findtext(fancytype, types[type]))
- fancytype = copytext(fancytype, lentext(types[type])+1)
- var/shorttype = copytext("[D.type]", lentext("[type]")+1)
- if (lentext(shorttype) > lentext(fancytype))
+ fancytype = copytext(fancytype, length(types[type])+1)
+ var/shorttype = copytext("[D.type]", length("[type]")+1)
+ if (length(shorttype) > length(fancytype))
shorttype = fancytype
- if (!lentext(shorttype))
+ if (!length(shorttype))
shorttype = "/"
.["[D]([shorttype])[REF(D)]#[i]"] = D
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index d7dd8db08d..7a222d1ebc 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -949,7 +949,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
| Uniform: |
- [uniform_select]
+ [uniform_select]
|
diff --git a/code/modules/admin/verbs/spawnobjasmob.dm b/code/modules/admin/verbs/spawnobjasmob.dm
index 621e6c3618..1d3cf95222 100644
--- a/code/modules/admin/verbs/spawnobjasmob.dm
+++ b/code/modules/admin/verbs/spawnobjasmob.dm
@@ -16,10 +16,10 @@
var/obj/chosen_obj = text2path(chosen)
var/list/settings = list(
- "mainsettings" = list(
- "name" = list("desc" = "Name", "type" = "string", "value" = "Bob"),
+ "mainsettings" = list(
+ "name" = list("desc" = "Name", "type" = "string", "value" = "Bob"),
"maxhealth" = list("desc" = "Max. health", "type" = "number", "value" = 100),
- "access" = list("desc" = "Access ID", "type" = "datum", "path" = "/obj/item/card/id", "value" = "Default"),
+ "access" = list("desc" = "Access ID", "type" = "datum", "path" = "/obj/item/card/id", "value" = "Default"),
"objtype" = list("desc" = "Base obj type", "type" = "datum", "path" = "/obj", "value" = "[chosen]"),
"googlyeyes" = list("desc" = "Googly eyes", "type" = "boolean", "value" = "No"),
"disableai" = list("desc" = "Disable AI", "type" = "boolean", "value" = "Yes"),
@@ -27,7 +27,7 @@
"dropitem" = list("desc" = "Drop obj on death", "type" = "boolean", "value" = "Yes"),
"mobtype" = list("desc" = "Base mob type", "type" = "datum", "path" = "/mob/living/simple_animal/hostile/mimic/copy", "value" = "/mob/living/simple_animal/hostile/mimic/copy"),
"ckey" = list("desc" = "ckey", "type" = "ckey", "value" = "none"),
- )
+ )
)
var/list/prefreturn = presentpreflikepicker(usr,"Customize mob", "Customize mob", Button1="Ok", width = 450, StealFocus = 1,Timeout = 0, settings=settings)
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index c1088cbb3d..37652d1887 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -393,23 +393,22 @@
name = "Dissection Guide"
icon_state = "alienpaper_words"
info = {"Dissection for Dummies
-
-
- 1.Acquire fresh specimen.
- 2.Put the specimen on operating table.
- 3.Apply surgical drapes, preparing for experimental dissection.
- 4.Apply scalpel to specimen's torso.
- 5.Clamp bleeders on specimen's torso with a hemostat.
- 6.Retract skin of specimen's torso with a retractor.
- 7.Apply scalpel again to specimen's torso.
- 8.Search through the specimen's torso with your hands to remove any superfluous organs.
- 9.Insert replacement gland (Retrieve one from gland storage).
- 10.Consider dressing the specimen back to not disturb the habitat.
- 11.Put the specimen in the experiment machinery.
- 12.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.
- 13.You will receive one supply credit, and the subject will be counted towards your quota.
-
-Congratulations! You are now trained for invasive xenobiology research!"}
+
+ 1.Acquire fresh specimen.
+ 2.Put the specimen on operating table.
+ 3.Apply surgical drapes, preparing for experimental dissection.
+ 4.Apply scalpel to specimen's torso.
+ 5.Clamp bleeders on specimen's torso with a hemostat.
+ 6.Retract skin of specimen's torso with a retractor.
+ 7.Apply scalpel again to specimen's torso.
+ 8.Search through the specimen's torso with your hands to remove any superfluous organs.
+ 9.Insert replacement gland (Retrieve one from gland storage).
+ 10.Consider dressing the specimen back to not disturb the habitat.
+ 11.Put the specimen in the experiment machinery.
+ 12.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.
+ 13.You will receive one supply credit, and the subject will be counted towards your quota.
+
+ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/paper/guides/antag/abductor/update_icon()
return
diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm
index a35cbbf0e4..e9a815ac38 100644
--- a/code/modules/antagonists/abductor/equipment/gland.dm
+++ b/code/modules/antagonists/abductor/equipment/gland.dm
@@ -73,7 +73,7 @@
clear_mind_control()
..()
-/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0)
+/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
if(special != 2 && uses) // Special 2 means abductor surgery
Start()
@@ -124,7 +124,7 @@
mind_control_uses = 1
mind_control_duration = 2400
-/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0)
+/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
owner.faction |= "slime"
owner.grant_language(/datum/language/slime)
@@ -286,7 +286,7 @@
mind_control_uses = 2
mind_control_duration = 900
-/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0)
+/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
index 8000be87e6..b5a218131b 100644
--- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
@@ -147,6 +147,11 @@
if(iscarbon(L))
var/mob/living/carbon/M = L
M.uncuff()
+ var/brutedamage = L.getBruteLoss()
+ var/burndamage = L.getFireLoss()
+ if(brutedamage || burndamage)
+ L.adjustBruteLoss(-(brutedamage * 0.25))
+ L.adjustFireLoss(-(burndamage * 0.25))
L.Knockdown(50) //Completely defenseless for five seconds - mainly to give them time to read over the information they've just been presented with
if(iscarbon(L))
var/mob/living/carbon/C = L
@@ -262,7 +267,7 @@
clockwork_desc = "A sigil that will drain non-Servants that remain on it. Servants that remain on it will be healed if it has any vitality drained."
icon_state = "sigilvitality"
layer = SIGIL_LAYER
- alpha = 75
+ alpha = 125
color = "#123456"
affects_servants = TRUE
stat_affected = DEAD
diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
index ec712f2eec..7066109979 100644
--- a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
@@ -64,7 +64,7 @@
/obj/item/clockwork/slab/cyborg/janitor //six scriptures, plus a fabricator
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \
- /datum/clockwork_scripture/create_object/stargazer, /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
+ /datum/clockwork_scripture/create_object/stargazer, /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
/obj/item/clockwork/slab/cyborg/service //six scriptures, plus xray vision
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant,/datum/clockwork_scripture/create_object/stargazer, \
diff --git a/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm b/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm
index 2be0fdde11..f53796f02a 100644
--- a/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm
+++ b/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm
@@ -15,7 +15,7 @@
. = ..()
var/area/A = get_area(src)
if(A && construct_type)
- notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_CONSTRUCT)
+ notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_CONSTRUCT, ignore_dnr_observers = TRUE)
GLOB.poi_list += src
LAZYADD(GLOB.mob_spawners[name], src)
@@ -39,7 +39,9 @@
. = ..()
//ATTACK GHOST IGNORING PARENT RETURN VALUE
-/obj/item/clockwork/construct_chassis/attack_ghost(mob/user)
+/obj/item/clockwork/construct_chassis/attack_ghost(mob/dead/observer/user)
+ if(!user.can_reenter_round())
+ return FALSE
if(!SSticker.mode)
to_chat(user, "You cannot use that before the game has started.")
return
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
index 82c1291433..4ab481cfe2 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
@@ -80,7 +80,7 @@
power_cost = 125
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/submission
- creator_message = "A luminous sigil appears below you. Any non-Servants to cross it will be converted after 8 seconds if they do not move."
+ creator_message = "A luminous sigil appears below you. Any non-Servants to cross it will be converted and healed of some of their wounds after 8 seconds if they do not move."
usage_tip = "This is the primary conversion method, though it will not penetrate mindshield implants."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
diff --git a/code/modules/antagonists/clockcult/clock_structures/_trap_object.dm b/code/modules/antagonists/clockcult/clock_structures/_trap_object.dm
index 00a3406da1..491f1d24b3 100644
--- a/code/modules/antagonists/clockcult/clock_structures/_trap_object.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/_trap_object.dm
@@ -71,6 +71,7 @@
return TRUE
/obj/structure/destructible/clockwork/trap/proc/activate()
+ return
//These objects send signals to normal traps to activate
/obj/structure/destructible/clockwork/trap/trigger
@@ -79,6 +80,14 @@
break_message = "The trigger breaks apart!"
density = FALSE
+/obj/structure/destructible/clockwork/trap/trigger/Initialize()
+ . = ..()
+ for(var/obj/structure/destructible/clockwork/trap/T in get_turf(src))
+ if(!istype(T, /obj/structure/destructible/clockwork/trap/trigger))
+ wired_to += T
+ T.wired_to += src
+ to_chat(usr, "[src] automatically links with [T] beneath it.")
+
/obj/structure/destructible/clockwork/trap/trigger/activate()
for(var/obj/structure/destructible/clockwork/trap/T in wired_to)
if(istype(T, /obj/structure/destructible/clockwork/trap/trigger)) //Triggers don't go off multiple times
diff --git a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
index 7afd9e7dbc..35c1ea7bdd 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
@@ -110,9 +110,7 @@
if(!(BI.resistance_flags & ON_FIRE))
BI.fire_act()
continue
- if(is_servant_of_ratvar(L) || (HAS_TRAIT(L, TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE))
- continue
- if(L.stat || L.lying)
+ if(is_servant_of_ratvar(L) || (HAS_TRAIT(L, TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE) || L.incapacitated(TRUE))
continue
if (iscarbon(L))
var/mob/living/carbon/c = L
diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm
index 94f0ba7112..af29bc9b31 100644
--- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm
@@ -7,18 +7,10 @@
icon_state = "pressure_sensor"
alpha = 50
-/obj/structure/destructible/clockwork/trap/trigger/Initialize()
- . = ..()
- for(var/obj/structure/destructible/clockwork/trap/T in get_turf(src))
- if(!istype(T, /obj/structure/destructible/clockwork/trap/trigger))
- wired_to += T
- T.wired_to += src
- to_chat(usr, "[src] automatically links with [T] beneath it.")
-
/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/Crossed(atom/movable/AM)
if(isliving(AM) && !is_servant_of_ratvar(AM))
var/mob/living/L = AM
- if(L.stat || L.m_intent == MOVE_INTENT_WALK || L.lying)
+ if(L.stat || L.m_intent == MOVE_INTENT_WALK || L.movement_type & (FLYING|FLOATING))
return
audible_message("*click*")
playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 06ea2cbe0a..943e76b4ee 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -493,7 +493,7 @@
desc = "You peer within this smokey orb and glimpse terrible fates befalling the escape shuttle."
icon = 'icons/obj/cult.dmi'
icon_state ="shuttlecurse"
- var/global/curselimit = 0
+ var/static/curselimit = 0
/obj/item/shuttle_curse/attack_self(mob/living/user)
if(!iscultist(user))
@@ -530,7 +530,7 @@
playsound(user.loc, 'sound/effects/glassbr1.ogg', 50, 1)
qdel(src)
sleep(20)
- var/global/list/curses
+ var/static/list/curses
if(!curses)
curses = list("A fuel technician just slit his own throat and begged for death.",
"The shuttle's navigation programming was replaced by a file containing just two words: IT COMES.",
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index f0fc59834c..1cbf267277 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -249,7 +249,7 @@ structure_check() searches for nearby cultist structures required for the invoca
convertee.adjustFireLoss(-(burndamage * 0.75))
convertee.visible_message("[convertee] writhes in pain \
[brutedamage || burndamage ? "even as [convertee.p_their()] wounds heal and close" : "as the markings below [convertee.p_them()] glow a bloody red"]!", \
- "AAAAAAAAAAAAAA-")
+ "AAAAAAAAAAAAAA-")
SSticker.mode.add_cultist(convertee.mind, 1)
new /obj/item/melee/cultblade/dagger(get_turf(src))
convertee.mind.special_role = ROLE_CULTIST
@@ -848,10 +848,10 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
log_game("Manifest rune failed - too many summoned ghosts")
return list()
- notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src)
+ notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src, ignore_dnr_observers = TRUE)
var/list/ghosts_on_rune = list()
for(var/mob/dead/observer/O in T)
- if(O.client && !jobban_isbanned(O, ROLE_CULTIST) && !QDELETED(src) && !QDELETED(O))
+ if(!QDELETED(O) && O.client && !jobban_isbanned(O, ROLE_CULTIST) && !QDELETED(src) && O.can_reenter_round())
ghosts_on_rune += O
if(!ghosts_on_rune.len)
to_chat(user, "There are no spirits near [src]!")
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index df761ac183..06200073bb 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -106,7 +106,7 @@
/mob/living/carbon/true_devil/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
return 666
-/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
+/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
if(mind && has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
return ..() //flashes don't stop devils UNLESS it's their bane.
diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
index 779dfb43a7..78e4d38b3c 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
@@ -64,7 +64,7 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
for(var/obj/machinery/computer/camera_advanced/shuttle_docker/D in GLOB.jam_on_wardec)
D.jammed = TRUE
- GLOB.war_declared = TRUE
+ GLOB.war_declared = TRUE
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
var/actual_players = GLOB.joined_player_list.len - nukeops.len
var/tc_malus = 0
diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
index add3c1d9b0..d0e6dafbc1 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
@@ -343,10 +343,10 @@
/obj/machinery/nuclearbomb/proc/set_anchor()
- if(!isinspace())
- anchored = !anchored
- else
+ if(isinspace() && !anchored)
to_chat(usr, "There is nothing to anchor to!")
+ else
+ anchored = !anchored
/obj/machinery/nuclearbomb/proc/set_safety()
safety = !safety
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index f45555a6ee..f27da5f667 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -94,7 +94,7 @@
user.temporarilyRemoveItemFromInventory(src, TRUE)
src.Insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E
-/obj/item/organ/heart/demon/Insert(mob/living/carbon/M, special = 0)
+/obj/item/organ/heart/demon/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
if(M.mind)
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm
index 87cee7586d..ce455d9e67 100644
--- a/code/modules/antagonists/swarmer/swarmer.dm
+++ b/code/modules/antagonists/swarmer/swarmer.dm
@@ -33,7 +33,7 @@
. = ..()
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)
+ notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user)
. = ..()
diff --git a/code/modules/antagonists/traitor/IAA/internal_affairs.dm b/code/modules/antagonists/traitor/IAA/internal_affairs.dm
index b05750305a..caf2f644df 100644
--- a/code/modules/antagonists/traitor/IAA/internal_affairs.dm
+++ b/code/modules/antagonists/traitor/IAA/internal_affairs.dm
@@ -223,8 +223,6 @@
special_role = TRAITOR_AGENT_ROLE
syndicate = TRUE
forge_single_objective()
- else
- ..() // Give them standard objectives.
return
/datum/antagonist/traitor/internal_affairs/forge_traitor_objectives()
diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
index e1d607c34b..56954f8718 100644
--- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
+++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
@@ -208,7 +208,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
var/unlock_text = "Hello World!" //Text shown when an ability is unlocked
var/unlock_sound //Sound played when an ability is unlocked
-/datum/AI_Module/proc/upgrade(mob/living/silicon/AI/AI) //Apply upgrades!
+/datum/AI_Module/proc/upgrade(mob/living/silicon/ai/AI) //Apply upgrades!
return
/datum/AI_Module/large //Big, powerful stuff that can only be used once.
@@ -397,7 +397,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
unlock_text = "You establish a power diversion to your turrets, upgrading their health and damage."
unlock_sound = 'sound/items/rped.ogg'
-/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/AI/AI)
+/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/ai/AI)
for(var/obj/machinery/porta_turret/ai/turret in GLOB.machines)
turret.obj_integrity += 30
turret.lethal_projectile = /obj/item/projectile/beam/laser/heavylaser //Once you see it, you will know what it means to FEAR.
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 38aa0ad7f5..f14872a0a4 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -340,9 +340,9 @@
to_chat(victim, "You feel a dark presence from [A.name]")
/obj/item/voodoo/suicide_act(mob/living/carbon/user)
- user.visible_message("[user] links the voodoo doll to [user.p_them()]self and sits on it, infinitely crushing [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!")
- user.gib()
- return(BRUTELOSS)
+ user.visible_message("[user] links the voodoo doll to [user.p_them()]self and sits on it, infinitely crushing [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!")
+ user.gib()
+ return(BRUTELOSS)
/obj/item/voodoo/fire_act(exposed_temperature, exposed_volume)
if(target)
diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm
index bb7ffdc85d..4ebefd4dab 100644
--- a/code/modules/antagonists/wizard/equipment/spellbook.dm
+++ b/code/modules/antagonists/wizard/equipment/spellbook.dm
@@ -626,16 +626,16 @@
dat += {"
-
+ body { font-size: 80%; font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; }
+ ul#tabs { list-style-type: none; margin: 30px 0 0 0; padding: 0 0 0.3em 0; }
+ ul#tabs li { display: inline; }
+ ul#tabs li a { color: #42454a; background-color: #dedbde; border: 1px solid #c9c3ba; border-bottom: none; padding: 0.3em; text-decoration: none; }
+ ul#tabs li a:hover { background-color: #f1f0ee; }
+ ul#tabs li a.selected { color: #000; background-color: #f1f0ee; font-weight: bold; padding: 0.7em 0.3em 0.38em 0.3em; }
+ div.tabContent { border: 1px solid #c9c3ba; padding: 0.5em; background-color: #f1f0ee; }
+ div.tabContent.hide { display: none; }
+
+
"}
dat += {"[content]