diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index 721851ffaf3..3d24c1a3306 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -68,3 +68,5 @@
#define DEFAULT_GAS_ACCELERANT /decl/material/gas/hydrogen
#define DEFAULT_GAS_OXIDIZER /decl/material/gas/oxygen
+
+#define CHEM_REACTION_FLAG_OVERFLOW_CONTAINER BITFLAG(0)
diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm
index 6084471660b..707b08b14d0 100644
--- a/code/_onclick/hud/ai.dm
+++ b/code/_onclick/hud/ai.dm
@@ -15,4 +15,4 @@
ai_hud.input_args
)
if(mymob?.client)
- mymob.client.screen = list(adding)
+ mymob.client.screen += adding
diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm
index 61d8f7f626f..689c5f1bd68 100644
--- a/code/controllers/subsystems/overlays.dm
+++ b/code/controllers/subsystems/overlays.dm
@@ -179,7 +179,7 @@ SUBSYSTEM_DEF(overlays)
if(NOT_QUEUED_ALREADY)
QUEUE_FOR_COMPILE
-/atom/proc/set_overlays(list/overlays_list, priority = FALSE) // Sets overlays to a list, equivalent to cut_overlays() + add_overlays().
+/atom/proc/set_overlays(list/overlays_list, priority = FALSE) // Sets overlays to a list, equivalent to cut_overlays() + add_overlay().
if (!overlays_list)
return
diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm
index 4c6dfbb6ccd..f10c02c06cf 100644
--- a/code/controllers/subsystems/throwing.dm
+++ b/code/controllers/subsystems/throwing.dm
@@ -170,11 +170,10 @@ SUBSYSTEM_DEF(throwing)
thrownthing.throwing = null
if (!hit)
- for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on.
- var/atom/A = thing
- if (A == target)
+ for (var/atom/thing as anything in get_turf(thrownthing)) //looking for our target on the turf we land on.
+ if (thing == target)
hit = TRUE
- thrownthing.throw_impact(A, src)
+ thrownthing.throw_impact(thing, src)
break
if(QDELETED(thrownthing))
@@ -182,9 +181,10 @@ SUBSYSTEM_DEF(throwing)
if(!hit)
thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground.
- thrownthing.space_drift(init_dir)
+ if(!QDELETED(thrownthing))
+ thrownthing.space_drift(init_dir)
- if(t_target)
+ if(t_target && !QDELETED(thrownthing))
thrownthing.throw_impact(t_target, src)
if (callback)
diff --git a/code/datums/inventory_slots/slots/slot_belt.dm b/code/datums/inventory_slots/slots/slot_belt.dm
index 6eb7629e282..c5ac53c35a3 100644
--- a/code/datums/inventory_slots/slots/slot_belt.dm
+++ b/code/datums/inventory_slots/slots/slot_belt.dm
@@ -11,13 +11,16 @@
/datum/inventory_slot/belt/can_equip_to_slot(var/mob/user, var/obj/item/prop, var/disable_warning, var/ignore_equipped)
. = ..()
if(.)
- // If they have a uniform slot, they need a uniform to wear a belt.
+ // Things with this flag can be worn on the belt slot without a uniform.
+ if(prop.item_flags & ITEM_FLAG_IS_BELT)
+ return TRUE
+ // Otherwise, if they have a uniform slot, they need a uniform to wear a belt.
var/datum/inventory_slot/check_slot = user.get_inventory_slot_datum(slot_w_uniform_str)
- if(check_slot && !check_slot.get_equipped_item())
- if(!disable_warning)
- to_chat(user, SPAN_WARNING("You need to be wearing something on your body before you can wear \the [prop]."))
- return FALSE
- return (prop.item_flags & ITEM_FLAG_IS_BELT)
+ if(check_slot?.get_equipped_item())
+ return TRUE
+ if(!disable_warning)
+ to_chat(user, SPAN_WARNING("You need to be wearing something on your body before you can wear \the [prop]."))
+ return FALSE
/datum/inventory_slot/belt/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns)
if(_holding)
diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm
index 061b47ed3fc..b79198b50c3 100644
--- a/code/datums/recipe.dm
+++ b/code/datums/recipe.dm
@@ -93,9 +93,11 @@
--needed_items[itype]
if(needed_items[itype] <= 0)
needed_items -= itype
+ break
else
needed_items -= itype
- break
+ break
+ // break
if(!length(container_contents))
break
return !length(needed_items)
@@ -128,10 +130,15 @@
//Find items we need
if (LAZYLEN(items))
for (var/i in items)
- var/obj/item/I = locate(i) in container_contents
- if (I && I.reagents)
- I.reagents.trans_to_holder(buffer,I.reagents.total_volume)
- qdel(I)
+ var/cnt = 1
+ if (isnum(items[i]))
+ cnt = items[i]
+ for (cnt, cnt > 0, cnt--)
+ var/obj/item/I = locate(i) in container_contents
+ if (I && I.reagents)
+ container_contents -= I
+ I.reagents.trans_to_holder(buffer,I.reagents.total_volume)
+ qdel(I)
//Find fruits
if (LAZYLEN(fruit))
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 61b4694bf77..4e803429ba2 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -855,3 +855,9 @@
/atom/proc/on_defilement()
return
+
+/atom/proc/get_overhead_text_x_offset()
+ return 0
+
+/atom/proc/get_overhead_text_y_offset()
+ return 0
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 1c21c09ee7a..28daf9435d2 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -42,9 +42,8 @@
/obj/item/clothing/head/culthood
name = "cult hood"
desc = "A hood worn by the followers of Nar-Sie."
-
icon = 'icons/clothing/head/cult.dmi'
- flags_inv = HIDEFACE
+ flags_inv = HIDEFACE | BLOCK_HEAD_HAIR
body_parts_covered = SLOT_HEAD
armor = list(
ARMOR_MELEE = ARMOR_MELEE_RESISTANT,
diff --git a/code/game/machinery/_machines_base/stock_parts/radio/transmitter.dm b/code/game/machinery/_machines_base/stock_parts/radio/transmitter.dm
index 67d06b18aec..3ea9f96f1fa 100644
--- a/code/game/machinery/_machines_base/stock_parts/radio/transmitter.dm
+++ b/code/game/machinery/_machines_base/stock_parts/radio/transmitter.dm
@@ -4,6 +4,9 @@
icon_state = "transmitter"
var/range = 60 // Limits transmit range
var/latency = 2 // Delay between event and transmission; doesn't apply to transmit on tick
+ #ifdef UNIT_TEST
+ latency = 0 // this can slow down testing and cause random inconsistent failures
+ #endif
var/buffer
/obj/item/stock_parts/radio/transmitter/proc/queue_transmit(list/data)
@@ -11,7 +14,10 @@
return
if(!buffer)
buffer = data
- addtimer(CALLBACK(src, .proc/transmit), latency)
+ if(latency)
+ addtimer(CALLBACK(src, .proc/transmit), latency)
+ else
+ transmit()
else
buffer |= data
diff --git a/code/game/machinery/camera/_camera_device.dm b/code/game/machinery/camera/_camera_device.dm
index aba5e522a61..6fa7a539f25 100644
--- a/code/game/machinery/camera/_camera_device.dm
+++ b/code/game/machinery/camera/_camera_device.dm
@@ -12,7 +12,7 @@
var/xray_enabled = FALSE
has_commands = TRUE
-/datum/extension/network_device/camera/New(datum/holder, n_id, n_key, c_type, autojoin, list/preset_channels, camera_name, camnet_enabled = TRUE, req_connection = TRUE)
+/datum/extension/network_device/camera/New(datum/holder, n_id, n_key, r_type, autojoin, list/preset_channels, camera_name, camnet_enabled = TRUE, req_connection = TRUE)
if(length(preset_channels))
channels = preset_channels.Copy()
. = ..()
@@ -22,6 +22,7 @@
display_name = camera_name
/datum/extension/network_device/camera/post_construction()
+ . = ..()
if(cameranet_enabled)
cameranet.add_source(holder)
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 973d1caf10b..2560d9550ec 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -86,13 +86,12 @@
if(!c_tag)
var/area/A = get_area(src)
if(isturf(loc) && A)
- for(var/obj/machinery/camera/C in A)
- if(C == src) continue
- if(C.number)
- number = max(number, C.number+1)
- c_tag = "[A.proper_name][number == 1 ? "" : " #[number]"]"
- if(!c_tag) // Add a default c_tag in case the camera has been placed in an invalid location or inside another object.
- c_tag = "Security Camera - [random_id(/obj/machinery/camera, 100,999)]"
+ var/suffix = uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, "c_tag [A.proper_name]", 1) // unlike sequential_id, starts at 1 instead of 100
+ if(suffix == 1)
+ suffix = null
+ c_tag = "[A.proper_name][suffix ? " [suffix]" : null]"
+ // Add a default c_tag in case the camera has been placed in an invalid location or inside another object.
+ c_tag ||= "Security Camera - [random_id(/obj/machinery/camera, 100,999)]"
invalidateCameraCache()
set_extension(src, /datum/extension/network_device/camera, null, null, null, TRUE, preset_channels, c_tag, cameranet_enabled, requires_connection)
@@ -192,7 +191,7 @@
if (istype(AM, /obj))
var/obj/O = AM
if (O.throwforce >= src.toughness)
- visible_message("[src] was hit by [O].")
+ visible_message(SPAN_WARNING("[src] was hit by [O]!"))
take_damage(O.throwforce)
/obj/machinery/camera/physical_attack_hand(mob/living/carbon/human/user)
@@ -200,7 +199,7 @@
return
if(user.species.can_shred(user))
user.do_attack_animation(src)
- visible_message("\The [user] slashes at [src]!")
+ visible_message(SPAN_WARNING("\The [user] slashes at [src]!"))
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
add_hiddenprint(user)
take_damage(25)
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index 62bf538ecfe..30ee583beec 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -1,32 +1,31 @@
/obj/machinery/camera/network/engineering
preset_channels = list(CAMERA_CAMERA_CHANNEL_ENGINEERING)
- initial_access = list(access_engine)
+ req_access = list(access_engine)
/obj/machinery/camera/network/ert
preset_channels = list(CAMERA_CHANNEL_ERT)
cameranet_enabled = FALSE
- initial_access = list(access_engine)
+ req_access = list(access_engine)
/obj/machinery/camera/network/medbay
preset_channels = list(CAMERA_CHANNEL_MEDICAL)
- initial_access = list(access_medical)
-
+ req_access = list(access_medical)
/obj/machinery/camera/network/mercenary
preset_channels = list(CAMERA_CHANNEL_MERCENARY)
cameranet_enabled = FALSE
- initial_access = list(access_mercenary)
+ req_access = list(access_mercenary)
/obj/machinery/camera/network/mining
preset_channels = list(CAMERA_CHANNEL_MINE)
- initial_access = list(access_mining)
+ req_access = list(access_mining)
/obj/machinery/camera/network/research
preset_channels = list(CAMERA_CHANNEL_RESEARCH)
- initial_access = list(access_research)
+ req_access = list(access_research)
/obj/machinery/camera/network/security
preset_channels = list(CAMERA_CHANNEL_SECURITY)
- initial_access = list(access_security)
+ req_access = list(access_security)
/obj/machinery/camera/network/television
preset_channels = list(CAMERA_CHANNEL_TELEVISION)
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 4745a0ca0cb..5a6e4780c71 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -4,7 +4,6 @@
name = "computer frame"
icon = 'icons/obj/items/stock_parts/stock_parts.dmi'
icon_state = "unwired"
- obj_flags = OBJ_FLAG_ROTATABLE
expected_machine_type = "computer"
/obj/machinery/constructable_frame/computerframe/on_update_icon()
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index 0ab6191ec8c..e58b243c5dc 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -1,8 +1,6 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
//Circuit boards are in /code/game/objects/items/weapons/circuitboards/machinery/
-
-/obj/machinery/constructable_frame //Made into a seperate type to make future revisions easier.
+///Made into a seperate type to make future revisions easier.
+/obj/machinery/constructable_frame
name = "machine frame"
icon = 'icons/obj/items/stock_parts/stock_parts.dmi'
icon_state = "box_0"
@@ -11,9 +9,10 @@
use_power = POWER_USE_OFF
uncreated_component_parts = null
construct_state = /decl/machine_construction/frame/unwrenched
+ obj_flags = OBJ_FLAG_ROTATABLE
+ atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE
var/obj/item/stock_parts/circuitboard/circuit = null
var/expected_machine_type
- atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE
/obj/machinery/constructable_frame/state_transition(decl/machine_construction/new_state)
. = ..()
diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm
index 7bd64338600..1e4d602a2b8 100644
--- a/code/game/objects/effects/chem/chemsmoke.dm
+++ b/code/game/objects/effects/chem/chemsmoke.dm
@@ -138,7 +138,7 @@
var/whereLink = "[where]"
if(show_log)
- var/atom/location = carry?.get_reaction_loc()
+ var/atom/location = carry?.get_reaction_loc(CHEM_REACTION_FLAG_OVERFLOW_CONTAINER)
if(location?.fingerprintslast)
var/mob/M = get_mob_by_key(location.fingerprintslast)
var/more = ""
diff --git a/code/game/objects/effects/decals/posters/_poster.dm b/code/game/objects/effects/decals/posters/_poster.dm
index 84912068382..073afe6baa4 100644
--- a/code/game/objects/effects/decals/posters/_poster.dm
+++ b/code/game/objects/effects/decals/posters/_poster.dm
@@ -36,7 +36,7 @@
/obj/structure/sign/poster/Initialize(var/ml, var/_mat, var/_reinf_mat, var/placement_dir = null, var/given_poster_type = null)
. = ..(ml, _mat, _reinf_mat)
set_design(given_poster_type || poster_design || pick(decls_repository.get_decl_paths_of_subtype(/decl/poster_design)))
- set_dir (placement_dir || dir)
+ set_dir(placement_dir || dir)
/obj/structure/sign/poster/physically_destroyed(skip_qdel)
playsound(src, sound_destroyed, 80, TRUE)
diff --git a/code/game/objects/item_materials.dm b/code/game/objects/item_materials.dm
index 60af82df511..59def6f2a16 100644
--- a/code/game/objects/item_materials.dm
+++ b/code/game/objects/item_materials.dm
@@ -8,7 +8,7 @@
if(blood_overlay)
add_overlay(blood_overlay)
if(global.contamination_overlay && contaminated)
- overlays += global.contamination_overlay
+ add_overlay(global.contamination_overlay)
/obj/item/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
. = ..()
diff --git a/code/game/objects/items/weapons/autopsy.dm b/code/game/objects/items/weapons/autopsy.dm
index 2d6b5e790f2..9d9f4061d46 100644
--- a/code/game/objects/items/weapons/autopsy.dm
+++ b/code/game/objects/items/weapons/autopsy.dm
@@ -48,17 +48,17 @@
playsound(src, 'sound/effects/fastbeep.ogg', 10)
/obj/item/scanner/autopsy/proc/add_data(var/obj/item/organ/external/O)
- if(!O.autopsy_data.len) return
+ if(!length(O.autopsy_data))
+ return
for(var/V in O.autopsy_data)
var/datum/autopsy_data/W = O.autopsy_data[V]
- if(!weapon_data[V])
- weapon_data[V] = list("data" = W.copy(), "organs" = list(O.name))
- else
+ if(weapon_data[V])
var/datum/autopsy_data/data = weapon_data[V]["data"]
data.merge_with(W)
- var/list/organs = weapon_data[V]["organs"]
- organs |= O.name
+ weapon_data[V]["organs"] |= O.name
+ else
+ weapon_data[V] = list("data" = W.copy(), "organs" = list(O.name))
/obj/item/scanner/autopsy/proc/get_formatted_data()
var/list/scan_data = list("Subject: [target_name]")
diff --git a/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm b/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm
index c0713c1e57c..c6a553dfe5c 100644
--- a/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm
+++ b/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm
@@ -7,6 +7,9 @@
var/list/supported_programs
var/list/restricted_programs
+/obj/item/stock_parts/circuitboard/holodeckcontrol/get_buildable_types()
+ return typesof(/obj/machinery/computer/HolodeckControl)
+
/obj/item/stock_parts/circuitboard/holodeckcontrol/construct(var/obj/machinery/computer/HolodeckControl/HC)
if (..(HC))
HC.supported_programs = supported_programs.Copy()
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 a2c234cb532..39f01e28bbc 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm
@@ -47,7 +47,7 @@
var/created_size = 0
for(var/i = 1 to 200) //sanity loop limit
var/obj/item/cash_type = pick(3; /obj/item/cash/c1000, 4; /obj/item/cash/c500, 5; /obj/item/cash/c200)
- var/bundle_size = initial(cash_type.w_class) / 2
+ var/bundle_size = initial(cash_type.w_class)
if(created_size + bundle_size <= storage_capacity)
created_size += bundle_size
. += cash_type
diff --git a/code/game/objects/structures/tables.dm b/code/game/objects/structures/tables.dm
index ef9eb7989d8..499ed965bcc 100644
--- a/code/game/objects/structures/tables.dm
+++ b/code/game/objects/structures/tables.dm
@@ -674,23 +674,23 @@
/obj/structure/table/holotable
icon_state = "holo_preview"
+ holographic = TRUE
color = COLOR_OFF_WHITE
material = /decl/material/solid/metal/aluminium/holographic
reinf_material = /decl/material/solid/metal/aluminium/holographic
/obj/structure/table/holo_plastictable
icon_state = "holo_preview"
+ holographic = TRUE
color = COLOR_OFF_WHITE
material = /decl/material/solid/plastic/holographic
reinf_material = /decl/material/solid/plastic/holographic
/obj/structure/table/holo_woodentable
+ holographic = TRUE
icon_state = "holo_preview"
-
-/obj/structure/table/holo_woodentable/Initialize()
material = /decl/material/solid/wood/holographic
reinf_material = /decl/material/solid/wood/holographic
- . = ..()
//wood wood wood
/obj/structure/table/woodentable
diff --git a/code/game/sound.dm b/code/game/sound.dm
index b72d517281a..d4eb620d38f 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -55,8 +55,8 @@ var/global/const/FALLOFF_SOUNDS = 0.5
volume *= pressure_factor
- if(!turf_source.blocks_air && (T.zone || turf_source.zone) && T.zone != turf_source.zone)
- volume -= 30
+ if(!turf_source.blocks_air && T.zone != turf_source.zone)
+ volume = round(volume * 0.7) // quick and dirty volume reduction from ZAS flood fill
return volume
/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, extrarange, override_env, envdry, envwet)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 90a68a31d11..04d4e6c4beb 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -330,7 +330,7 @@
// Called when turf is hit by a thrown object
/turf/hitby(atom/movable/AM, var/datum/thrownthing/TT)
- ..()
+ SHOULD_CALL_PARENT(FALSE) // /atom/hitby() applies damage to AM if it's a living mob.
if(density)
if(isliving(AM))
var/mob/living/M = AM
diff --git a/code/modules/atmospherics/he_pipes.dm b/code/modules/atmospherics/he_pipes.dm
index e9411c81190..8df55801602 100644
--- a/code/modules/atmospherics/he_pipes.dm
+++ b/code/modules/atmospherics/he_pipes.dm
@@ -28,8 +28,8 @@
add_filter("glow",1, list(type="drop_shadow", x = 0, y = 0, offset = 0, size = 4))
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/set_dir(new_dir)
- ..()
- initialize_directions_he = initialize_directions // all directions are HE
+ . = ..()
+ initialize_directions_he = get_initialize_directions() // all directions are HE
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/atmos_init()
atmos_initalized = TRUE
diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm
index 180079d1971..ae2af786fe2 100644
--- a/code/modules/clothing/head/_head.dm
+++ b/code/modules/clothing/head/_head.dm
@@ -4,7 +4,6 @@
icon = 'icons/clothing/head/softcap.dmi'
blood_overlay_type = "helmetblood"
w_class = ITEM_SIZE_SMALL
- flags_inv = BLOCK_HEAD_HAIR
slot_flags = SLOT_HEAD
body_parts_covered = SLOT_HEAD
diff --git a/code/modules/economy/worth_cash.dm b/code/modules/economy/worth_cash.dm
index dd94cbbf3c8..636b1f9d3f9 100644
--- a/code/modules/economy/worth_cash.dm
+++ b/code/modules/economy/worth_cash.dm
@@ -152,6 +152,7 @@
/obj/item/cash/c200
absolute_worth = 200
+ w_class = ITEM_SIZE_SMALL // so that the money freezer doesn't overflow bc this is a pile instead of single bill
/obj/item/cash/c500
absolute_worth = 500
diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm
index e6df389246d..730215c0003 100644
--- a/code/modules/holodeck/HolodeckObjects.dm
+++ b/code/modules/holodeck/HolodeckObjects.dm
@@ -206,9 +206,15 @@
visible_message("[src] fades away as it shatters!")
qdel(src)
-/obj/structure/bed/chair/holochair/attackby(obj/item/W, mob/user)
- if(IS_WRENCH(W))
- to_chat(user, ("It's a holochair, you can't dismantle it!"))
+/obj/structure/bed/holobed
+ tool_interaction_flags = 0
+ holographic = TRUE
+ material = /decl/material/solid/metal/aluminium/holographic
+
+/obj/structure/bed/chair/holochair
+ tool_interaction_flags = 0
+ holographic = TRUE
+ material = /decl/material/solid/metal/aluminium/holographic
/obj/item/holo
damtype = PAIN
diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm
index 443e71bd6f8..39b93d916b6 100644
--- a/code/modules/hydroponics/trays/tray.dm
+++ b/code/modules/hydroponics/trays/tray.dm
@@ -466,11 +466,12 @@
if(weedlevel > 0)
user.visible_message("[user] starts uprooting the weeds.", "You remove the weeds from the [src].")
weedlevel = 0
+ update_icon()
if(seed)
var/needed_skill = seed.mysterious ? SKILL_ADEPT : SKILL_BASIC
if(!user.skill_check(SKILL_BOTANY, needed_skill))
plant_health -= rand(40,60)
- check_plant_health(1)
+ check_plant_health()
else
to_chat(user, "This plot is completely devoid of weeds. It doesn't need uprooting.")
@@ -489,6 +490,7 @@
toxins += spray.toxicity
pestlevel -= spray.pest_kill_str
weedlevel -= spray.weed_kill_str
+ update_icon()
to_chat(user, "You spray [src] with [O].")
playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6)
qdel(O)
diff --git a/code/modules/hydroponics/trays/tray_process.dm b/code/modules/hydroponics/trays/tray_process.dm
index 5d23c92560f..b308e466061 100644
--- a/code/modules/hydroponics/trays/tray_process.dm
+++ b/code/modules/hydroponics/trays/tray_process.dm
@@ -119,7 +119,7 @@
// Handle life and death.
// When the plant dies, weeds thrive and pests die off.
- check_plant_health(0)
+ check_plant_health(FALSE)
// If enough time (in cycles, not ticks) has passed since the plant was harvested, we're ready to harvest again.
if((age > seed.get_trait(TRAIT_MATURATION)) && \
diff --git a/code/modules/materials/definitions/solids/materials_solid_ice.dm b/code/modules/materials/definitions/solids/materials_solid_ice.dm
index 6e02c04bf18..7dc9a2cadac 100644
--- a/code/modules/materials/definitions/solids/materials_solid_ice.dm
+++ b/code/modules/materials/definitions/solids/materials_solid_ice.dm
@@ -124,13 +124,13 @@
//Little helper macro, since hydrates are all basically the same
// DISPLAY_NAME is needed because of compounds with white spaces in their names
-#define DECLARE_HYDRATE_DNAME_PATH(PATH, NAME, DISPLAY_NAME) \
-/decl/material/solid/ice/hydrate/##NAME/uid = "solid_hydrate_##NAME"; \
-/decl/material/solid/ice/hydrate/##NAME/Initialize(){ \
- name = "[##DISPLAY_NAME] hydrate"; \
- heating_products = list(PATH = 0.2, /decl/material/liquid/water = 0.8); \
- . = ..(); \
-} \
+#define DECLARE_HYDRATE_DNAME_PATH(PATH, NAME, DISPLAY_NAME) \
+/decl/material/solid/ice/hydrate/##NAME/uid = "solid_hydrate_" + #NAME; \
+/decl/material/solid/ice/hydrate/##NAME/name = #DISPLAY_NAME + " hydrate"; \
+/decl/material/solid/ice/hydrate/##NAME/heating_products = list( \
+ PATH = 0.2, \
+ /decl/material/liquid/water = 0.8 \
+); \
/decl/material/solid/ice/hydrate/##NAME
#define DECLARE_HYDRATE_DNAME(NAME, DISPLAY_NAME) DECLARE_HYDRATE_DNAME_PATH(/decl/material/gas/##NAME, NAME, DISPLAY_NAME)
diff --git a/code/modules/mob/floating_message.dm b/code/modules/mob/floating_message.dm
index 08b66bd25c6..1a37abc46d3 100644
--- a/code/modules/mob/floating_message.dm
+++ b/code/modules/mob/floating_message.dm
@@ -64,7 +64,8 @@ var/global/list/floating_chat_colors = list()
I.maptext_width = CHAT_MESSAGE_WIDTH
I.maptext_height = CHAT_MESSAGE_HEIGHT
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA | KEEP_APART
- I.pixel_w = -round(I.maptext_width/2) + 16
+ I.pixel_w = -round(I.maptext_width/2) + 16 + holder.get_overhead_text_x_offset()
+ I.pixel_z = holder.get_overhead_text_y_offset()
style = "font-family: 'Small Fonts'; -dm-text-outline: 1px black; font-size: [size]px; line-height: 1.1; [style]"
I.maptext = "
[message]"
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b4e35098b5e..86921d9140e 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1100,10 +1100,10 @@
if(damage && P.damtype == BRUTE)
var/hit_dir = get_dir(P.starting, src)
var/obj/effect/decal/cleanable/blood/B = blood_splatter(get_step(src, hit_dir), src, 1, hit_dir)
- B.icon_state = pick("dir_splatter_1","dir_splatter_2")
- var/scale = min(1, round(P.damage / 50, 0.2))
- B.set_scale(scale)
-
+ if(!QDELETED(B))
+ B.icon_state = pick("dir_splatter_1","dir_splatter_2")
+ var/scale = min(1, round(P.damage / 50, 0.2))
+ B.set_scale(scale)
new /obj/effect/temp_visual/bloodsplatter(loc, hit_dir, species.get_blood_color(src))
/mob/living/carbon/human/get_dexterity(var/silent = FALSE)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 3608af3aba9..7fd53c184a4 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1218,3 +1218,12 @@ default behaviour is:
LAZYADD(overlays_to_add, image(icon = surgery_icon, icon_state = overlay_state, layer = -HO_SURGERY_LAYER))
total.overlays |= overlays_to_add
set_current_mob_overlay(HO_SURGERY_LAYER, total, update_icons)
+
+/mob/living/get_overhead_text_x_offset()
+ var/decl/bodytype/bodytype = get_bodytype()
+ return ..() + bodytype?.antaghud_offset_x
+
+/mob/living/get_overhead_text_y_offset()
+ var/decl/bodytype/bodytype = get_bodytype()
+ return ..() + bodytype?.antaghud_offset_y
+
diff --git a/code/modules/mob/living/simple_animal/hostile/pike.dm b/code/modules/mob/living/simple_animal/hostile/pike.dm
index 75e70b201da..33494af88e4 100644
--- a/code/modules/mob/living/simple_animal/hostile/pike.dm
+++ b/code/modules/mob/living/simple_animal/hostile/pike.dm
@@ -8,6 +8,7 @@
speed = 1
mob_size = MOB_SIZE_LARGE
+ offset_overhead_text_x = 16
pixel_x = -16
health = 150
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index ee414277997..a3749c8b268 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -544,11 +544,12 @@ var/global/list/simplemob_icon_bitflag_cache = list()
if(P.damtype == BRUTE)
var/hit_dir = get_dir(P.starting, src)
var/obj/effect/decal/cleanable/blood/B = blood_splatter(get_step(src, hit_dir), src, 1, hit_dir)
- B.icon_state = pick("dir_splatter_1","dir_splatter_2")
- B.basecolor = bleed_colour
- var/scale = min(1, round(mob_size / MOB_SIZE_MEDIUM, 0.1))
- B.set_scale(scale)
- B.update_icon()
+ if(!QDELETED(B))
+ B.icon_state = pick("dir_splatter_1","dir_splatter_2")
+ B.basecolor = bleed_colour
+ var/scale = min(1, round(mob_size / MOB_SIZE_MEDIUM, 0.1))
+ B.set_scale(scale)
+ B.update_icon()
/mob/living/simple_animal/handle_fire()
return
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 658c0ff7a5d..2f1ed4415b0 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1360,3 +1360,10 @@
// Gets the ID card of a mob, but will not check types in the exceptions list
/mob/GetIdCard(exceptions = null)
return LAZYACCESS(GetIdCards(exceptions), 1)
+
+/mob/get_overhead_text_x_offset()
+ return offset_overhead_text_x
+
+/mob/get_overhead_text_y_offset()
+ return offset_overhead_text_y
+
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 2a4d148347d..54a76e69cb8 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -175,3 +175,7 @@
/// Used for darksight, required on all mobs to ensure lighting renders properly.
var/obj/screen/lighting_plane_master/lighting_master
+
+ // Offset the overhead text if necessary.
+ var/offset_overhead_text_x = 0
+ var/offset_overhead_text_y = 0
\ No newline at end of file
diff --git a/code/modules/mob/mob_layering.dm b/code/modules/mob/mob_layering.dm
index 33f8325c27a..e3143c6d1dc 100644
--- a/code/modules/mob/mob_layering.dm
+++ b/code/modules/mob/mob_layering.dm
@@ -90,7 +90,13 @@
if(istext(pixel_shift))
pixel_shift = cached_json_decode(pixel_shift)
if(islist(pixel_shift))
- var/list/directional_offset = LAZYACCESS(pixel_shift, "[dir]")
+ var/list/directional_offset = LAZYACCESS(pixel_shift, num2text(dir))
+ // Unset diagonals should be substituted with the appropriate NSEW value.
+ if(!directional_offset)
+ if(dir & EAST)
+ directional_offset = LAZYACCESS(pixel_shift, num2text(EAST))
+ else if(dir & WEST)
+ directional_offset = LAZYACCESS(pixel_shift, num2text(WEST))
if(islist(directional_offset))
pixel_shift = directional_offset
new_pixel_x += pixel_shift["x"] || 0
diff --git a/code/modules/modular_computers/file_system/directory.dm b/code/modules/modular_computers/file_system/directory.dm
index efafd3b0365..af81828a81c 100644
--- a/code/modules/modular_computers/file_system/directory.dm
+++ b/code/modules/modular_computers/file_system/directory.dm
@@ -58,6 +58,7 @@
var/datum/computer_file/held_file = file_ref.resolve()
if(!held_file)
held_files -= file_ref
+ continue
if(istype(held_file, /datum/computer_file/directory))
var/datum/computer_file/directory/dir = held_file
diff --git a/code/modules/multiz/turf_mimic_edge.dm b/code/modules/multiz/turf_mimic_edge.dm
index f0f14810968..4f7aead21aa 100644
--- a/code/modules/multiz/turf_mimic_edge.dm
+++ b/code/modules/multiz/turf_mimic_edge.dm
@@ -69,7 +69,7 @@
return
/turf/simulated/mimic_edge/get_vis_contents_to_add()
- . = shared_mimic_edge_get_add_vis_contents(src, get_mimic_turf(), ..())
+ . = shared_mimic_edge_get_add_vis_contents(src, get_mimic_turf(), list())
/turf/simulated/mimic_edge/proc/get_mimic_turf()
return mimic_x && mimic_y && mimic_z && locate(mimic_x, mimic_y, mimic_z)
@@ -135,7 +135,7 @@
return
/turf/unsimulated/mimic_edge/get_vis_contents_to_add()
- . = shared_mimic_edge_get_add_vis_contents(src, get_mimic_turf(), ..())
+ . = shared_mimic_edge_get_add_vis_contents(src, get_mimic_turf(), list())
/turf/unsimulated/mimic_edge/proc/get_mimic_turf()
return mimic_x && mimic_y && mimic_z && locate(mimic_x, mimic_y, mimic_z)
@@ -201,7 +201,7 @@
return
/turf/exterior/mimic_edge/get_vis_contents_to_add()
- . = shared_mimic_edge_get_add_vis_contents(src, get_mimic_turf(), ..())
+ . = shared_mimic_edge_get_add_vis_contents(src, get_mimic_turf(), list())
/turf/exterior/mimic_edge/proc/get_mimic_turf()
return mimic_x && mimic_y && mimic_z && locate(mimic_x, mimic_y, mimic_z)
diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm
index c566744aa62..5844573df7d 100644
--- a/code/modules/paperwork/paper_bundle.dm
+++ b/code/modules/paperwork/paper_bundle.dm
@@ -24,16 +24,6 @@
var/tmp/cur_page = 1 // current page
var/tmp/max_pages = 100 //Maximum number of papers that can be in the bundle
var/list/pages // Ordered list of pages as they are to be displayed. Can be different order than src.contents.
- var/static/list/cached_overlays //Cached images used by all paper bundles for generating the overlays and underlays
-
-/**Creates frequently used images globally, so we can re-use them. */
-/obj/item/paper_bundle/proc/cache_overlays()
- if(LAZYLEN(cached_overlays))
- return
- LAZYSET(cached_overlays, "clip", image('icons/obj/bureaucracy.dmi', "clip"))
- LAZYSET(cached_overlays, "paper", image('icons/obj/bureaucracy.dmi', "paper"))
- LAZYSET(cached_overlays, "photo", image('icons/obj/bureaucracy.dmi', "photo"))
- LAZYSET(cached_overlays, "refill", image('icons/obj/bureaucracy.dmi', "paper_refill_label"))
/obj/item/paper_bundle/Destroy()
LAZYCLEARLIST(pages) //Get rid of refs
@@ -306,22 +296,21 @@
/obj/item/paper_bundle/on_update_icon()
. = ..()
- if(!LAZYLEN(cached_overlays))
- cache_overlays()
- underlays.Cut()
+ underlays.Cut()
var/obj/item/paper/P = pages[1]
icon = P.icon
icon_state = P.icon_state
copy_overlays(P.overlays)
+
var/paper_count = 0
var/photo_count = 0
for(var/obj/O in pages)
if(istype(O, /obj/item/paper) && (paper_count < MAX_PAPER_UNDERLAYS))
//We can't even see them, so don't bother create appearences form each paper's icon, and use a generic one
- var/mutable_appearance/img = new(cached_overlays["paper"])
+ var/mutable_appearance/img = mutable_appearance('icons/obj/bureaucracy.dmi', "paper")
img.color = O.color
img.pixel_x -= min(paper_count, 2)
img.pixel_y -= min(paper_count, 2)
@@ -336,7 +325,7 @@
if(photo_count < 1)
add_overlay(Ph.tiny)
else
- add_overlay(cached_overlays["photo"]) //We can't even see them, so don't bother create new unique appearences
+ add_overlay("photo") //We can't even see them, so don't bother create new unique appearences
photo_count++
//Break if we have nothing else to do
@@ -353,7 +342,7 @@
else if(photo_count > 0)
desc += "\nThere is a photo attached to it."
- add_overlay(cached_overlays["clip"])
+ add_overlay("clip")
/**
* Merge another bundle or paper into us.
@@ -518,7 +507,7 @@
/obj/item/paper_bundle/refill/on_update_icon()
. = ..()
- add_overlay(cached_overlays["refill"])
+ add_overlay("refill")
///////////////////////////////////////////////////////////////////////////
// Interaction Rename
diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm
index b81a7ddc576..4429de2ad36 100644
--- a/code/modules/reagents/Chemistry-Holder.dm
+++ b/code/modules/reagents/Chemistry-Holder.dm
@@ -39,7 +39,9 @@ var/global/obj/temp_reagents_holder = new
clone.cached_color = cached_color
return clone
-/datum/reagents/proc/get_reaction_loc()
+/datum/reagents/proc/get_reaction_loc(chemical_reaction_flags)
+ if((chemical_reaction_flags & CHEM_REACTION_FLAG_OVERFLOW_CONTAINER) && ATOM_IS_OPEN_CONTAINER(my_atom))
+ return get_turf(my_atom)
return my_atom
/datum/reagents/proc/get_primary_reagent_name(var/codex = FALSE) // Returns the name of the reagent with the biggest volume.
diff --git a/code/modules/reagents/chems/chems_blood.dm b/code/modules/reagents/chems/chems_blood.dm
index d3a7228bd38..c56c0a0dc81 100644
--- a/code/modules/reagents/chems/chems_blood.dm
+++ b/code/modules/reagents/chems/chems_blood.dm
@@ -59,7 +59,7 @@
blood_splatter(T, src, 1)
else if(isalien(W))
var/obj/effect/decal/cleanable/blood/B = blood_splatter(T, holder.my_atom, 1)
- if(B)
+ if(!QDELETED(B))
B.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*"
/decl/material/liquid/blood/affect_ingest(var/mob/living/M, var/removed, var/datum/reagents/holder)
diff --git a/code/modules/reagents/reactions/_reaction.dm b/code/modules/reagents/reactions/_reaction.dm
index 16756785735..caed59766bf 100644
--- a/code/modules/reagents/reactions/_reaction.dm
+++ b/code/modules/reagents/reactions/_reaction.dm
@@ -15,6 +15,8 @@
var/log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file.
var/lore_text
var/mechanics_text
+ /// Flags used when reaction processing.
+ var/chemical_reaction_flags = 0
/decl/chemical_reaction/proc/can_happen(var/datum/reagents/holder)
//check that all the required reagents are present
@@ -29,7 +31,7 @@
if(holder.has_any_reagent(inhibitors))
return 0
- var/atom/location = holder.get_reaction_loc()
+ var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
var/temperature = location?.temperature || T20C
if(temperature < minimum_temperature || temperature > maximum_temperature)
return 0
@@ -37,7 +39,7 @@
return 1
/decl/chemical_reaction/proc/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
- var/atom/location = holder.get_reaction_loc()
+ var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(thermal_product && location && ATOM_SHOULD_TEMPERATURE_ENQUEUE(location))
ADJUST_ATOM_TEMPERATURE(location, thermal_product)
@@ -47,7 +49,7 @@
for(var/reagent in required_reagents)
. += reagent
-/decl/chemical_reaction/proc/get_reaction_flags(var/datum/reagents/holder)
+/decl/chemical_reaction/proc/get_alternate_reaction_indicator(var/datum/reagents/holder)
return 0
/decl/chemical_reaction/proc/process(var/datum/reagents/holder, var/limit)
@@ -59,7 +61,7 @@
if(reaction_volume > A)
reaction_volume = A
- var/reaction_flags = get_reaction_flags(holder)
+ var/alt_reaction_indicator = get_alternate_reaction_indicator(holder)
for(var/reactant in required_reagents)
holder.remove_reagent(reactant, reaction_volume * required_reagents[reactant], safety = 1)
@@ -69,11 +71,11 @@
if(result)
holder.add_reagent(result, amt_produced, data, safety = 1)
- on_reaction(holder, amt_produced, reaction_flags)
+ on_reaction(holder, amt_produced, alt_reaction_indicator)
//called after processing reactions, if they occurred
/decl/chemical_reaction/proc/post_reaction(var/datum/reagents/holder)
- var/atom/container = holder.get_reaction_loc()
+ var/atom/container = holder.get_reaction_loc(chemical_reaction_flags)
if(mix_message && container && !ismob(container))
var/turf/T = get_turf(container)
if(istype(T))
diff --git a/code/modules/reagents/reactions/reaction_grenade_reaction.dm b/code/modules/reagents/reactions/reaction_grenade_reaction.dm
index 1bc2f9aa9ec..f32859c611c 100644
--- a/code/modules/reagents/reactions/reaction_grenade_reaction.dm
+++ b/code/modules/reagents/reactions/reaction_grenade_reaction.dm
@@ -2,6 +2,7 @@
result = null
abstract_type = /decl/chemical_reaction/grenade_reaction
result_amount = 1
+ chemical_reaction_flags = CHEM_REACTION_FLAG_OVERFLOW_CONTAINER
/decl/chemical_reaction/grenade_reaction/explosion_potassium
name = "Explosion"
@@ -11,10 +12,10 @@
/decl/chemical_reaction/grenade_reaction/explosion_potassium/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/atom/location = holder.get_reaction_loc()
+ var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
var/datum/effect/effect/system/reagents_explosion/e = new()
- e.set_up(round (created_volume/10, 1), location, 0, 0)
+ e.set_up(round(created_volume/3, 1), location, 0, 0)
if(isliving(location))
e.amount *= 0.5
var/mob/living/L = location
@@ -32,7 +33,7 @@
/decl/chemical_reaction/grenade_reaction/flash_powder/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/turf/location = get_turf(holder.get_reaction_loc())
+ var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
spark_at(location, amount=2, cardinal_only = TRUE)
for(var/mob/living/carbon/M in viewers(world.view, location))
@@ -58,7 +59,7 @@
/decl/chemical_reaction/grenade_reaction/emp_pulse/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/turf/location = holder.get_reaction_loc()
+ var/turf/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
// 100 created volume = 4 heavy range & 7 light range. A few tiles smaller than traitor EMP grandes.
// 200 created volume = 8 heavy range & 14 light range. 4 tiles larger than traitor EMP grenades.
@@ -79,7 +80,7 @@
/decl/chemical_reaction/grenade_reaction/flash_fire/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/turf/location = get_turf(holder.get_reaction_loc())
+ var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(istype(location))
location.assume_gas(/decl/material/gas/hydrogen, created_volume, FLAMMABLE_GAS_FLASHPOINT + 10)
spark_at(location, amount=1, cardinal_only = TRUE)
@@ -93,7 +94,7 @@
/decl/chemical_reaction/grenade_reaction/chemsmoke/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/location = get_turf(holder.get_reaction_loc())
+ var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
var/datum/effect/effect/system/smoke_spread/chem/S = new /datum/effect/effect/system/smoke_spread/chem
S.attach(location)
@@ -112,7 +113,7 @@
/decl/chemical_reaction/grenade_reaction/foam/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/turf/location = get_turf(holder.get_reaction_loc())
+ var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
location.visible_message(SPAN_WARNING("The solution spews out foam!"), range = 5)
var/datum/effect/effect/system/foam_spread/s = new()
@@ -129,7 +130,7 @@
/decl/chemical_reaction/grenade_reaction/metalfoam/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/atom/location = holder.get_reaction_loc()
+ var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
if(istype(location, /obj/item/sealant_tank))
var/obj/item/sealant_tank/foam = location
@@ -151,7 +152,7 @@
/decl/chemical_reaction/grenade_reaction/ironfoam/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/turf/location = get_turf(holder.get_reaction_loc())
+ var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
location.visible_message(SPAN_WARNING("The solution spews out a metallic foam!"), range = 5)
var/datum/effect/effect/system/foam_spread/s = new()
diff --git a/code/modules/reagents/reactions/reaction_other.dm b/code/modules/reagents/reactions/reaction_other.dm
index 680e3564aa1..6088fb606f1 100644
--- a/code/modules/reagents/reactions/reaction_other.dm
+++ b/code/modules/reagents/reactions/reaction_other.dm
@@ -6,12 +6,12 @@
var/strength = 3
/decl/chemical_reaction/soap_key/can_happen(var/datum/reagents/holder)
- if(istype(holder.get_reaction_loc(), /obj/item/soap))
+ if(istype(holder.get_reaction_loc(chemical_reaction_flags), /obj/item/soap))
return ..()
return 0
/decl/chemical_reaction/soap_key/on_reaction(var/datum/reagents/holder)
- var/obj/item/soap/S = holder.get_reaction_loc()
+ var/obj/item/soap/S = holder.get_reaction_loc(chemical_reaction_flags)
if(istype(S) && S.key_data)
var/obj/item/key/soap/key = new(get_turf(S), S.key_data)
key.uses = strength
diff --git a/code/modules/reagents/reactions/reaction_recipe_food.dm b/code/modules/reagents/reactions/reaction_recipe_food.dm
index 7bc273ca6a5..6a63aa7f0c5 100644
--- a/code/modules/reagents/reactions/reaction_recipe_food.dm
+++ b/code/modules/reagents/reactions/reaction_recipe_food.dm
@@ -6,7 +6,7 @@
/decl/chemical_reaction/recipe/food/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/location = get_turf(holder.get_reaction_loc())
+ var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(obj_result && isturf(location))
for(var/i = 1, i <= created_volume, i++)
new obj_result(location)
diff --git a/code/modules/reagents/reactions/reaction_synthesis.dm b/code/modules/reagents/reactions/reaction_synthesis.dm
index 511219aa387..f541c2f5072 100644
--- a/code/modules/reagents/reactions/reaction_synthesis.dm
+++ b/code/modules/reagents/reactions/reaction_synthesis.dm
@@ -20,7 +20,7 @@
/decl/chemical_reaction/synthesis/fiberglass/on_reaction(datum/reagents/holder, created_volume, reaction_flags)
..()
- var/location = get_turf(holder.get_reaction_loc())
+ var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
created_volume = CEILING(created_volume)
if(created_volume > 0)
@@ -47,7 +47,7 @@
return TRUE
/decl/chemical_reaction/synthesis/crystalization/on_reaction(datum/reagents/holder, created_volume, reaction_flags)
- var/location = get_turf(holder.get_reaction_loc())
+ var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
var/list/removing_reagents = list()
for(var/rtype in holder.reagent_volumes)
@@ -81,7 +81,7 @@
return TRUE
/decl/chemical_reaction/synthesis/aerogel/on_reaction(datum/reagents/holder, created_volume, reaction_flags)
- var/location = get_turf(holder.get_reaction_loc())
+ var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
var/list/removing_reagents = list()
for(var/rtype in holder.reagent_volumes)
@@ -101,7 +101,7 @@
/decl/chemical_reaction/synthesis/plastication/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/location = get_turf(holder.get_reaction_loc())
+ var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
SSmaterials.create_object(/decl/material/solid/plastic, location, created_volume)
@@ -116,7 +116,7 @@
/decl/chemical_reaction/synthesis/resin_pack/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
..()
- var/turf/T = get_turf(holder.get_reaction_loc())
+ var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(istype(T))
var/create_stacks = FLOOR(created_volume)
if(create_stacks > 0)
diff --git a/code/modules/recycling/disposalholder.dm b/code/modules/recycling/disposalholder.dm
index c007a959ce3..d77e16a891a 100644
--- a/code/modules/recycling/disposalholder.dm
+++ b/code/modules/recycling/disposalholder.dm
@@ -9,7 +9,7 @@
var/datum/gas_mixture/gas = null // gas used to flush, will appear at exit point
var/active = 0 // true if the holder is moving, otherwise inactive
dir = 0
- var/count = 2048 //*** can travel 2048 steps before going inactive (in case of loops)
+ var/count = 4096 //*** can travel 4096 steps before going inactive (in case of loops)
var/destinationTag = "" // changes if contains a delivery container
var/tomail = 0 //changes if contains wrapped package
var/hasmob = 0 //If it contains a mob
diff --git a/code/unit_tests/equipment_tests.dm b/code/unit_tests/equipment_tests.dm
index 632ff5592df..e15fa9dbad6 100644
--- a/code/unit_tests/equipment_tests.dm
+++ b/code/unit_tests/equipment_tests.dm
@@ -116,7 +116,7 @@
"[slot_gloves_str]" = /obj/item/clothing/gloves/rainbow,
"[slot_l_ear_str]" = /obj/item/clothing/head/hairflower,
"[slot_r_ear_str]" = /obj/item/clothing/head/hairflower,
- "[slot_belt_str]" = /obj/item/storage/belt/utility,
+ "[slot_belt_str]" = /obj/item/storage/ore, // note: this should be an item without ITEM_FLAG_IS_BELT
"[slot_wear_suit_str]" = /obj/item/clothing/suit/chickensuit
)
diff --git a/code/unit_tests/map_tests.dm b/code/unit_tests/map_tests.dm
index 5d47ff00659..ed95db958b6 100644
--- a/code/unit_tests/map_tests.dm
+++ b/code/unit_tests/map_tests.dm
@@ -78,10 +78,14 @@
continue
if(!isPlayerLevel(A.z))
continue
- var/obj/machinery/alarm/alarm = locate() in A // Only test areas with functional alarms
- if(!alarm)
- continue
- if(alarm.stat & (NOPOWER | BROKEN))
+ // Only test areas with functional alarms
+ var/obj/machinery/alarm/found_alarm
+ for (var/obj/machinery/alarm/alarm in A)
+ if(alarm.inoperable()) // must have at least one functional alarm
+ continue
+ found_alarm = alarm
+
+ if(!found_alarm)
continue
//Make a list of devices that are being controlled by their air alarms
@@ -97,17 +101,37 @@
for(var/tag in vents_in_area) // The point of this test is that while the names list is registered at init, the info is transmitted by radio.
if(!A.air_vent_info[tag])
var/obj/machinery/atmospherics/unary/vent_pump/V = vents_in_area[tag]
- var/logtext = "Vent [A.air_vent_names[tag]] ([V.x], [V.y], [V.z]) with id_tag [tag] did not update the air alarm in area [A]."
- if(!V.operable())
+ var/logtext = "Vent [A.air_vent_names[tag]] ([V.x], [V.y], [V.z]) with id_tag [tag] did not update [log_info_line(found_alarm)] in area [A]."
+ if(V.inoperable())
logtext = "[logtext] The vent was not functional."
+ var/alarm_dist = get_dist(found_alarm, V)
+ if(alarm_dist > 60)
+ logtext += " The vent may be out of transmission range (max 60, was [alarm_dist])."
+ var/V_freq
+ for(var/obj/item/stock_parts/radio/radio_component in V.component_parts)
+ V_freq ||= radio_component.frequency
+ if(isnull(V_freq))
+ logtext += " The vent had no frequency set."
+ else if(V_freq != found_alarm.frequency)
+ logtext += " Frequencies did not match (alarm: [found_alarm.frequency], vent: [V_freq])."
log_bad(logtext)
failed = TRUE
for(var/tag in scrubbers_in_area)
if(!A.air_scrub_info[tag])
var/obj/machinery/atmospherics/unary/vent_scrubber/V = scrubbers_in_area[tag]
- var/logtext = "Scrubber [A.air_scrub_names[tag]] ([V.x], [V.y], [V.z]) with id_tag [tag] did not update the air alarm in area [A]."
- if(!V.operable())
+ var/logtext = "Scrubber [A.air_scrub_names[tag]] ([V.x], [V.y], [V.z]) with id_tag [tag] did not update [log_info_line(found_alarm)] in area [A]."
+ if(V.inoperable())
logtext = "[logtext] The scrubber was not functional."
+ var/alarm_dist = get_dist(found_alarm, V)
+ if(alarm_dist > 60)
+ logtext += " The scrubber may be out of transmission range (max 60, was [alarm_dist])."
+ var/V_freq
+ for(var/obj/item/stock_parts/radio/radio_component in V.component_parts)
+ V_freq ||= radio_component.frequency
+ if(isnull(V_freq))
+ logtext += " The scrubber had no frequency set."
+ else if(V_freq != found_alarm.frequency)
+ logtext += " Frequencies did not match (alarm: [found_alarm.frequency], scrubber: [V_freq])."
log_bad(logtext)
failed = TRUE
@@ -395,7 +419,7 @@
pass = FALSE
if(pass)
- pass("Have cameras have the c_tag set.")
+ pass("All cameras have the c_tag set.")
else
fail("One or more cameras do not have the c_tag set.")
@@ -688,6 +712,8 @@
continue
if(is_type_in_list(sort, exempt_junctions))
continue
+ if(sort.sort_type in global.using_map.disconnected_disposals_tags)
+ continue
var/obj/machinery/disposal/bin = get_bin_from_junction(sort)
if(!bin)
log_bad("Junction with tag [sort.sort_type] at ([sort.x], [sort.y], [sort.z]) could not find disposal.")
@@ -719,6 +745,9 @@
var/datum/unit_test/networked_disposals_shall_deliver_tagged_packages/test
speed = 100
+/obj/structure/disposalholder/unit_test/merge()
+ return FALSE
+
/obj/structure/disposalholder/unit_test/Destroy()
test.package_delivered(src)
. = ..()
diff --git a/icons/obj/items/stock_parts/stock_parts.dmi b/icons/obj/items/stock_parts/stock_parts.dmi
index c5232faf88d..24e82a36cea 100644
Binary files a/icons/obj/items/stock_parts/stock_parts.dmi and b/icons/obj/items/stock_parts/stock_parts.dmi differ
diff --git a/maps/exodus/exodus-2.dmm b/maps/exodus/exodus-2.dmm
index 3ec3c597cd4..dae06257a53 100644
--- a/maps/exodus/exodus-2.dmm
+++ b/maps/exodus/exodus-2.dmm
@@ -28776,9 +28776,6 @@
/turf/simulated/floor/tiled/steel_grid,
/area/exodus/hallway/primary/central_one)
"bjc" = (
-/obj/abstract/landmark/start{
- name = "AI"
- },
/obj/machinery/newscaster{
pixel_x = 32;
pixel_y = 32
@@ -28809,7 +28806,7 @@
/obj/item/radio/intercom{
pixel_y = 22
},
-/obj/structure/aicore/deactivated,
+/obj/abstract/landmark/start/ai,
/turf/simulated/floor/bluegrid,
/area/exodus/turret_protected/ai)
"bjd" = (
@@ -32793,10 +32790,10 @@
/obj/machinery/portable_atmospherics/powered/scrubber/huge,
/obj/effect/floor_decal/industrial/outline/yellow,
/obj/structure/window/borosilicate_reinforced{
- dir = 4;
+ dir = 4
},
/obj/structure/window/borosilicate_reinforced{
- dir = 1;
+ dir = 1
},
/turf/simulated/floor/plating,
/area/exodus/research/mixing)
@@ -33587,10 +33584,10 @@
/obj/machinery/portable_atmospherics/powered/scrubber/huge,
/obj/effect/floor_decal/industrial/outline/yellow,
/obj/structure/window/borosilicate_reinforced{
- dir = 8;
+ dir = 8
},
/obj/structure/window/borosilicate_reinforced{
- dir = 1;
+ dir = 1
},
/turf/simulated/floor/plating,
/area/exodus/research/mixing)
@@ -36718,7 +36715,7 @@
/obj/machinery/portable_atmospherics/powered/scrubber/huge,
/obj/effect/floor_decal/industrial/outline/yellow,
/obj/structure/window/borosilicate_reinforced{
- dir = 1;
+ dir = 1
},
/turf/simulated/floor/plating,
/area/exodus/research/mixing)
@@ -36946,7 +36943,7 @@
dir = 4
},
/obj/structure/window/borosilicate_reinforced{
- dir = 4;
+ dir = 4
},
/turf/simulated/floor/tiled/white,
/area/exodus/research/mixing)
@@ -36954,7 +36951,7 @@
/obj/machinery/portable_atmospherics/canister,
/obj/effect/floor_decal/corner/purple/three_quarters,
/obj/structure/window/borosilicate_reinforced{
- dir = 8;
+ dir = 8
},
/turf/simulated/floor/tiled/white,
/area/exodus/research/mixing)
@@ -63356,8 +63353,8 @@
/area/ship/exodus_pod_mining)
"doN" = (
/obj/abstract/level_data_spawner/main_level{
- name = "Exodus Operations Deck";
-},
+ name = "Exodus Operations Deck"
+ },
/turf/space,
/area/space)
"drB" = (
@@ -64950,9 +64947,6 @@
/obj/structure/table,
/turf/simulated/floor/tiled/white,
/area/exodus/research/robotics)
-"wTf" = (
-/turf/simulated/floor/airless,
-/area/exodus/turret_protected/ai)
"wTp" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 6
@@ -93985,7 +93979,7 @@ auR
avS
avU
fPF
-wTf
+eEn
beb
bgW
aoi
diff --git a/maps/exodus/exodus_cameras.dm b/maps/exodus/exodus_cameras.dm
index 8164f3995c9..1f5d4b51ee3 100644
--- a/maps/exodus/exodus_cameras.dm
+++ b/maps/exodus/exodus_cameras.dm
@@ -8,37 +8,37 @@ var/global/const/CAMERA_CHANNEL_ENGINEERING_OUTPOST = "Engineering Outpost"
// Networks
/obj/machinery/camera/network/command
preset_channels = list(CAMERA_CHANNEL_COMMAND)
- initial_access = list(access_heads)
+ req_access = list(access_heads)
/obj/machinery/camera/network/crescent
preset_channels = list(CAMERA_CHANNEL_CRESCENT)
/obj/machinery/camera/network/engine
preset_channels = list(CAMERA_CHANNEL_ENGINE)
- initial_access = list(access_engine)
+ req_access = list(access_engine)
/obj/machinery/camera/network/engineering_outpost
preset_channels = list(CAMERA_CHANNEL_ENGINEERING_OUTPOST)
- initial_access = list(access_engine)
+ req_access = list(access_engine)
// Motion
/obj/machinery/camera/motion/engineering_outpost
preset_channels = list(CAMERA_CHANNEL_ENGINEERING_OUTPOST)
- initial_access = list(access_engine)
+ req_access = list(access_engine)
// All Upgrades
/obj/machinery/camera/all/command
preset_channels = list(CAMERA_CHANNEL_COMMAND)
- initial_access = list(access_heads)
+ req_access = list(access_heads)
// Compile stubs.
/obj/machinery/camera/motion/command
preset_channels = list(CAMERA_CHANNEL_COMMAND)
- initial_access = list(access_heads)
+ req_access = list(access_heads)
/obj/machinery/camera/network/maintenance
preset_channels = list(CAMERA_CAMERA_CHANNEL_ENGINEERING)
- initial_access = list(access_engine)
+ req_access = list(access_engine)
/obj/machinery/camera/xray/security
preset_channels = list(CAMERA_CHANNEL_SECURITY)
diff --git a/maps/ministation/ministation.dmm b/maps/ministation/ministation.dmm
index fdcd879ca6a..a0822bc1e99 100644
--- a/maps/ministation/ministation.dmm
+++ b/maps/ministation/ministation.dmm
@@ -13927,9 +13927,7 @@
pixel_x = 27;
pixel_y = 5
},
-/obj/abstract/landmark/start{
- name = "AI"
- },
+/obj/abstract/landmark/start/ai,
/obj/machinery/network/requests_console{
department = "AI";
pixel_x = 32;
diff --git a/maps/tradeship/tradeship-2.dmm b/maps/tradeship/tradeship-2.dmm
index d0bb5e0062a..6f4dac1f926 100644
--- a/maps/tradeship/tradeship-2.dmm
+++ b/maps/tradeship/tradeship-2.dmm
@@ -4749,7 +4749,7 @@
dir = 1
},
/turf/space,
-/area/space)
+/area/ship/trade/shuttle/outgoing/general)
"oi" = (
/obj/machinery/vending/snack{
dir = 4
@@ -6994,7 +6994,7 @@
dir = 1
},
/turf/space,
-/area/space)
+/area/ship/trade/shuttle/outgoing/general)
"Nc" = (
/obj/structure/disposalpipe/segment{
dir = 4;
@@ -7175,16 +7175,6 @@
/obj/machinery/power/terminal,
/turf/simulated/floor/plating,
/area/ship/trade/maintenance/engine/aft)
-"OD" = (
-/obj/structure/catwalk,
-/obj/structure/railing/mapped{
- dir = 1
- },
-/obj/structure/railing/mapped{
- dir = 4
- },
-/turf/space,
-/area/space)
"OP" = (
/obj/machinery/alarm{
dir = 8;
@@ -7525,16 +7515,6 @@
},
/turf/simulated/floor/plating,
/area/ship/trade/shuttle/outgoing/general)
-"Sk" = (
-/obj/structure/catwalk,
-/obj/structure/railing/mapped{
- dir = 1
- },
-/obj/structure/railing/mapped{
- dir = 8
- },
-/turf/space,
-/area/space)
"Sr" = (
/turf/simulated/floor/plating,
/area/ship/trade/maintenance/hallway)
@@ -9834,7 +9814,7 @@ aa
aa
aa
aa
-Sk
+WM
gN
qv
Sj
@@ -10572,7 +10552,7 @@ aa
aa
aa
aa
-OD
+Bi
Tb
CV
Wb
diff --git a/maps/~mapsystem/maps_unit_testing.dm b/maps/~mapsystem/maps_unit_testing.dm
index fe0f90121e7..025460d9724 100644
--- a/maps/~mapsystem/maps_unit_testing.dm
+++ b/maps/~mapsystem/maps_unit_testing.dm
@@ -38,5 +38,9 @@
var/list/area_purity_test_exempt_areas = list()
+ /// A list of disposals tags (sort_type var) that aren't expected to have outputs.
+ var/list/disconnected_disposals_tags = list()
+
/// A list of lists, of the format ((x, y, z, dir),).
var/list/disconnected_wires_test_exempt_turfs = list()
+
diff --git a/mods/content/psionics/datum/chems.dm b/mods/content/psionics/datum/chems.dm
index 4cbc86e54ad..119cfbc1c2e 100644
--- a/mods/content/psionics/datum/chems.dm
+++ b/mods/content/psionics/datum/chems.dm
@@ -13,7 +13,7 @@
required_reagents = list(/decl/material/liquid/blood = 15, /decl/material/liquid/crystal_agent = 1)
result_amount = 1
-/decl/chemical_reaction/synthesis/nullglass/get_reaction_flags(var/datum/reagents/holder)
+/decl/chemical_reaction/synthesis/nullglass/get_alternate_reaction_indicator(var/datum/reagents/holder)
var/list/blood_data = REAGENT_DATA(holder, /decl/material/liquid/blood)
var/weakref/donor_ref = LAZYACCESS(blood_data, "donor")
var/mob/living/donor = donor_ref?.resolve()
@@ -21,7 +21,7 @@
. = (istype(donor) && (donor.psi || (donor.mind && wizards.is_antagonist(donor.mind))))
/decl/chemical_reaction/synthesis/nullglass/on_reaction(var/datum/reagents/holder, var/created_volume, var/reaction_flags)
- var/location = get_turf(holder.get_reaction_loc())
+ var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(reaction_flags)
for(var/i = 1, i <= created_volume, i++)
new /obj/item/soulstone(location)
diff --git a/mods/content/xenobiology/slime/_slime.dm b/mods/content/xenobiology/slime/_slime.dm
index a0123babb3b..5f7c26441b7 100644
--- a/mods/content/xenobiology/slime/_slime.dm
+++ b/mods/content/xenobiology/slime/_slime.dm
@@ -213,9 +213,9 @@
adjust_friendship(user, rand(2,3))
return TRUE
- if(feeding_on)
- var/prey = feeding_on
- if(feeding_on == user)
+ var/prey = feeding_on?.resolve()
+ if(prey)
+ if(prey == user)
if(prob(60))
visible_message(SPAN_DANGER("\The [user] fails to escape \the [src]!"))
else
@@ -223,12 +223,12 @@
set_feeding_on()
else
if(prob(30))
- visible_message(SPAN_DANGER("\The [user] attempts to wrestle \the [src] off \the [feeding_on]!"))
+ visible_message(SPAN_DANGER("\The [user] attempts to wrestle \the [src] off \the [prey]!"))
else
- visible_message(SPAN_DANGER("\The [user] manages to wrestle \the [src] off \the [feeding_on]!"))
+ visible_message(SPAN_DANGER("\The [user] manages to wrestle \the [src] off \the [prey]!"))
set_feeding_on()
- if(prey != feeding_on)
+ if(prey != feeding_on?.resolve())
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
SET_STATUS_MAX(src, STAT_CONFUSE, 2)
step_away(src, user)
@@ -335,6 +335,7 @@
/mob/living/slime/xenobio_scan_results()
var/decl/slime_colour/slime_data = GET_DECL(slime_type)
+ . = list()
. += "Slime scan result for \the [src]:"
. += "[slime_data.name] [is_adult ? "adult" : "baby"] slime"
. += "Nutrition:\t[nutrition]/[get_max_nutrition()]"
@@ -360,7 +361,7 @@
var/list/mutationTexts = list("[slime_data.name] ([100 - mutation_chance]%)")
for(var/i in mutationChances)
- mutationTexts += "[i] ([mutationChances[i]]%)"
+ mutationTexts += "[GET_DECL(i)] ([mutationChances[i]]%)"
. += "Possible colours on splitting:\t[english_list(mutationTexts)]"