diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6eeff93d225..dd563d348ff 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -20,7 +20,7 @@ env:
jobs:
DreamChecker:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Setup Cache
@@ -51,7 +51,7 @@ jobs:
chmod +x send.sh
./send.sh failure $WEBHOOK_URL
OpenDream:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Python setup
@@ -73,7 +73,7 @@ jobs:
- name: Run OpenDream
run: ./DMCompiler_linux-x64/DMCompiler nebula.dme --suppress-unimplemented --skip-anything-typecheck --version=${BYOND_MAJOR}.${BYOND_MINOR} | python tools/od_annotator/__main__.py "$@"
Code:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Setup Cache
@@ -99,7 +99,7 @@ jobs:
chmod +x send.sh
./send.sh failure $WEBHOOK_URL
Maps:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
strategy:
matrix:
map_path: [example, tradeship, exodus, ministation, shaded_hills, away_sites_testing, modpack_testing, planets_testing]
diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm
index 386da5ca61a..335eb97ec2a 100644
--- a/code/__defines/_planes+layers.dm
+++ b/code/__defines/_planes+layers.dm
@@ -91,31 +91,32 @@ What is the naming convention for planes or layers?
#define ABOVE_WIRE_LAYER 1.58
//TURF PLANE
//TURF_LAYER = 2
- #define TURF_DETAIL_LAYER 2.01
- #define TURF_SHADOW_LAYER 2.02
+ #define TURF_OVER_EDGE_LAYER TURF_LAYER + (FLOOR_LAYER_CONSTANT*100)
+ #define TURF_DETAIL_LAYER TURF_OVER_EDGE_LAYER + 0.01
+ #define TURF_SHADOW_LAYER TURF_OVER_EDGE_LAYER + 0.02
//ABOVE TURF
- #define DECAL_LAYER 2.03
- #define RUNE_LAYER 2.04
- #define AO_LAYER 2.045
- #define ABOVE_TILE_LAYER 2.05
- #define EXPOSED_PIPE_LAYER 2.06
- #define EXPOSED_WIRE_LAYER 2.07
- #define EXPOSED_WIRE_TERMINAL_LAYER 2.08
- #define CATWALK_LAYER 2.09
- #define BLOOD_LAYER 2.10
- #define MOUSETRAP_LAYER 2.11
- #define PLANT_LAYER 2.12
+ #define DECAL_LAYER TURF_OVER_EDGE_LAYER + 0.03
+ #define RUNE_LAYER TURF_OVER_EDGE_LAYER + 0.04
+ #define AO_LAYER TURF_OVER_EDGE_LAYER + 0.045
+ #define ABOVE_TILE_LAYER TURF_OVER_EDGE_LAYER + 0.05
+ #define EXPOSED_PIPE_LAYER TURF_OVER_EDGE_LAYER + 0.06
+ #define EXPOSED_WIRE_LAYER TURF_OVER_EDGE_LAYER + 0.07
+ #define EXPOSED_WIRE_TERMINAL_LAYER TURF_OVER_EDGE_LAYER + 0.08
+ #define CATWALK_LAYER TURF_OVER_EDGE_LAYER + 0.09
+ #define BLOOD_LAYER TURF_OVER_EDGE_LAYER + 0.10
+ #define MOUSETRAP_LAYER TURF_OVER_EDGE_LAYER + 0.11
+ #define PLANT_LAYER TURF_OVER_EDGE_LAYER + 0.12
//HIDING MOB
- #define HIDING_MOB_LAYER 2.14
- #define SHALLOW_FLUID_LAYER 2.15
- #define MOB_SHADOW_LAYER 2.16
+ #define HIDING_MOB_LAYER TURF_OVER_EDGE_LAYER + 0.14
+ #define SHALLOW_FLUID_LAYER TURF_OVER_EDGE_LAYER + 0.15
+ #define MOB_SHADOW_LAYER TURF_OVER_EDGE_LAYER + 0.16
//OBJ
- #define BELOW_DOOR_LAYER 2.17
- #define OPEN_DOOR_LAYER 2.18
- #define BELOW_TABLE_LAYER 2.19
- #define TABLE_LAYER 2.20
- #define BELOW_OBJ_LAYER 2.21
- #define STRUCTURE_LAYER 2.22
+ #define BELOW_DOOR_LAYER TURF_OVER_EDGE_LAYER + 0.17
+ #define OPEN_DOOR_LAYER TURF_OVER_EDGE_LAYER + 0.18
+ #define BELOW_TABLE_LAYER TURF_OVER_EDGE_LAYER + 0.19
+ #define TABLE_LAYER TURF_OVER_EDGE_LAYER + 0.20
+ #define BELOW_OBJ_LAYER TURF_OVER_EDGE_LAYER + 0.21
+ #define STRUCTURE_LAYER TURF_OVER_EDGE_LAYER + 0.22
// OBJ_LAYER 3
#define ABOVE_OBJ_LAYER 3.01
#define CLOSED_DOOR_LAYER 3.02
diff --git a/code/__defines/bodytype.dm b/code/__defines/bodytype.dm
index 207d9e83d8c..a44b77cc47f 100644
--- a/code/__defines/bodytype.dm
+++ b/code/__defines/bodytype.dm
@@ -1,7 +1,3 @@
-#define BODY_FLAG_EXCLUDE BITFLAG(0)
-#define BODY_FLAG_HUMANOID BITFLAG(1)
-#define BODY_FLAG_MONKEY BITFLAG(2)
-#define BODY_FLAG_QUADRUPED BITFLAG(3)
#define BODYTYPE_HUMANOID "humanoid body"
#define BODYTYPE_QUADRUPED "quadruped body"
@@ -20,9 +16,21 @@
#define HAS_A_SKIN_TONE (HAS_SKIN_TONE_NORMAL | HAS_SKIN_TONE_GRAV | HAS_SKIN_TONE_SPCR | HAS_SKIN_TONE_TRITON) // Bodytype has a numeric skintone
// Bodytype feature flags
-#define BODY_FLAG_NO_DNA BITFLAG(0) // Does not create DNA. Replaces SPECIES_FLAG_NO_SCAN.
-#define BODY_FLAG_NO_PAIN BITFLAG(1) // Cannot suffer halloss/recieves deceptive health indicator.
-#define BODY_FLAG_NO_EAT BITFLAG(2) // Cannot eat food/drink drinks even if a stomach organ is present.
-#define BODY_FLAG_CRYSTAL_REFORM BITFLAG(3) // Can regenerate missing limbs from mineral baths.
-#define BODY_FLAG_NO_STASIS BITFLAG(4) // Does not experience stasis effects (sleeper, cryo)
-#define BODY_FLAG_NO_DEFIB BITFLAG(5) // Cannot be revived with a defibrilator.
+/// Does not create DNA. Replaces SPECIES_FLAG_NO_SCAN.
+#define BODY_FLAG_NO_DNA BITFLAG(0)
+/// Cannot suffer halloss/recieves deceptive health indicator.
+#define BODY_FLAG_NO_PAIN BITFLAG(1)
+/// Cannot eat food/drink drinks even if a stomach organ is present.
+#define BODY_FLAG_NO_EAT BITFLAG(2)
+/// Can regenerate missing limbs from mineral baths.
+#define BODY_FLAG_CRYSTAL_REFORM BITFLAG(3)
+/// Does not experience stasis effects (sleeper, cryo)
+#define BODY_FLAG_NO_STASIS BITFLAG(4)
+/// Cannot be revived with a defibrilator.
+#define BODY_FLAG_NO_DEFIB BITFLAG(5)
+
+// Equipment flags for gear and accessory restrictions
+#define BODY_EQUIP_FLAG_EXCLUDE BITFLAG(0)
+#define BODY_EQUIP_FLAG_HUMANOID BITFLAG(1)
+#define BODY_EQUIP_FLAG_MONKEY BITFLAG(2)
+#define BODY_EQUIP_FLAG_QUADRUPED BITFLAG(3)
diff --git a/code/__defines/turfs.dm b/code/__defines/turfs.dm
index 4a7811130b9..ac797e16cbd 100644
--- a/code/__defines/turfs.dm
+++ b/code/__defines/turfs.dm
@@ -30,18 +30,19 @@
///Helper macro for printing to text the world's x,y,z size to a string.
#define WORLD_SIZE_TO_STRING "[world.maxx]x[world.maxy]x[world.maxz]"
-#define EXT_LAYER_CONSTANT 0.001
-#define EXT_EDGE_OCEAN (10 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_SEAFLOOR (11 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_VOLCANIC (12 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_DIRT (20 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_BARREN (21 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_CLAY (21 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_MUD (22 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_SAND (30 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_CHLORINE_SAND (31 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_WATER (40 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_GRASS (51 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_PATH (52 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_GRASS_WILD (53 * EXT_LAYER_CONSTANT)
-#define EXT_EDGE_SNOW (60 * EXT_LAYER_CONSTANT)
+#define FLOOR_EDGE_NONE -1
+#define FLOOR_LAYER_CONSTANT 0.001
+#define FLOOR_LAYER_OCEAN (10 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_SEAFLOOR (11 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_VOLCANIC (12 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_DIRT (20 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_BARREN (21 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_CLAY (21 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_MUD (22 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_SAND (30 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_CHLORINE_SAND (50 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_WATER (50 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_GRASS (55 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_PATH (60 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_GRASS_WILD (65 * FLOOR_LAYER_CONSTANT)
+#define FLOOR_EDGE_SNOW (70 * FLOOR_LAYER_CONSTANT)
diff --git a/code/_global_vars/sound.dm b/code/_global_vars/sound.dm
index 4b42260aa53..9525f1b0b2b 100644
--- a/code/_global_vars/sound.dm
+++ b/code/_global_vars/sound.dm
@@ -113,8 +113,18 @@ var/global/list/light_strike_sound = list(
'sound/effects/hit_kick.ogg',
'sound/effects/hit_punch.ogg'
)
-
+
var/global/list/tray_hit_sound = list(
'sound/items/trayhit1.ogg',
'sound/items/trayhit2.ogg'
+)
+
+var/global/list/sweeping_sound = list(
+ 'sound/foley/sweeping1.ogg',
+ 'sound/foley/sweeping2.ogg',
+ 'sound/foley/sweeping3.ogg',
+ 'sound/foley/sweeping4.ogg',
+ 'sound/foley/sweeping5.ogg',
+ 'sound/foley/sweeping6.ogg',
+ 'sound/foley/sweeping7.ogg',
)
\ No newline at end of file
diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm
index ac2ec4ff6fd..2f5d2eb8e35 100644
--- a/code/_helpers/game.dm
+++ b/code/_helpers/game.dm
@@ -172,7 +172,6 @@
return L
// Returns a list of mobs and/or objects in range of R from source. Used in radio and say code.
-
/proc/get_mobs_or_objects_in_view(var/R, var/atom/source, var/include_mobs = 1, var/include_objects = 1)
var/turf/T = get_turf(source)
@@ -195,28 +194,24 @@
hear += I
return hear
-/proc/get_mobs_and_objs_in_view_fast(var/turf/T, var/range, var/list/mobs, var/list/objs, var/check_ghosts = null)
- var/list/hear = list()
- DVIEW(hear, range, T, INVISIBILITY_MAXIMUM)
+// Alternative to get_mobs_or_objects_in_view which only considers mobs and "listening" objects.
+/proc/get_listeners_in_range(turf/center, range, list/mobs, list/objs, check_ghosts=FALSE)
var/list/hearturfs = list()
-
- for(var/atom/movable/AM in hear)
- if(ismob(AM))
- mobs += AM
- hearturfs += get_turf(AM)
- else if(isobj(AM))
- objs += AM
- hearturfs += get_turf(AM)
+ FOR_DVIEW(var/turf/T, range, center, INVISIBILITY_MAXIMUM)
+ hearturfs[T] = TRUE
+ for(var/mob/M in T)
+ mobs += M
+ END_FOR_DVIEW
for(var/mob/M in global.player_list)
if(check_ghosts && M.stat == DEAD && M.get_preference_value(check_ghosts) != PREF_NEARBY)
mobs |= M
- else if(get_turf(M) in hearturfs)
+ else if(hearturfs[get_turf(M)])
mobs |= M
for(var/obj/O in global.listening_objects)
- if(get_turf(O) in hearturfs)
- objs |= O
+ if(hearturfs[get_turf(O)])
+ objs += O
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 4f194f9aca2..38e3e0ee74e 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -95,7 +95,6 @@ avoid code duplication. This includes items that may sometimes act as a standard
devour(used_item)
return TRUE
-
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
// Click parameters is the params string from byond Click() code, see that documentation.
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm
index c48ac630255..47c1be9e245 100644
--- a/code/controllers/subsystems/garbage.dm
+++ b/code/controllers/subsystems/garbage.dm
@@ -312,6 +312,9 @@ SUBSYSTEM_DEF(garbage)
if(isnull(D))
return
+ if(D.is_processing)
+ get_stack_trace("[D] ([D.type]) was qdeleted while still processing on [D.is_processing]!")
+
switch(hint)
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
GC_CHECK_AM_NULLSPACE(D, "QDEL_HINT_QUEUE")
diff --git a/code/datums/ai/passive.dm b/code/datums/ai/passive.dm
index 73d29d470b6..ae2bc1e62e4 100644
--- a/code/datums/ai/passive.dm
+++ b/code/datums/ai/passive.dm
@@ -62,6 +62,8 @@
var/scooping_skill_req = SKILL_ADEPT
/datum/mob_controller/passive/scooped_by(mob/living/initiator)
+ if(body.stat != CONSCIOUS)
+ return TRUE
if(is_friend(initiator))
return TRUE
if(is_enemy(initiator) || (scooping_skill && initiator.skill_fail_prob(scooping_skill, 50, scooping_skill_req))) // scary, try to wriggle away
diff --git a/code/datums/extensions/demolisher/_demolisher.dm b/code/datums/extensions/demolisher/_demolisher.dm
new file mode 100644
index 00000000000..0b5f4bc8db5
--- /dev/null
+++ b/code/datums/extensions/demolisher/_demolisher.dm
@@ -0,0 +1,38 @@
+// A subtype for items that can dismantle/demolish non-reinforced non-natural walls.
+/datum/extension/demolisher
+ base_type = /datum/extension/demolisher
+ expected_type = /obj/item
+ var/demolish_delay = 6 SECONDS
+ var/demolish_verb
+ var/demolish_sound
+
+/datum/extension/demolisher/New(datum/holder, _delay, _verb, _sound)
+ . = ..()
+ if(_delay)
+ demolish_delay = _delay
+ if(_verb)
+ demolish_verb = _verb
+ if(_sound)
+ demolish_sound = _sound
+
+/datum/extension/demolisher/proc/get_demolish_delay(turf/wall/wall)
+ return demolish_delay + wall?.get_material()?.cut_delay
+
+/datum/extension/demolisher/proc/get_demolish_verb()
+ return demolish_verb
+
+/datum/extension/demolisher/proc/get_demolish_sound()
+ return demolish_sound
+
+/datum/extension/demolisher/proc/try_demolish(mob/user, turf/wall/wall)
+ var/dismantle_verb = get_demolish_verb()
+ var/dismantle_sound = get_demolish_sound()
+ to_chat(user, SPAN_NOTICE("You begin [dismantle_verb] \the [wall]."))
+ if(dismantle_sound)
+ playsound(wall, dismantle_sound, 100, 1)
+ var/cut_delay = max(0, get_demolish_delay(wall))
+ if(do_after(user, cut_delay, wall))
+ to_chat(user, SPAN_NOTICE("You finish [dismantle_verb] \the [wall]."))
+ user.visible_message(SPAN_DANGER("\The [user] finishes [dismantle_verb] \the [wall]!"))
+ wall.dismantle_turf()
+ return TRUE
diff --git a/code/datums/extensions/demolisher/delicate.dm b/code/datums/extensions/demolisher/delicate.dm
new file mode 100644
index 00000000000..a9f6dbdb543
--- /dev/null
+++ b/code/datums/extensions/demolisher/delicate.dm
@@ -0,0 +1,13 @@
+/datum/extension/demolisher/delicate
+ demolish_verb = "dismantling"
+ demolish_sound = 'sound/items/Crowbar.ogg'
+ var/alternative_tools = "a sledgehammer or welding torch" // For overriding on medieval maps.
+
+/datum/extension/demolisher/delicate/try_demolish(mob/user, turf/wall/wall)
+ if(!(wall.get_material()?.removed_by_welder))
+ return ..()
+ to_chat(user, SPAN_WARNING("\The [wall] is too robust to be dismantled with \the [holder]; try [alternative_tools]."))
+ return TRUE
+
+/datum/extension/demolisher/delicate/get_demolish_delay(turf/wall/wall)
+ return ..() * 1.2
diff --git a/code/datums/extensions/demolisher/energy.dm b/code/datums/extensions/demolisher/energy.dm
new file mode 100644
index 00000000000..ff4a7282de6
--- /dev/null
+++ b/code/datums/extensions/demolisher/energy.dm
@@ -0,0 +1,16 @@
+/datum/extension/demolisher/energy
+ demolish_sound = "sparks"
+ demolish_verb = "slicing through"
+
+/datum/extension/demolisher/energy/try_demolish(mob/user, turf/wall/wall)
+ var/obj/item/tool = holder
+ if(!tool.is_special_cutting_tool())
+ return FALSE
+ if(istype(tool, /obj/item/gun/energy/plasmacutter))
+ var/obj/item/gun/energy/plasmacutter/cutter = tool
+ if(!cutter.slice(user))
+ return TRUE
+ return ..()
+
+/datum/extension/demolisher/energy/get_demolish_delay(turf/wall/wall)
+ return ..() * 0.5
diff --git a/code/datums/extensions/demolisher/pick.dm b/code/datums/extensions/demolisher/pick.dm
new file mode 100644
index 00000000000..5b48b14b6ef
--- /dev/null
+++ b/code/datums/extensions/demolisher/pick.dm
@@ -0,0 +1,22 @@
+/datum/extension/demolisher/pick
+ demolish_verb = "dismantling"
+ demolish_sound = 'sound/items/Crowbar.ogg'
+
+/datum/extension/demolisher/pick/try_demolish(mob/user, turf/wall/wall)
+ var/obj/item/pick = holder
+ if(pick.material?.hardness < wall.get_material()?.hardness)
+ to_chat(user, SPAN_WARNING("\The [holder] is not hard enough to cut through [wall.get_material().solid_name]."))
+ return TRUE
+ return ..()
+
+/datum/extension/demolisher/pick/get_demolish_delay(turf/wall/wall)
+ var/obj/item/pick = holder
+ return pick.get_expected_tool_use_delay(TOOL_PICK, ..())
+
+/datum/extension/demolisher/pick/get_demolish_verb()
+ var/obj/item/pick = holder
+ return pick.get_tool_message(TOOL_PICK)
+
+/datum/extension/demolisher/pick/get_demolish_sound()
+ var/obj/item/pick = holder
+ return pick.get_tool_sound(TOOL_PICK)
diff --git a/code/datums/extensions/demolisher/welder.dm b/code/datums/extensions/demolisher/welder.dm
new file mode 100644
index 00000000000..b6a43fc85b0
--- /dev/null
+++ b/code/datums/extensions/demolisher/welder.dm
@@ -0,0 +1,16 @@
+/datum/extension/demolisher/welder
+ demolish_verb = "cutting through"
+ demolish_sound = 'sound/items/Welder.ogg'
+ expected_type = /obj/item/weldingtool
+
+/datum/extension/demolisher/welder/try_demolish(mob/user, turf/wall/wall)
+ if(!(wall.get_material()?.removed_by_welder))
+ to_chat(user, SPAN_WARNING("\The [wall] is too delicate to be dismantled with \the [holder]; try a hammer or crowbar."))
+ return TRUE
+ var/obj/item/weldingtool/welder = holder
+ if(welder.weld(0,user))
+ return ..()
+ return TRUE
+
+/datum/extension/demolisher/welder/get_demolish_delay(turf/wall/wall)
+ return ..() * 0.7
diff --git a/code/datums/extensions/milkable/milkable.dm b/code/datums/extensions/milkable/milkable.dm
index 5e50844e70b..5615ff1a2b5 100644
--- a/code/datums/extensions/milkable/milkable.dm
+++ b/code/datums/extensions/milkable/milkable.dm
@@ -23,6 +23,7 @@
START_PROCESSING(SSprocessing, src)
/datum/extension/milkable/Destroy()
+ STOP_PROCESSING(SSprocessing, src)
QDEL_NULL(udder)
return ..()
@@ -86,7 +87,7 @@
SPAN_NOTICE("\The [user] starts milking \the [critter] into \the [container]."),
SPAN_NOTICE("You start milking \the [critter] into \the [container].")
)
- if(!user.do_skilled(4 SECONDS, milking_skill))
+ if(!user.do_skilled(4 SECONDS, milking_skill, target = critter, check_holding = TRUE))
user.visible_message(
SPAN_NOTICE("\The [user] stops milking \the [critter]."),
SPAN_NOTICE("You stop milking \the [critter].")
diff --git a/code/datums/extensions/shearable/shearable.dm b/code/datums/extensions/shearable/shearable.dm
index 4fff54d32ef..c94d40a8669 100644
--- a/code/datums/extensions/shearable/shearable.dm
+++ b/code/datums/extensions/shearable/shearable.dm
@@ -20,6 +20,10 @@
fleece_material = GET_DECL(fleece_material)
START_PROCESSING(SSprocessing, src)
+/datum/extension/shearable/Destroy()
+ STOP_PROCESSING(SSprocessing, src)
+ return ..()
+
/datum/extension/shearable/Process()
if(has_fleece)
return PROCESS_KILL
diff --git a/code/datums/inventory_slots/slots/slot_ears.dm b/code/datums/inventory_slots/slots/slot_ears.dm
index b6dd92dd37f..295c24a5a89 100644
--- a/code/datums/inventory_slots/slots/slot_ears.dm
+++ b/code/datums/inventory_slots/slots/slot_ears.dm
@@ -36,7 +36,7 @@
inv_slot.clear_slot()
/datum/inventory_slot/ear/prop_can_fit_in_slot(var/obj/item/prop)
- return ..() || prop.w_class <= ITEM_SIZE_TINY
+ return ..() || (prop.w_class <= ITEM_SIZE_TINY && !(prop.obj_flags & OBJ_FLAG_NO_STORAGE))
/datum/inventory_slot/ear/right
slot_name = "Right Ear"
diff --git a/code/datums/proximity_trigger/proximity_trigger.dm b/code/datums/proximity_trigger/proximity_trigger.dm
index 065c64a1c47..afd59d7fab5 100644
--- a/code/datums/proximity_trigger/proximity_trigger.dm
+++ b/code/datums/proximity_trigger/proximity_trigger.dm
@@ -151,7 +151,7 @@ var/global/const/PROXIMITY_EXCLUDE_HOLDER_TURF = 1 // When acquiring turfs to mo
/datum/proximity_trigger/proc/update_opaque_atom(var/atom/opaque_atom)
var/turf/atom_loc = get_turf(opaque_atom)
- if(QDELETED(opaque_atom) || !opaque_atom.opacity || !atom_loc || !(atom_loc in turfs_in_range))
+ if(QDELETED(opaque_atom) || !opaque_atom.opacity || !atom_loc || !turfs_in_range[atom_loc])
events_repository.unregister(/decl/observ/opacity_set, opaque_atom, src, TYPE_PROC_REF(/datum/proximity_trigger, update_opaque_atom))
events_repository.unregister(/decl/observ/destroyed, opaque_atom, src, TYPE_PROC_REF(/datum/proximity_trigger, update_opaque_atom))
events_repository.unregister(/decl/observ/moved, opaque_atom, src, TYPE_PROC_REF(/datum/proximity_trigger, update_opaque_atom))
@@ -163,15 +163,17 @@ var/global/const/PROXIMITY_EXCLUDE_HOLDER_TURF = 1 // When acquiring turfs to mo
if(!center)
return
- FOR_DVIEW(var/T, range_, center, 0)
- if (T in turfs_in_range) // This is awful, but I don't want to refactor this to be assoc.
- . += T
+ FOR_DVIEW(var/turf/t, range_, center, 0)
+ if (turfs_in_range[t])
+ . += t
END_FOR_DVIEW
/datum/proximity_trigger/proc/acquire_relevant_turfs()
. = turf_selection.get_turfs(holder, range_, l_angle_, r_angle_)
if(proximity_flags & PROXIMITY_EXCLUDE_HOLDER_TURF)
. -= get_turf(holder)
+ for(var/T in .)
+ .[T] = TRUE
/obj/item/proxy_debug
abstract_type = /obj/item/proxy_debug
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 72360e20350..a2ea4962606 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -584,7 +584,7 @@
var/turf/T = get_turf(src)
var/list/mobs = list()
var/list/objs = list()
- get_mobs_and_objs_in_view_fast(T,range, mobs, objs, check_ghosts)
+ get_listeners_in_range(T,range, mobs, objs, check_ghosts)
for(var/o in objs)
var/obj/O = o
@@ -612,7 +612,7 @@
var/turf/T = get_turf(src)
var/list/mobs = list()
var/list/objs = list()
- get_mobs_and_objs_in_view_fast(T, hearing_distance, mobs, objs, check_ghosts)
+ get_listeners_in_range(T, hearing_distance, mobs, objs, check_ghosts)
for(var/m in mobs)
var/mob/M = m
@@ -991,4 +991,3 @@
/atom/proc/is_watertight()
return ATOM_IS_OPEN_CONTAINER(src)
-
diff --git a/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm b/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm
index 1fce02e2ca3..aed8aa4e95e 100644
--- a/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm
+++ b/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm
@@ -121,7 +121,7 @@
/obj/effect/bluegoast/proc/blueswitch()
var/mob/living/human/H
if(ishuman(daddy))
- H = new(get_turf(src), daddy.species.name, daddy.get_mob_snapshot(force = TRUE), daddy.get_bodytype())
+ H = new(get_turf(src), daddy.species.name, daddy.get_mob_snapshot(), daddy.get_bodytype())
for(var/obj/item/entry in daddy.get_equipped_items(TRUE))
daddy.remove_from_mob(entry) //steals instead of copies so we don't end up with duplicates
H.equip_to_appropriate_slot(entry)
diff --git a/code/game/gamemodes/wizard/servant_items/caretaker.dm b/code/game/gamemodes/wizard/servant_items/caretaker.dm
index 60707257859..c5adb272efe 100644
--- a/code/game/gamemodes/wizard/servant_items/caretaker.dm
+++ b/code/game/gamemodes/wizard/servant_items/caretaker.dm
@@ -9,7 +9,7 @@
ARMOR_ENERGY = ARMOR_ENERGY_SMALL,
ARMOR_RAD = ARMOR_RAD_SHIELDED
)
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
flags_inv = HIDEEARS | BLOCK_HEAD_HAIR
/obj/item/clothing/suit/caretakercloak
diff --git a/code/game/gamemodes/wizard/servant_items/champion.dm b/code/game/gamemodes/wizard/servant_items/champion.dm
index 91373fca725..80e04ee1bfd 100644
--- a/code/game/gamemodes/wizard/servant_items/champion.dm
+++ b/code/game/gamemodes/wizard/servant_items/champion.dm
@@ -11,7 +11,7 @@
ARMOR_BOMB = ARMOR_BOMB_RESISTANT,
ARMOR_BIO = ARMOR_BIO_MINOR
)
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
/obj/item/clothing/suit/champarmor
name = "champion's armor"
diff --git a/code/game/gamemodes/wizard/servant_items/fiend.dm b/code/game/gamemodes/wizard/servant_items/fiend.dm
index f4c52f75866..e52606eb62f 100644
--- a/code/game/gamemodes/wizard/servant_items/fiend.dm
+++ b/code/game/gamemodes/wizard/servant_items/fiend.dm
@@ -9,7 +9,7 @@
ARMOR_ENERGY = ARMOR_ENERGY_SMALL,
ARMOR_RAD = ARMOR_RAD_SHIELDED
)
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
flags_inv = HIDEEARS | BLOCK_HEAD_HAIR
/obj/item/clothing/suit/fiendcowl
@@ -29,7 +29,7 @@
name = "black suit"
desc = "A snappy black suit with red trim. The undershirt's stained with something, though..."
icon = 'icons/clothing/suits/suit_fiend.dmi'
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
/obj/item/clothing/shoes/dress/devilshoes
desc = "Off-colour leather dress shoes. Their footsteps are silent."
diff --git a/code/game/gamemodes/wizard/servant_items/infiltrator.dm b/code/game/gamemodes/wizard/servant_items/infiltrator.dm
index 0efb01274eb..846addc5b7c 100644
--- a/code/game/gamemodes/wizard/servant_items/infiltrator.dm
+++ b/code/game/gamemodes/wizard/servant_items/infiltrator.dm
@@ -11,7 +11,7 @@
ARMOR_LASER = ARMOR_LASER_MINOR,
ARMOR_ENERGY = ARMOR_ENERGY_MINOR
)
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
/obj/item/clothing/suit/infilsuit
name = "immaculate suit"
diff --git a/code/game/gamemodes/wizard/servant_items/overseer.dm b/code/game/gamemodes/wizard/servant_items/overseer.dm
index 9274cb20574..f8676e0440d 100644
--- a/code/game/gamemodes/wizard/servant_items/overseer.dm
+++ b/code/game/gamemodes/wizard/servant_items/overseer.dm
@@ -12,7 +12,7 @@
item_flags = ITEM_FLAG_AIRTIGHT
max_pressure_protection = FIRESUIT_MAX_PRESSURE
min_pressure_protection = 0
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
flags_inv = HIDEEARS | BLOCK_HEAD_HAIR
/obj/item/clothing/suit/straight_jacket/overseercloak
diff --git a/code/game/machinery/CableLayer.dm b/code/game/machinery/CableLayer.dm
index 0501f7f3a67..8a4ff9d1bd6 100644
--- a/code/game/machinery/CableLayer.dm
+++ b/code/game/machinery/CableLayer.dm
@@ -85,7 +85,7 @@
if(istype(new_turf, /turf/floor))
var/turf/floor/T = new_turf
if(!T.is_plating())
- T.make_plating(!T.is_floor_damaged())
+ T.set_flooring(null, place_product = !T.is_floor_damaged())
return new_turf.is_plating()
/obj/machinery/cablelayer/proc/layCable(var/turf/new_turf,var/M_Dir)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index e345957b733..65f6f87a176 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -91,6 +91,7 @@
var/emag_file = 'icons/obj/doors/station/emag.dmi'
/obj/machinery/door/airlock/get_material()
+ RETURN_TYPE(/decl/material)
return GET_DECL(mineral ? mineral : /decl/material/solid/metal/steel)
/obj/machinery/door/airlock/proc/get_window_material()
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index af47a4e9def..707a91143d3 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -138,6 +138,7 @@
force_close()
/obj/machinery/door/blast/get_material()
+ RETURN_TYPE(/decl/material)
return implicit_material
// Proc: attackby()
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index ffdf5fc9c7a..8e60582e0a3 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -114,6 +114,7 @@
register_area(area)
/obj/machinery/door/firedoor/get_material()
+ RETURN_TYPE(/decl/material)
return GET_DECL(/decl/material/solid/metal/steel)
/obj/machinery/door/firedoor/examine(mob/user, distance)
diff --git a/code/game/machinery/floorlayer.dm b/code/game/machinery/floorlayer.dm
index 185879c1812..e51b20d8362 100644
--- a/code/game/machinery/floorlayer.dm
+++ b/code/game/machinery/floorlayer.dm
@@ -82,7 +82,7 @@
if(istype(new_turf, /turf/floor))
var/turf/floor/T = new_turf
if(!T.is_plating())
- T.make_plating(!T.is_floor_damaged())
+ T.set_flooring(null, place_product = !T.is_floor_damaged())
return new_turf.is_plating()
/obj/machinery/floorlayer/proc/TakeNewStack()
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index a3a7e7e34ca..9d871d3e2b5 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -63,8 +63,9 @@ var/global/list/holopads = list()
/obj/machinery/hologram/holopad/Initialize()
. = ..()
- // Null ID means we want to use our area name.
global.holopads += src
+ global.listening_objects += src
+ // Null ID means we want to use our area name.
if(isnull(holopad_id))
var/area/A = get_area(src)
holopad_id = A?.proper_name || "Unknown"
@@ -77,6 +78,10 @@ var/global/list/holopads = list()
// Update our desc.
desc = "It's a floor-mounted device for projecting holographic images. Its ID is '[holopad_id]'"
+/obj/machinery/hologram/holopad/Destroy()
+ global.listening_objects -= src
+ return ..()
+
/obj/machinery/hologram/holopad/interface_interact(var/mob/living/human/user) //Carn: Hologram requests.
if(!CanInteract(user, DefaultTopicState()))
return FALSE
diff --git a/code/game/machinery/nuclear_bomb.dm b/code/game/machinery/nuclear_bomb.dm
index 07c6c5ecc30..d3465ff698f 100644
--- a/code/game/machinery/nuclear_bomb.dm
+++ b/code/game/machinery/nuclear_bomb.dm
@@ -462,7 +462,7 @@ var/global/bomb_set
. = ..()
verbs -= /obj/machinery/nuclearbomb/verb/toggle_deployable
for(var/turf/floor/T in get_area(src))
- if(istype(T.flooring, /decl/flooring/reinforced/circuit/red))
+ if(istype(T.get_topmost_flooring(), /decl/flooring/reinforced/circuit/red))
flash_tiles += T
update_icon()
for(var/obj/machinery/self_destruct/ch in get_area(src))
@@ -547,7 +547,7 @@ var/global/bomb_set
if(!last_turf_state || target_icon_state != last_turf_state)
for(var/thing in flash_tiles)
var/turf/floor/T = thing
- if(!istype(T.flooring, /decl/flooring/reinforced/circuit/red))
+ if(!istype(T.get_topmost_flooring(), /decl/flooring/reinforced/circuit/red))
flash_tiles -= T
continue
T.icon_state = target_icon_state
diff --git a/code/game/machinery/pipe/pipelayer.dm b/code/game/machinery/pipe/pipelayer.dm
index fcf03128bd6..457062889fa 100644
--- a/code/game/machinery/pipe/pipelayer.dm
+++ b/code/game/machinery/pipe/pipelayer.dm
@@ -111,7 +111,7 @@
if(istype(new_turf, /turf/floor))
var/turf/floor/T = new_turf
if(!T.is_plating())
- T.make_plating(!T.is_floor_damaged())
+ T.set_flooring(null, place_product = !T.is_floor_damaged())
return new_turf.is_plating()
/obj/machinery/pipelayer/proc/layPipe(var/turf/w_turf,var/M_Dir,var/old_dir)
diff --git a/code/game/machinery/vending/actors.dm b/code/game/machinery/vending/actors.dm
index 4808085a60c..6ab863b7612 100644
--- a/code/game/machinery/vending/actors.dm
+++ b/code/game/machinery/vending/actors.dm
@@ -10,7 +10,6 @@
/obj/structure/flora/pottedplant = 2,
/obj/item/flashlight/lamp = 2,
/obj/item/flashlight/lamp/green = 2,
- /obj/item/chems/drinks/jar = 1,
/obj/item/nullrod = 1,
/obj/item/sword/cult_toy = 4,
/obj/item/sword/katana/toy = 2
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index 7cc4cb21b22..638b704a188 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -93,10 +93,10 @@
to_world_log("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
return 1
-#define EXPLFX_BOTH 3
-#define EXPLFX_SOUND 2
-#define EXPLFX_SHAKE 1
-#define EXPLFX_NONE 0
+#define EXPLFX_NONE 0
+#define EXPLFX_SOUND BITFLAG(0)
+#define EXPLFX_SHAKE BITFLAG(1)
+#define EXPLFX_BOTH (EXPLFX_SOUND|EXPLFX_SHAKE)
// All the vars used on the turf should be on unsimulated turfs too, we just don't care about those generally.
#define SEARCH_DIR(dir) \
@@ -207,8 +207,9 @@
reception = EXPLFX_NONE
for (var/turf/THING as anything in RANGE_TURFS(M, 1))
- reception |= EXPLFX_SHAKE
- break
+ if(THING.simulated)
+ reception |= EXPLFX_SHAKE
+ break
if (!reception)
CHECK_TICK
diff --git a/code/game/objects/items/_item_materials.dm b/code/game/objects/items/_item_materials.dm
index 62bc4ad063e..ab9d0ed512a 100644
--- a/code/game/objects/items/_item_materials.dm
+++ b/code/game/objects/items/_item_materials.dm
@@ -54,7 +54,8 @@
qdel(src)
/obj/item/get_material()
- . = material
+ RETURN_TYPE(/decl/material)
+ return material
// TODO: Refactor more code to use this where necessary, and then make this use
// some sort of generalized system for hitting with different parts of an item
diff --git a/code/game/objects/items/devices/paint_sprayer.dm b/code/game/objects/items/devices/paint_sprayer.dm
index 816f48e33c8..a9dbd8a0878 100644
--- a/code/game/objects/items/devices/paint_sprayer.dm
+++ b/code/game/objects/items/devices/paint_sprayer.dm
@@ -216,11 +216,13 @@
/obj/item/paint_sprayer/proc/paint_floor(var/turf/floor/F, var/mob/user, var/params)
- if(!F.flooring)
+
+ var/decl/flooring/flooring = F.get_topmost_flooring()
+ if(!istype(flooring))
to_chat(user, SPAN_WARNING("You need flooring to paint on."))
return FALSE
- if(!F.flooring.can_paint || F.is_floor_damaged())
+ if(!flooring.can_paint || F.is_floor_damaged())
to_chat(user, SPAN_WARNING("\The [src] cannot paint \the [F.name]."))
return FALSE
diff --git a/code/game/objects/items/flame/_flame.dm b/code/game/objects/items/flame/_flame.dm
index eab10674099..3641ce07c8e 100644
--- a/code/game/objects/items/flame/_flame.dm
+++ b/code/game/objects/items/flame/_flame.dm
@@ -32,6 +32,8 @@
var/can_manually_light = FALSE
/// Can this item be put into a sconce?
var/sconce_can_hold = FALSE
+ /// Can this item go in a bag or storage slot while lit?
+ var/can_store_lit = FALSE
/obj/item/flame/Initialize(var/ml, var/material_key)
@@ -75,6 +77,8 @@
if(lit || !has_fuel(_fuel_spend_amt))
return FALSE
lit = TRUE
+ if(!can_store_lit)
+ obj_flags |= OBJ_FLAG_NO_STORAGE
atom_damage_type = BURN
update_attack_force()
@@ -115,6 +119,8 @@
if(!lit)
return FALSE
lit = FALSE
+ if(!can_store_lit && !(initial(obj_flags) & OBJ_FLAG_NO_STORAGE)) // only disable it if it wasn't already set
+ obj_flags &= ~OBJ_FLAG_NO_STORAGE
atom_damage_type = BRUTE
update_attack_force()
diff --git a/code/game/objects/items/flame/flame_fuelled_lantern.dm b/code/game/objects/items/flame/flame_fuelled_lantern.dm
index 2a144cec9d5..38d4ca1f22f 100644
--- a/code/game/objects/items/flame/flame_fuelled_lantern.dm
+++ b/code/game/objects/items/flame/flame_fuelled_lantern.dm
@@ -17,6 +17,7 @@
color = /decl/material/solid/metal/copper::color
can_manually_light = FALSE
sconce_can_hold = TRUE
+ can_store_lit = TRUE
/obj/item/flame/fuelled/lantern/get_sconce_overlay()
. = list(overlay_image(icon, "[icon_state]-sconce", color = color, flags = RESET_COLOR))
diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm
index 7a6097b9741..d88d703659a 100644
--- a/code/game/objects/items/stacks/nanopaste.dm
+++ b/code/game/objects/items/stacks/nanopaste.dm
@@ -12,44 +12,59 @@
/obj/item/stack/nanopaste/use_on_mob(mob/living/target, mob/living/user, animate = TRUE)
+ if (!istype(target))
+ to_chat(user, SPAN_WARNING("\The [src] cannot be applied to \the [target]!"))
+ return TRUE
+
+ if (!ishuman(user) && !issilicon(user))
+ to_chat(user, SPAN_WARNING("You don't have the dexterity to do this!"))
+ return TRUE
+
if (isrobot(target)) //Repairing cyborgs
var/mob/living/silicon/robot/R = target
- if (R.get_damage(BRUTE) || R.get_damage(BURN) )
+ if (R.getBruteLoss() || R.getFireLoss() )
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
R.heal_damage(BRUTE, 15, do_update_health = FALSE)
R.heal_damage(BURN, 15)
use(1)
user.visible_message(
- SPAN_NOTICE("\The [user] applied some [src] on [R]'s damaged areas."),
- SPAN_NOTICE("You apply some [src] at [R]'s damaged areas.")
+ SPAN_NOTICE("\The [user] applied some [name] to \the [R]'s damaged areas."),
+ SPAN_NOTICE("You apply some [name] to \the [R]'s damaged areas.")
)
else
- to_chat(user, SPAN_NOTICE("All [R]'s systems are nominal."))
- return TRUE
-
- if (ishuman(target)) //Repairing robolimbs
- var/mob/living/human/H = target
- var/obj/item/organ/external/S = GET_EXTERNAL_ORGAN(H, user.get_target_zone())
-
- if(!S)
- to_chat(user, SPAN_WARNING("\The [target] is missing that body part."))
- return TRUE
-
- if(BP_IS_BRITTLE(S))
- to_chat(user, SPAN_WARNING("\The [target]'s [S.name] is hard and brittle - \the [src] cannot repair it."))
- return TRUE
-
- if(S && S.is_robotic() && S.hatch_state == HATCH_OPENED)
- if(!S.get_damage())
- to_chat(user, SPAN_NOTICE("Nothing to fix here."))
- else if(can_use(1))
- user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
- S.heal_damage(15, 15, robo_repair = 1)
- use(1)
- user.visible_message(
- SPAN_NOTICE("\The [user] applies some nanite paste on [user != target ? "[target]'s [S.name]" : "[S]"] with [src]."),
- SPAN_NOTICE("You apply some nanite paste on [user == target ? "your" : "[target]'s"] [S.name].")
- )
- return TRUE
+ to_chat(user, SPAN_NOTICE("\The [R]'s systems are all nominal."))
+ return TRUE
+ //Repairing robolimbs
+ var/obj/item/organ/external/affecting = GET_EXTERNAL_ORGAN(target, user.get_target_zone())
+
+ if(!affecting)
+ to_chat(user, SPAN_WARNING("\The [target] is missing that body part."))
+ return TRUE
+
+ if(BP_IS_BRITTLE(affecting))
+ to_chat(user, SPAN_WARNING("\The [target]'s [affecting.name] is hard and brittle - \the [src] cannot repair it."))
+ return TRUE
+
+ if(!affecting.is_robotic())
+ to_chat(user, SPAN_WARNING("\The [target]'s [affecting.name] is flesh and blood, and cannot be repaired with \the [src]."))
+ return TRUE
+
+ if(affecting.damage >= 30 && affecting.hatch_state != HATCH_OPENED)
+ to_chat(user, SPAN_WARNING("The damage to \the [affecting] is too severe to repair without an open maintenance hatch."))
+ return TRUE
+
+ if(!affecting.get_damage())
+ to_chat(user, SPAN_NOTICE("Nothing to fix here."))
+ return TRUE
+
+ if(can_use(1))
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ affecting.heal_damage(15, 15, robo_repair = 1)
+ use(1)
+ user.visible_message(
+ SPAN_NOTICE("\The [user] applies some [name] to \the [user != target ? "[target]'s [affecting.name]" : "[affecting]"] with [src]."),
+ SPAN_NOTICE("You apply some [name] to [user == target ? "your" : "\the [target]'s"] [affecting.name].")
+ )
+ return TRUE
return ..()
diff --git a/code/game/objects/items/weapons/broom.dm b/code/game/objects/items/weapons/broom.dm
index b628b4ea79e..29c016a2418 100644
--- a/code/game/objects/items/weapons/broom.dm
+++ b/code/game/objects/items/weapons/broom.dm
@@ -45,10 +45,10 @@
if(isturf(A))
var/turf/cleaning = A
var/dirty = cleaning.get_dirt()
- if(dirty)
+ if(dirty > 10) // a small amount so that you can't sweep immediately after someone walks somewhere
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.visible_message(SPAN_NOTICE("\The [user] sweeps \the [A]."))
- // TODO: shff sound
+ playsound(A, "sweeping", 100, TRUE)
cleaning.remove_dirt(min(dirty, rand(20,30)))
else
to_chat(user, SPAN_WARNING("\The [cleaning] is not in need of sweeping."))
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 94239dc2dea..1ad21ad4a4f 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -189,6 +189,7 @@
matter = list(/decl/material/solid/metal/copper = MATTER_AMOUNT_SECONDARY, /decl/material/solid/metal/steel = MATTER_AMOUNT_SECONDARY)
max_health = ITEM_HEALTH_NO_DAMAGE
_base_attack_force = 2
+ can_be_twohanded = TRUE
var/safety = 1 //if you can zap people with the paddles on harm mode
var/combat = 0 //If it can be used to revive people wearing thick clothing (e.g. spacesuits)
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 26ad711148e..69ac907bcac 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -10,13 +10,14 @@
var/list/victims = list()
var/list/objs = list()
var/turf/T = get_turf(src)
- get_mobs_and_objs_in_view_fast(T, 7, victims, objs)
+ get_listeners_in_range(T, 7, victims, objs)
for(var/mob/living/M in victims)
bang(T, M)
- for(var/obj/effect/blob/B in objs) //Blob damage here
+ FOR_DVIEW(var/obj/effect/blob/B, 7, T, INVISIBILITY_MAXIMUM) //Blob damage here
var/damage = round(30/(get_dist(B,T)+1))
B.take_damage(damage, BURN)
+ END_FOR_DVIEW
new /obj/effect/sparks(loc)
new /obj/effect/effect/smoke/illumination(loc, 5, 30, 1, "#ffffff")
diff --git a/code/game/objects/items/weapons/melee/energy_projected.dm b/code/game/objects/items/weapons/melee/energy_projected.dm
index a6dbb10baa7..927cff0a5f9 100644
--- a/code/game/objects/items/weapons/melee/energy_projected.dm
+++ b/code/game/objects/items/weapons/melee/energy_projected.dm
@@ -22,6 +22,7 @@
. = ..()
if(!ismob(loc))
return INITIALIZE_HINT_QDEL
+ set_extension(src, /datum/extension/demolisher/energy)
/obj/item/energy_blade/projected/is_special_cutting_tool(var/high_power)
return active
diff --git a/code/game/objects/items/weapons/melee/energy_sword.dm b/code/game/objects/items/weapons/melee/energy_sword.dm
index 323a2ab8d50..3d20dd638d3 100644
--- a/code/game/objects/items/weapons/melee/energy_sword.dm
+++ b/code/game/objects/items/weapons/melee/energy_sword.dm
@@ -21,6 +21,10 @@
lighting_color = blade_color
. = ..()
+/obj/item/energy_blade/sword/Initialize()
+ . = ..()
+ set_extension(src, /datum/extension/demolisher/energy)
+
/obj/item/energy_blade/sword/is_special_cutting_tool(var/high_power)
return active && !high_power
diff --git a/code/game/objects/items/weapons/tools/crowbar.dm b/code/game/objects/items/weapons/tools/crowbar.dm
index d4f5a30e1cf..99ee7edcc83 100644
--- a/code/game/objects/items/weapons/tools/crowbar.dm
+++ b/code/game/objects/items/weapons/tools/crowbar.dm
@@ -29,6 +29,7 @@
/obj/item/crowbar/Initialize()
. = ..()
set_extension(src, /datum/extension/tool, list(TOOL_CROWBAR = TOOL_QUALITY_DEFAULT))
+ set_extension(src, /datum/extension/demolisher/delicate)
/obj/item/crowbar/get_autopsy_descriptors()
. = ..()
diff --git a/code/game/objects/items/weapons/tools/weldingtool.dm b/code/game/objects/items/weapons/tools/weldingtool.dm
index fe9b04adfcc..2143a7297eb 100644
--- a/code/game/objects/items/weapons/tools/weldingtool.dm
+++ b/code/game/objects/items/weapons/tools/weldingtool.dm
@@ -32,6 +32,7 @@
insert_tank(new tank, null, TRUE, TRUE)
set_extension(src, /datum/extension/tool, list(TOOL_WELDER = TOOL_QUALITY_DEFAULT))
set_extension(src, /datum/extension/base_icon_state, icon_state)
+ set_extension(src, /datum/extension/demolisher/welder)
. = ..()
update_icon()
@@ -343,20 +344,17 @@
return turn_on(user)
/obj/item/weldingtool/use_on_mob(mob/living/target, mob/living/user, animate = TRUE)
- if(ishuman(target))
- var/mob/living/human/H = target
- var/obj/item/organ/external/S = GET_EXTERNAL_ORGAN(H, user?.get_target_zone())
- if(!S || !S.is_robotic() || user.a_intent != I_HELP)
- return ..()
- if(BP_IS_BRITTLE(S))
- to_chat(user, SPAN_WARNING("\The [target]'s [S.name] is hard and brittle - \the [src] cannot repair it."))
- return TRUE
- if(!welding)
- to_chat(user, SPAN_WARNING("You'll need to turn [src] on to patch the damage on [target]'s [S.name]!"))
- return TRUE
- if(S.robo_repair(15, BRUTE, "some dents", src, user))
+ var/obj/item/organ/external/affecting = istype(target) && GET_EXTERNAL_ORGAN(target, user?.get_target_zone())
+ if(affecting && user.a_intent == I_HELP)
+ if(!affecting.is_robotic())
+ to_chat(user, SPAN_WARNING("\The [target]'s [affecting.name] is not robotic. \The [src] cannot repair it."))
+ else if(BP_IS_BRITTLE(affecting))
+ to_chat(user, SPAN_WARNING("\The [target]'s [affecting.name] is hard and brittle. \The [src] cannot repair it."))
+ else if(!welding)
+ to_chat(user, SPAN_WARNING("You'll need to turn \the [src] on to patch the damage on \the [target]'s [affecting.name]!"))
+ else if(affecting.robo_repair(15, BRUTE, "some dents", src, user))
weld(1, user)
- return TRUE
+ return TRUE
return ..()
/obj/item/weldingtool/get_autopsy_descriptors()
diff --git a/code/game/objects/structures/_structure_materials.dm b/code/game/objects/structures/_structure_materials.dm
index 33e4c24426b..5e76990a22e 100644
--- a/code/game/objects/structures/_structure_materials.dm
+++ b/code/game/objects/structures/_structure_materials.dm
@@ -5,7 +5,8 @@
var/dismantled
/obj/structure/get_material()
- . = material
+ RETURN_TYPE(/decl/material)
+ return material
/obj/structure/proc/get_material_health_modifier()
. = 1
diff --git a/code/game/objects/structures/banners.dm b/code/game/objects/structures/banners.dm
index 440c5e39826..c00d20b438a 100644
--- a/code/game/objects/structures/banners.dm
+++ b/code/game/objects/structures/banners.dm
@@ -143,13 +143,17 @@
color = /decl/material/solid/organic/wood/ebony::color
/obj/structure/banner_frame/wall/ebony/red
+ banner = /obj/item/banner/red
color = /obj/item/banner/red::color // Mapping preview colour.
/obj/structure/banner_frame/wall/ebony/blue
+ banner = /obj/item/banner/blue
color = /obj/item/banner/blue::color
/obj/structure/banner_frame/wall/ebony/green
+ banner = /obj/item/banner/green
color = /obj/item/banner/green::color
/obj/structure/banner_frame/wall/ebony/woven
+ banner = /obj/item/banner/woven
color = /obj/item/banner/woven::color
\ No newline at end of file
diff --git a/code/game/objects/structures/bookcase.dm b/code/game/objects/structures/bookcase.dm
index 79881eb7859..928d5cbb044 100644
--- a/code/game/objects/structures/bookcase.dm
+++ b/code/game/objects/structures/bookcase.dm
@@ -197,4 +197,8 @@ var/global/list/station_bookcases = list()
tool_interaction_flags = TOOL_INTERACTION_DECONSTRUCT
obj_flags = 0
+/obj/structure/bookcase/ebony
+ material = /decl/material/solid/organic/wood/ebony
+ color = /decl/material/solid/organic/wood/ebony::color
+
#undef GET_BOOK_POS
diff --git a/code/game/objects/structures/coathanger.dm b/code/game/objects/structures/coathanger.dm
index 6461e0ca68b..2360879e427 100644
--- a/code/game/objects/structures/coathanger.dm
+++ b/code/game/objects/structures/coathanger.dm
@@ -4,12 +4,17 @@
icon = 'icons/obj/structures/coatrack.dmi'
icon_state = "coatrack0"
material = /decl/material/solid/organic/wood/mahogany
+ color = /decl/material/solid/organic/wood/mahogany::color
material_alteration = (MAT_FLAG_ALTERATION_NAME | MAT_FLAG_ALTERATION_COLOR)
tool_interaction_flags = TOOL_INTERACTION_DECONSTRUCT
var/max_items = 3
var/tmp/list/slots_allowed
var/tmp/list/blacklisted_types = list(/obj/item/clothing/suit/space)
+/obj/structure/coatrack/ebony
+ material = /decl/material/solid/organic/wood/ebony
+ color = /decl/material/solid/organic/wood/ebony::color
+
/obj/structure/coatrack/dismantle_structure(mob/user)
for(var/obj/item/thing in contents)
thing.dropInto(loc)
diff --git a/code/game/objects/structures/fires.dm b/code/game/objects/structures/fires.dm
index 0f15c4f6dc4..faf17bcae81 100644
--- a/code/game/objects/structures/fires.dm
+++ b/code/game/objects/structures/fires.dm
@@ -487,7 +487,7 @@
/obj/structure/fire_source/CanPass(atom/movable/mover, turf/target, height, air_group)
. = ..()
- if(lit && ismob(mover))
+ if(. && lit && ismob(mover))
var/mob/M = mover
if(!MOVING_QUICKLY(M))
to_chat(M, SPAN_WARNING("You refrain from stepping into \the [src]."))
diff --git a/code/game/objects/structures/stool_bed_chair_nest_sofa/pew.dm b/code/game/objects/structures/stool_bed_chair_nest_sofa/pew.dm
index c8e72f75d05..9e849a85d38 100644
--- a/code/game/objects/structures/stool_bed_chair_nest_sofa/pew.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest_sofa/pew.dm
@@ -93,6 +93,15 @@
update_icon()
+/obj/structure/bed/chair/bench/proc/get_material_icon()
+ return material?.bench_icon
+
+/obj/structure/bed/chair/bench/update_materials()
+ . = ..()
+ var/icon/material_icon = get_material_icon()
+ if(material_icon)
+ icon = material_icon
+
/obj/structure/bed/chair/bench/mahogany
color = WOOD_COLOR_RICH
material = /decl/material/solid/organic/wood/mahogany
@@ -108,6 +117,9 @@
icon_state = "pew_standing"
base_icon = "pew"
+/obj/structure/bed/chair/bench/pew/get_material_icon()
+ return material?.pew_icon
+
/obj/structure/bed/chair/bench/pew/single
name = "backed chair"
desc = "A tall chair with a sturdy back. Not very comfortable."
@@ -115,5 +127,9 @@
connect_neighbors = FALSE
/obj/structure/bed/chair/bench/pew/mahogany
- color = WOOD_COLOR_RICH
+ color = /decl/material/solid/organic/wood/mahogany::color
material = /decl/material/solid/organic/wood/mahogany
+
+/obj/structure/bed/chair/bench/pew/ebony
+ color = /decl/material/solid/organic/wood/ebony::color
+ material = /decl/material/solid/organic/wood/ebony
\ No newline at end of file
diff --git a/code/game/objects/structures/wall_sconce.dm b/code/game/objects/structures/wall_sconce.dm
index 8a1323e989d..8339a0d3b6c 100644
--- a/code/game/objects/structures/wall_sconce.dm
+++ b/code/game/objects/structures/wall_sconce.dm
@@ -29,6 +29,7 @@
max_health = 100
w_class = ITEM_SIZE_LARGE
directional_offset = @'{"NORTH":{"y":24}, "SOUTH":{"y":-1}, "EAST":{"x":10,"y":10}, "WEST":{"x":-10,"y":10}}'
+ layer = ABOVE_HUMAN_LAYER
/// Reference to the currently attached item.
var/obj/item/flame/light_source
/// Whether or not the light source, if present, is automatically lit on Initialize.
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 7b2892a9de1..a729a23fb5b 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -161,6 +161,7 @@ var/global/const/FALLOFF_SOUNDS = 0.5
if ("chop") soundin = pick(global.chop_sound)
if ("glasscrack") soundin = pick(global.glasscrack_sound)
if ("tray_hit") soundin = pick(global.tray_hit_sound)
+ if ("sweeping") soundin = pick(global.sweeping_sound)
return soundin
diff --git a/code/game/turfs/flooring/_flooring.dm b/code/game/turfs/flooring/_flooring.dm
index ddf86756a04..c31500af0c4 100644
--- a/code/game/turfs/flooring/_flooring.dm
+++ b/code/game/turfs/flooring/_flooring.dm
@@ -9,47 +9,63 @@ var/global/list/flooring_cache = list()
/decl/flooring
abstract_type = /decl/flooring
+
var/name
var/desc
var/icon
var/icon_base
- var/color
+ var/color = COLOR_WHITE
var/footstep_type = /decl/footsteps/blank
+ var/growth_value = 0
+
+ var/neighbour_type
var/has_base_range
var/damage_temperature
+ var/icon_edge_layer = FLOOR_EDGE_NONE
+ var/has_environment_proc
- var/build_type // Unbuildable if not set. Must be /obj/item/stack.
- var/build_material // Unbuildable if object material var is not set to this.
- var/build_cost = 1 // Stack units.
- var/build_time = 0 // BYOND ticks.
+ /// Unbuildable if not set. Must be /obj/item/stack.
+ var/build_type
+ /// Unbuildable if object material var is not set to this.
+ var/build_material
+ /// Stack units.
+ var/build_cost = 1
+ /// BYOND ticks.
+ var/build_time = 0
- var/descriptor = "tiles"
- var/flags
+ var/descriptor
+ var/flooring_flags
var/remove_timer = 10
var/can_paint
var/can_engrave = TRUE
+ var/turf_light_range
+ var/turf_light_power
+ var/turf_light_color
+
+ var/decl/material/force_material
+
var/movement_delay
- //How we smooth with other flooring
- var/decal_layer = DECAL_LAYER
- var/floor_smooth = SMOOTH_ALL
/// Smooth with nothing except the types in this list. Turned into a typecache for performance reasons.
var/list/flooring_whitelist = list()
/// Smooth with everything except the types in this list. Turned into a typecache for performance reasons.
var/list/flooring_blacklist = list()
- //How we smooth with walls
- var/wall_smooth = SMOOTH_ALL
- //There are no lists for walls at this time
+ /// How we smooth with other flooring
+ var/floor_smooth
+ /// How we smooth with walls
+ var/wall_smooth
+ /// How we smooth with space and openspace tiles
+ var/space_smooth
- //How we smooth with space and openspace tiles
- var/space_smooth = SMOOTH_ALL
- //There are no lists for spaces
- var/z_flags //same z flags used for turfs, i.e ZMIMIC_DEFAULT etc
+ /// same z flags used for turfs, i.e ZMIMIC_DEFAULT etc
+ var/z_flags
+ /// Flags to apply to the turf.
+ var/turf_flags
- var/height = 0
+ var/constructed = FALSE
var/has_internal_edges = FALSE
var/has_external_edges = FALSE
@@ -59,10 +75,30 @@ var/global/list/flooring_cache = list()
var/outer_corner_state
var/render_trenches = TRUE
+ var/floor_layer = TURF_LAYER
+ var/holographic = FALSE
+ var/dirt_color = "#7c5e42"
/decl/flooring/Initialize()
. = ..()
+ neighbour_type ||= type
+
+ if(ispath(force_material))
+ force_material = GET_DECL(force_material)
+ if(!istype(force_material))
+ force_material = null
+
+ if(holographic)
+ turf_flags = null
+ damage_temperature = INFINITY
+ build_type = null
+ build_material = null
+ flooring_flags = null
+ can_paint = FALSE
+ can_engrave = FALSE
+ constructed = TRUE
+
edge_state = "[icon_base]_edges"
corner_state = "[icon_base]_corners"
outer_edge_state = "[icon_base]_outer_edges"
@@ -73,6 +109,14 @@ var/global/list/flooring_cache = list()
has_internal_edges = check_state_in_icon(edge_state, icon) || check_state_in_icon(corner_state, icon)
has_external_edges = check_state_in_icon(outer_edge_state, icon) || check_state_in_icon(outer_corner_state, icon)
+ var/default_smooth = (has_internal_edges || has_external_edges) ? SMOOTH_NONE : SMOOTH_ALL
+ if(isnull(wall_smooth))
+ wall_smooth = default_smooth
+ if(isnull(space_smooth))
+ space_smooth = default_smooth
+ if(isnull(floor_smooth))
+ floor_smooth = default_smooth
+
/decl/flooring/validate()
. = ..()
@@ -107,49 +151,68 @@ var/global/list/flooring_cache = list()
if(!check_state_in_icon(outer_corner_state, icon))
. += "flagged for external edges but missing corner state from '[icon]'"
-/decl/flooring/proc/update_turf_icon(turf/floor/target)
+/decl/flooring/proc/get_surface_descriptor()
+ return descriptor || name || "terrain"
+/decl/flooring/proc/update_turf_strings(turf/floor/target)
target.SetName(name)
- target.desc = desc
+ target.desc = desc
+
+/decl/flooring/proc/update_turf_icon(turf/floor/target)
+
if(target.icon != icon)
- target.icon = icon
- if(target.color != color)
- target.color = color
- if(!target.flooring_override)
- target.flooring_override = icon_base
+ target.icon = icon
+ if(!target.floor_icon_state_override)
+ target.floor_icon_state_override = icon_base
if(has_base_range)
- target.flooring_override = "[target.flooring_override][rand(0,has_base_range)]"
+ target.floor_icon_state_override = "[target.floor_icon_state_override][rand(0,has_base_range)]"
+
+ if(target.icon_state != target.floor_icon_state_override)
+ target.icon_state = target.floor_icon_state_override
- if(target.icon_state != target.flooring_override)
- target.icon_state = target.flooring_override
+ if(color)
+ target.color = color
+ else
+ var/decl/material/use_material = target.get_material()
+ target.color = use_material?.color
+ var/edge_layer = (icon_edge_layer != FLOOR_EDGE_NONE) ? target.layer + icon_edge_layer : target.layer
+ var/list/edge_overlays = list()
var/has_border = 0
for(var/step_dir in global.cardinal)
- var/turf/floor/T = get_step(target, step_dir)
- var/is_linked = symmetric_test_link(target, T)
- if (!is_linked)
- has_border |= step_dir
+ var/turf/T = get_step_resolving_mimic(target, step_dir)
+ if(!istype(T) || symmetric_test_link(target, T))
+ continue
+ has_border |= step_dir
+ if(icon_edge_layer != FLOOR_EDGE_NONE)
if(has_internal_edges)
- target.add_overlay(get_flooring_overlay("[icon]_[icon_base]-edge-[step_dir]", edge_state, step_dir))
- if(has_external_edges)
- target.add_overlay(get_flooring_overlay("[icon]_[icon_base]-outer-edge-[step_dir]", outer_edge_state, step_dir, TRUE))
+ edge_overlays += get_flooring_overlay("[icon]_[icon_base]-edge-[step_dir]", edge_state, step_dir, edge_layer = edge_layer)
+ if(has_external_edges && target.can_draw_edge_over(T))
+ edge_overlays += get_flooring_overlay("[icon]_[icon_base]-outer-edge-[step_dir]", outer_edge_state, step_dir, TRUE, edge_layer = edge_layer)
if (has_internal_edges || has_external_edges)
var/has_smooth = ~(has_border & (NORTH | SOUTH | EAST | WEST))
for(var/step_dir in global.cornerdirs)
- if(!symmetric_test_link(target, get_step(target, step_dir)))
+ var/turf/T = get_step_resolving_mimic(target, step_dir)
+ if(!istype(T) || symmetric_test_link(target, T))
+ continue
+ if(icon_edge_layer != FLOOR_EDGE_NONE)
if(has_internal_edges)
if((has_smooth & step_dir) == step_dir)
- target.add_overlay(get_flooring_overlay("[icon]_[icon_base]-corner-[step_dir]", corner_state, step_dir))
+ edge_overlays += get_flooring_overlay("[icon]_[icon_base]-corner-[step_dir]", corner_state, step_dir, edge_layer = edge_layer)
else if((has_border & step_dir) == step_dir)
- target.add_overlay(get_flooring_overlay("[icon]_[icon_base]-edge-[step_dir]", edge_state, step_dir))
- if(has_external_edges)
+ edge_overlays += get_flooring_overlay("[icon]_[icon_base]-edge-[step_dir]", edge_state, step_dir, edge_layer = edge_layer)
+ if(has_external_edges && target.can_draw_edge_over(T))
if((has_smooth & step_dir) == step_dir)
- target.add_overlay(get_flooring_overlay("[icon]_[icon_base]-outer-corner-[step_dir]", outer_corner_state, step_dir, TRUE))
+ edge_overlays += get_flooring_overlay("[icon]_[icon_base]-outer-corner-[step_dir]", outer_corner_state, step_dir, TRUE, edge_layer = edge_layer)
else if((has_border & step_dir) == step_dir)
- target.add_overlay(get_flooring_overlay("[icon]_[icon_base]-outer-edge-[step_dir]", outer_edge_state, step_dir, TRUE))
+ edge_overlays += get_flooring_overlay("[icon]_[icon_base]-outer-edge-[step_dir]", outer_edge_state, step_dir, TRUE, edge_layer = edge_layer)
+
+ if(length(edge_overlays))
+ target.add_overlay(edge_overlays)
-/decl/flooring/proc/get_flooring_overlay(var/cache_key, var/icon_base, var/icon_dir = 0, var/external = FALSE)
+/decl/flooring/proc/get_flooring_overlay(var/cache_key, var/icon_base, var/icon_dir = 0, var/external = FALSE, var/edge_layer)
+ cache_key = "[cache_key]-[edge_layer]"
if(!global.flooring_cache[cache_key])
var/image/I = image(icon = icon, icon_state = icon_base, dir = icon_dir)
//External overlays will be offset out of this tile
@@ -162,7 +225,7 @@ var/global/list/flooring_cache = list()
I.pixel_x = -world.icon_size
else if (icon_dir & EAST)
I.pixel_x = world.icon_size
- I.layer = decal_layer
+ I.layer = edge_layer
global.flooring_cache[cache_key] = I
return global.flooring_cache[cache_key]
@@ -171,3 +234,84 @@ var/global/list/flooring_cache = list()
/decl/flooring/proc/get_movement_delay(var/travel_dir, var/mob/mover)
return movement_delay
+
+/decl/flooring/proc/get_movable_alpha_mask_state(atom/movable/mover)
+ return
+
+/decl/flooring/proc/handle_item_interaction(turf/floor/floor, mob/user, obj/item/item)
+
+ if(!istype(user) || !istype(item) || !istype(floor) || user.a_intent == I_HURT)
+ return FALSE
+
+ if(!(IS_SCREWDRIVER(item) && (flooring_flags & TURF_REMOVE_SCREWDRIVER)) && floor.try_graffiti(user, item))
+ return TRUE
+
+ if(IS_SHOVEL(item) && (flooring_flags & TURF_REMOVE_SHOVEL))
+ if(!user.do_skilled(remove_timer, SKILL_CONSTRUCTION, floor) || floor.get_topmost_flooring() != src)
+ return TRUE
+ to_chat(user, SPAN_NOTICE("You remove the [get_surface_descriptor()] with \the [item]."))
+ floor.set_flooring(null, place_product = TRUE)
+ playsound(floor, 'sound/items/Deconstruct.ogg', 80, 1)
+ return TRUE
+
+ if(constructed)
+
+ if(IS_CROWBAR(item))
+ if(floor.is_floor_damaged())
+ if(!user.do_skilled(remove_timer, SKILL_CONSTRUCTION, floor, 0.15))
+ return TRUE
+ if(floor.get_topmost_flooring() != src)
+ return
+ to_chat(user, SPAN_NOTICE("You remove the broken [get_surface_descriptor()]."))
+ floor.set_flooring(null)
+ else if(flooring_flags & TURF_IS_FRAGILE)
+ if(!user.do_skilled(remove_timer, SKILL_CONSTRUCTION, floor, 0.15))
+ return TRUE
+ if(floor.get_topmost_flooring() != src)
+ return
+ to_chat(user, SPAN_DANGER("You forcefully pry off the [get_surface_descriptor()], destroying them in the process."))
+ floor.set_flooring(null)
+ else if(flooring_flags & TURF_REMOVE_CROWBAR)
+ if(!user.do_skilled(remove_timer, SKILL_CONSTRUCTION, floor))
+ return TRUE
+ if(floor.get_topmost_flooring() != src)
+ return
+ to_chat(user, SPAN_NOTICE("You lever off the [get_surface_descriptor()]."))
+ floor.set_flooring(null, place_product = TRUE)
+ else
+ return
+ playsound(floor, 'sound/items/Crowbar.ogg', 80, 1)
+ return TRUE
+
+ if(IS_SCREWDRIVER(item) && (flooring_flags & TURF_REMOVE_SCREWDRIVER))
+ if(floor.is_floor_damaged())
+ return FALSE
+ if(!user.do_skilled(remove_timer, SKILL_CONSTRUCTION, floor) || floor.get_topmost_flooring() != src)
+ return TRUE
+ to_chat(user, SPAN_NOTICE("You unscrew and remove the [get_surface_descriptor()]."))
+ floor.set_flooring(null, place_product = TRUE)
+ playsound(floor, 'sound/items/Screwdriver.ogg', 80, 1)
+ return TRUE
+
+ if(IS_WRENCH(item) && (flooring_flags & TURF_REMOVE_WRENCH))
+ if(!user.do_skilled(remove_timer, SKILL_CONSTRUCTION, floor) || floor.get_topmost_flooring() != src)
+ return TRUE
+ to_chat(user, SPAN_NOTICE("You unwrench and remove the [get_surface_descriptor()]."))
+ floor.set_flooring(null, place_product = TRUE)
+ playsound(floor, 'sound/items/Ratchet.ogg', 80, 1)
+ return TRUE
+
+ if(IS_COIL(item))
+ to_chat(user, SPAN_WARNING("You must remove the [get_surface_descriptor()] first."))
+ return TRUE
+
+ return FALSE
+
+/decl/flooring/proc/fire_act(turf/floor/target, datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ return FALSE
+
+/decl/flooring/proc/fluid_act(turf/floor/target, datum/reagents/fluids)
+ return FALSE
+
+/decl/flooring/proc/handle_environment_proc(turf/floor/target)
+ return PROCESS_KILL
diff --git a/code/game/turfs/flooring/_flooring_decals.dm b/code/game/turfs/flooring/_flooring_decals.dm
index 3f3c7052cbc..57b678005ee 100644
--- a/code/game/turfs/flooring/_flooring_decals.dm
+++ b/code/game/turfs/flooring/_flooring_decals.dm
@@ -856,6 +856,19 @@ var/global/list/floor_decals = list()
/obj/effect/floor_decal/spline/fancy/wood/three_quarters
icon_state = "spline_fancy_full"
+/obj/effect/floor_decal/spline/fancy/wood/walnut
+ name = "spline - walnut"
+ color = WOOD_COLOR_CHOCOLATE
+
+/obj/effect/floor_decal/spline/fancy/wood/corner/walnut
+ color = WOOD_COLOR_CHOCOLATE
+
+/obj/effect/floor_decal/spline/fancy/wood/cee/walnut
+ color = WOOD_COLOR_CHOCOLATE
+
+/obj/effect/floor_decal/spline/fancy/wood/three_quarters/walnut
+ color = WOOD_COLOR_CHOCOLATE
+
/obj/effect/floor_decal/industrial
abstract_type = /obj/effect/floor_decal/industrial
diff --git a/code/game/turfs/flooring/flooring_carpet.dm b/code/game/turfs/flooring/flooring_carpet.dm
index 63fa2608383..1158eb56ff1 100644
--- a/code/game/turfs/flooring/flooring_carpet.dm
+++ b/code/game/turfs/flooring/flooring_carpet.dm
@@ -1,53 +1,52 @@
/decl/flooring/carpet
- name = "brown carpet"
- desc = "Comfy and fancy carpeting."
- icon = 'icons/turf/flooring/carpet.dmi'
- icon_base = "brown"
- build_type = /obj/item/stack/tile/carpet
+ name = "brown carpet"
+ desc = "Comfy and fancy carpeting."
+ icon = 'icons/turf/flooring/carpet.dmi'
+ icon_base = "brown"
+ build_type = /obj/item/stack/tile/carpet
damage_temperature = T0C+200
- flags = TURF_REMOVE_CROWBAR | TURF_CAN_BURN
- can_engrave = FALSE
- footstep_type = /decl/footsteps/carpet
- floor_smooth = SMOOTH_NONE
- wall_smooth = SMOOTH_NONE
- space_smooth = SMOOTH_NONE
+ flooring_flags = TURF_REMOVE_CROWBAR | TURF_CAN_BURN
+ can_engrave = FALSE
+ footstep_type = /decl/footsteps/carpet
+ force_material = /decl/material/solid/organic/cloth
+ constructed = TRUE
/decl/flooring/carpet/blue
- name = "blue carpet"
- icon_base = "blue1"
- build_type = /obj/item/stack/tile/carpet/blue
+ name = "blue carpet"
+ icon_base = "blue1"
+ build_type = /obj/item/stack/tile/carpet/blue
/decl/flooring/carpet/blue2
- name = "pale blue carpet"
- icon_base = "blue2"
- build_type = /obj/item/stack/tile/carpet/blue2
+ name = "pale blue carpet"
+ icon_base = "blue2"
+ build_type = /obj/item/stack/tile/carpet/blue2
/decl/flooring/carpet/blue3
- name = "sea blue carpet"
- icon_base = "blue3"
- build_type = /obj/item/stack/tile/carpet/blue3
+ name = "sea blue carpet"
+ icon_base = "blue3"
+ build_type = /obj/item/stack/tile/carpet/blue3
/decl/flooring/carpet/magenta
- name = "magenta carpet"
- icon_base = "purple"
- build_type = /obj/item/stack/tile/carpet/magenta
+ name = "magenta carpet"
+ icon_base = "purple"
+ build_type = /obj/item/stack/tile/carpet/magenta
/decl/flooring/carpet/purple
- name = "purple carpet"
- icon_base = "purple"
- build_type = /obj/item/stack/tile/carpet/purple
+ name = "purple carpet"
+ icon_base = "purple"
+ build_type = /obj/item/stack/tile/carpet/purple
/decl/flooring/carpet/orange
- name = "orange carpet"
- icon_base = "orange"
- build_type = /obj/item/stack/tile/carpet/orange
+ name = "orange carpet"
+ icon_base = "orange"
+ build_type = /obj/item/stack/tile/carpet/orange
/decl/flooring/carpet/green
- name = "green carpet"
- icon_base = "green"
- build_type = /obj/item/stack/tile/carpet/green
+ name = "green carpet"
+ icon_base = "green"
+ build_type = /obj/item/stack/tile/carpet/green
/decl/flooring/carpet/red
- name = "red carpet"
- icon_base = "red"
- build_type = /obj/item/stack/tile/carpet/red
\ No newline at end of file
+ name = "red carpet"
+ icon_base = "red"
+ build_type = /obj/item/stack/tile/carpet/red
\ No newline at end of file
diff --git a/code/game/turfs/flooring/flooring_concrete.dm b/code/game/turfs/flooring/flooring_concrete.dm
new file mode 100644
index 00000000000..8924ba7901f
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_concrete.dm
@@ -0,0 +1,18 @@
+/decl/flooring/concrete
+ name = "concrete"
+ desc = "A flat expanse of artificial stone-like artificial material."
+ icon = 'icons/turf/flooring/concrete.dmi'
+ icon_base = "inset"
+ has_base_range = null
+ force_material = /decl/material/solid/stone/concrete
+ constructed = TRUE
+
+/decl/flooring/concrete/reinforced
+ name = "reinforced concrete"
+ icon_base = "hexacrete"
+ desc = "Stone-like artificial material. It has been reinforced with an unknown compound."
+
+/decl/flooring/concrete/asphalt
+ name = "asphalt"
+ color = COLOR_GRAY40
+ icon_base = "concrete"
diff --git a/code/game/turfs/flooring/flooring_grass.dm b/code/game/turfs/flooring/flooring_grass.dm
new file mode 100644
index 00000000000..6dc48401b69
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_grass.dm
@@ -0,0 +1,47 @@
+/decl/flooring/grass
+ name = "grass"
+ icon = 'icons/turf/flooring/grass.dmi'
+ icon_base = "grass"
+ has_base_range = 3
+ footstep_type = /decl/footsteps/grass
+ icon_edge_layer = FLOOR_EDGE_GRASS
+ color = "#5e7a3b"
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
+ can_engrave = FALSE
+ damage_temperature = T0C+80
+ flooring_flags = TURF_REMOVE_SHOVEL
+ force_material = /decl/material/solid/organic/plantmatter/grass
+ growth_value = 1.2 // Shouldn't really matter since you can't plant on grass, it turns to dirt first.
+ var/harvestable = FALSE
+
+/decl/flooring/grass/fire_act(turf/floor/target, datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(target.get_topmost_flooring() == src && (exposed_temperature > T0C + 200 && prob(5)) || exposed_temperature > T0C + 1000)
+ target.set_flooring(null)
+ return TRUE
+ return ..()
+
+/decl/flooring/grass/wild
+ name = "wild grass"
+ icon = 'icons/turf/flooring/wildgrass.dmi'
+ icon_base = "wildgrass"
+ has_base_range = null
+ icon_edge_layer = FLOOR_EDGE_GRASS_WILD
+ harvestable = TRUE
+
+/decl/flooring/grass/wild/get_movable_alpha_mask_state(atom/movable/mover)
+ . = ..() || "mask_grass"
+
+/decl/flooring/grass/wild/handle_item_interaction(turf/floor/floor, mob/user, obj/item/item)
+ if(IS_KNIFE(item) && harvestable)
+ if(item.do_tool_interaction(TOOL_KNIFE, user, floor, 3 SECONDS, start_message = "harvesting", success_message = "harvesting") && !QDELETED(floor) && floor.get_topmost_flooring() == src)
+ new /obj/item/stack/material/bundle/grass(floor, rand(2,5))
+ floor.set_flooring(/decl/flooring/grass)
+ return TRUE
+ return ..()
+
+/decl/flooring/grass/fake
+ desc = "Do they smoke grass out in space, Bowie? Or do they smoke AstroTurf?"
+ icon = 'icons/turf/flooring/fakegrass.dmi'
+ has_base_range = 3
+ build_type = /obj/item/stack/tile/grass
+ force_material = /decl/material/solid/organic/plastic
diff --git a/code/game/turfs/flooring/flooring_holowater.dm b/code/game/turfs/flooring/flooring_holowater.dm
new file mode 100644
index 00000000000..5d9eab0b44a
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_holowater.dm
@@ -0,0 +1,10 @@
+/decl/flooring/fake_water
+ name = "holowater"
+ desc = "The ripples are a fraction of a second out of sync."
+ color = COLOR_LIQUID_WATER
+ icon = 'icons/turf/flooring/fake_water.dmi'
+ icon_base = "fakewater"
+ has_base_range = null
+ footstep_type = /decl/footsteps/water
+ holographic = TRUE
+ constructed = TRUE
diff --git a/code/game/turfs/flooring/flooring_lava.dm b/code/game/turfs/flooring/flooring_lava.dm
new file mode 100644
index 00000000000..4f3f6d338e9
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_lava.dm
@@ -0,0 +1,27 @@
+
+/decl/flooring/lava
+ name = "lava"
+ icon_base = "lava"
+ icon = 'icons/turf/flooring/lava.dmi'
+ movement_delay = 4
+ footstep_type = /decl/footsteps/lava
+ has_environment_proc = TRUE
+ turf_light_color = LIGHT_COLOR_LAVA
+ turf_light_range = 2
+ turf_light_power = 0.7
+
+/decl/flooring/lava/handle_environment_proc(turf/floor/target)
+ . = PROCESS_KILL
+ if(locate(/obj/structure/catwalk) in target)
+ return
+ var/datum/gas_mixture/environment = target.return_air()
+ var/pressure = environment?.return_pressure()
+ for(var/atom/movable/AM as anything in target.get_contained_external_atoms())
+ if(!AM.is_burnable())
+ continue
+ . = null
+ if(isliving(AM))
+ var/mob/living/L = AM
+ if(L.can_overcome_gravity())
+ continue
+ AM.lava_act(environment, 5000 + environment.temperature, pressure)
diff --git a/code/game/turfs/flooring/flooring_misc.dm b/code/game/turfs/flooring/flooring_misc.dm
index 42ff3be6751..dd718fe4e0d 100644
--- a/code/game/turfs/flooring/flooring_misc.dm
+++ b/code/game/turfs/flooring/flooring_misc.dm
@@ -1,86 +1,85 @@
-/decl/flooring/fake_grass
- name = "grass"
- desc = "Do they smoke grass out in space, Bowie? Or do they smoke AstroTurf?"
- icon = 'icons/turf/flooring/fakegrass.dmi'
- icon_base = "grass"
- has_base_range = 3
- damage_temperature = T0C+80
- flags = TURF_REMOVE_SHOVEL
- build_type = /obj/item/stack/tile/grass
- can_engrave = FALSE
- floor_smooth = SMOOTH_NONE
- wall_smooth = SMOOTH_ALL
- space_smooth = SMOOTH_NONE
- decal_layer = ABOVE_WIRE_LAYER
-
/decl/flooring/linoleum
- name = "linoleum"
- desc = "It's like the 2090's all over again."
- icon = 'icons/turf/flooring/linoleum.dmi'
- icon_base = "lino"
- can_paint = 1
- build_type = /obj/item/stack/tile/linoleum
- flags = TURF_REMOVE_SCREWDRIVER
- footstep_type = /decl/footsteps/tiles
+ name = "linoleum"
+ desc = "It's like the 2090's all over again."
+ icon = 'icons/turf/flooring/linoleum.dmi'
+ icon_base = "lino"
+ can_paint = 1
+ build_type = /obj/item/stack/tile/linoleum
+ flooring_flags = TURF_REMOVE_SCREWDRIVER
+ footstep_type = /decl/footsteps/tiles
+ force_material = /decl/material/solid/organic/plastic
+ constructed = TRUE
/decl/flooring/crystal
- name = "crystal floor"
- icon = 'icons/turf/flooring/crystal.dmi'
- icon_base = "crystal"
- build_type = null
- flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_CROWBAR
- color = "#00ffe1"
+ name = "crystal floor"
+ icon = 'icons/turf/flooring/crystal.dmi'
+ icon_base = "crystal"
+ build_type = null
+ flooring_flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_CROWBAR
+ color = "#00ffe1"
+ force_material = /decl/material/solid/gemstone/crystal
+ constructed = TRUE
/decl/flooring/glass
- name = "glass flooring"
- desc = "A window to the world outside. Or the world beneath your feet, rather."
- icon = 'icons/turf/flooring/glass.dmi'
- icon_base = "glass"
- build_type = /obj/item/stack/material/pane
- build_material = /decl/material/solid/glass
- build_cost = 1
- build_time = 30
+ name = "glass flooring"
+ desc = "A window to the world outside. Or the world beneath your feet, rather."
+ icon = 'icons/turf/flooring/glass.dmi'
+ icon_base = "glass"
+ build_type = /obj/item/stack/material/pane
+ build_material = /decl/material/solid/glass
+ build_cost = 1
+ build_time = 30
damage_temperature = T100C
- flags = TURF_REMOVE_CROWBAR | TURF_ACID_IMMUNE
- can_engrave = FALSE
- color = GLASS_COLOR
- z_flags = ZM_MIMIC_DEFAULTS
- footstep_type = /decl/footsteps/plating
+ flooring_flags = TURF_REMOVE_CROWBAR | TURF_ACID_IMMUNE
+ can_engrave = FALSE
+ color = GLASS_COLOR
+ z_flags = ZM_MIMIC_DEFAULTS
+ footstep_type = /decl/footsteps/plating
+ force_material = /decl/material/solid/glass
+ constructed = TRUE
/decl/flooring/glass/boro
- name = "borosilicate glass flooring"
- build_material = /decl/material/solid/glass/borosilicate
- color = GLASS_COLOR_SILICATE
+ name = "borosilicate glass flooring"
+ build_material = /decl/material/solid/glass/borosilicate
+ color = GLASS_COLOR_SILICATE
damage_temperature = T0C + 4000
+ force_material = /decl/material/solid/glass/borosilicate
/decl/flooring/pool
- name = "pool floor"
- desc = "Sunken flooring designed to hold liquids."
- icon = 'icons/turf/flooring/pool.dmi'
- icon_base = "pool"
- build_type = /obj/item/stack/tile/pool
- flags = TURF_REMOVE_CROWBAR
- footstep_type = /decl/footsteps/tiles
- floor_smooth = SMOOTH_NONE
- wall_smooth = SMOOTH_NONE
- space_smooth = SMOOTH_NONE
- height = -(FLUID_OVER_MOB_HEAD) - 50
- render_trenches = FALSE
-
-/decl/flooring/pool/deep
- height = -FLUID_DEEP - 50
+ name = "pool floor"
+ desc = "Sunken flooring designed to hold liquids."
+ icon = 'icons/turf/flooring/pool.dmi'
+ icon_base = "pool"
+ build_type = /obj/item/stack/tile/pool
+ flooring_flags = TURF_REMOVE_CROWBAR
+ footstep_type = /decl/footsteps/tiles
+ render_trenches = FALSE
+ force_material = /decl/material/solid/stone/ceramic
+ constructed = TRUE
/decl/flooring/woven
- name = "woven floor"
- desc = "A rustic woven mat."
- icon = 'icons/turf/flooring/woven.dmi'
- icon_base = "woven"
+ name = "woven floor"
+ desc = "A rustic woven mat."
+ icon = 'icons/turf/flooring/woven.dmi'
+ icon_base = "woven"
+ damage_temperature = T0C+80
+ flooring_flags = TURF_REMOVE_CROWBAR
+ build_type = /obj/item/stack/tile/woven
+ can_engrave = FALSE
+ color = COLOR_BEIGE
+ force_material = /decl/material/solid/organic/plantmatter/grass/dry
+ constructed = TRUE
+
+/decl/flooring/straw
+ name = "straw floor"
+ desc = "A thick layer of straw, suitable for livestock."
+ icon = 'icons/turf/flooring/wildgrass.dmi' // temporary, replace with better icon at some point
+ icon_base = "wildgrass"
+ has_base_range = null
+ icon_edge_layer = FLOOR_EDGE_GRASS_WILD
damage_temperature = T0C+80
- flags = TURF_REMOVE_CROWBAR
- build_type = /obj/item/stack/tile/woven
- can_engrave = FALSE
- floor_smooth = SMOOTH_NONE
- wall_smooth = SMOOTH_ALL
- space_smooth = SMOOTH_NONE
- decal_layer = ABOVE_WIRE_LAYER
- color = COLOR_BEIGE
+ flooring_flags = TURF_REMOVE_CROWBAR
+ can_engrave = FALSE
+ color = COLOR_WHEAT
+ force_material = /decl/material/solid/organic/plantmatter/grass/dry
+ constructed = TRUE
diff --git a/code/game/turfs/flooring/flooring_mud.dm b/code/game/turfs/flooring/flooring_mud.dm
new file mode 100644
index 00000000000..6dbe53a90f2
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_mud.dm
@@ -0,0 +1,61 @@
+/decl/flooring/mud
+ name = "mud"
+ desc = "Thick, waterlogged mud."
+ icon = 'icons/turf/flooring/mud.dmi'
+ icon_base = "mud"
+ icon_edge_layer = FLOOR_EDGE_MUD
+ footstep_type = /decl/footsteps/mud
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
+ force_material = /decl/material/solid/soil
+ growth_value = 1.1
+
+/decl/flooring/mud/fire_act(turf/floor/target, datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(!target.reagents?.total_volume)
+ if(target.get_topmost_flooring() == src)
+ target.set_flooring(/decl/flooring/dry_mud)
+ else if(target.get_base_flooring() == src)
+ target.set_base_flooring(/decl/flooring/dry_mud)
+ return
+ return ..()
+
+/decl/flooring/dry_mud
+ name = "dry mud"
+ desc = "Should have stayed hydrated."
+ icon = 'icons/turf/flooring/seafloor.dmi'
+ icon_base = "seafloor"
+ icon_edge_layer = FLOOR_EDGE_MUD
+ footstep_type = /decl/footsteps/mud
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
+ color = "#ae9e66"
+ dirt_color = "#ae9e66"
+ force_material = /decl/material/solid/soil
+
+/decl/flooring/dry_mud/fluid_act(turf/floor/target, datum/reagents/fluids)
+ if(target.get_topmost_flooring() == src)
+ target.set_flooring(/decl/flooring/mud)
+ . = TRUE
+ if(target.get_base_flooring() == src)
+ target.set_base_flooring(/decl/flooring/mud)
+ . = TRUE
+ return . || ..()
+
+/decl/flooring/dirt
+ name = "dirt"
+ desc = "A flat expanse of dry, cracked earth."
+ icon = 'icons/turf/flooring/dirt.dmi'
+ icon_base = "dirt"
+ icon_edge_layer = FLOOR_EDGE_DIRT
+ color = "#41311b"
+ footstep_type = /decl/footsteps/asteroid
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
+ force_material = /decl/material/solid/soil
+ growth_value = 1
+
+/decl/flooring/dirt/fluid_act(turf/floor/target, datum/reagents/fluids)
+ if(target.get_topmost_flooring() == src)
+ target.set_flooring(/decl/flooring/mud)
+ . = TRUE
+ if(target.get_base_flooring() == src)
+ target.set_base_flooring(/decl/flooring/mud)
+ . = TRUE
+ return . || ..()
diff --git a/code/game/turfs/flooring/flooring_natural.dm b/code/game/turfs/flooring/flooring_natural.dm
new file mode 100644
index 00000000000..6d3876ab316
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_natural.dm
@@ -0,0 +1,66 @@
+/decl/flooring/seafloor
+ name = "sea floor"
+ desc = "A thick layer of silt and debris from above."
+ icon = 'icons/turf/flooring/seafloor.dmi'
+ icon_base = "seafloor"
+ icon_edge_layer = FLOOR_EDGE_SEAFLOOR
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
+ force_material = /decl/material/solid/sand
+
+/decl/flooring/shrouded
+ name = "packed sand"
+ desc = "Sand that has been packed in to solid earth."
+ icon = 'icons/turf/flooring/shrouded.dmi'
+ icon_base = "shrouded"
+ dirt_color = "#3e3960"
+ has_base_range = 8
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
+ force_material = /decl/material/solid/sand
+
+/decl/flooring/meat
+ name = "fleshy ground"
+ desc = "It's disgustingly soft to the touch. And warm. Too warm."
+ icon = 'icons/turf/flooring/flesh.dmi'
+ icon_base = "meat"
+ color = "#c40031"
+ has_base_range = null
+ footstep_type = /decl/footsteps/mud
+ force_material = /decl/material/solid/organic/meat
+
+/decl/flooring/barren
+ name = "ground"
+ desc = "Bare, barren sand."
+ icon = 'icons/turf/flooring/barren.dmi'
+ icon_base = "barren"
+ color = COLOR_WHITE
+ footstep_type = /decl/footsteps/asteroid
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH
+ icon_edge_layer = FLOOR_EDGE_BARREN
+ force_material = /decl/material/solid/soil
+ growth_value = 0.1
+
+/decl/flooring/clay
+ name = "clay"
+ desc = "Thick, claggy clay."
+ icon = 'icons/turf/flooring/clay.dmi'
+ icon_base = "clay"
+ icon_edge_layer = FLOOR_EDGE_CLAY
+ footstep_type = /decl/footsteps/mud
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
+ force_material = /decl/material/solid/clay
+ growth_value = 1.2
+
+/decl/flooring/ice
+ name = "ice"
+ icon = 'icons/turf/flooring/ice.dmi'
+ icon_base = "ice"
+ footstep_type = /decl/footsteps/plating
+ color = COLOR_LIQUID_WATER
+ force_material = /decl/material/solid/ice
+
+/decl/flooring/ice/update_turf_icon(turf/floor/target)
+ . = ..()
+ if(istype(target))
+ var/image/I = image(icon, "[icon_base]_shine")
+ I.appearance_flags |= RESET_COLOR
+ target.add_overlay(I)
diff --git a/code/game/turfs/flooring/flooring_path.dm b/code/game/turfs/flooring/flooring_path.dm
index 1446f7f91de..1ceddda2e1f 100644
--- a/code/game/turfs/flooring/flooring_path.dm
+++ b/code/game/turfs/flooring/flooring_path.dm
@@ -1,26 +1,38 @@
/decl/flooring/path
- abstract_type = /decl/flooring/path
- icon = 'icons/turf/flooring/path.dmi'
- flags = TURF_REMOVE_CROWBAR
- build_type = null
- can_engrave = TRUE
- floor_smooth = SMOOTH_NONE
- wall_smooth = SMOOTH_ALL
- space_smooth = SMOOTH_NONE
- decal_layer = ABOVE_WIRE_LAYER
+ abstract_type = /decl/flooring/path
+ icon = 'icons/turf/flooring/path.dmi'
+ flooring_flags = TURF_REMOVE_CROWBAR
+ build_type = null
+ can_engrave = TRUE
+ neighbour_type = /decl/flooring/path
+ color = null
+ constructed = TRUE
+ // If null, this is just skipped.
+ var/paving_adjective = "cobbled"
+ var/paver_adjective = "loose"
+ // This one should never be null.
+ var/paver_noun = "stones"
+
+/decl/flooring/path/update_turf_strings(turf/floor/target)
+ var/decl/material/material = target?.get_material()
+ ASSERT(material?.adjective_name)
+ ASSERT(paver_noun)
+ target.SetName("[material.adjective_name] [name]")
+ target.desc = "[jointext_no_nulls(list("A", paving_adjective, "path made of", paver_adjective, material.adjective_name, paver_noun), " ")]."
/decl/flooring/path/cobblestone
- name = "cobblestone path"
- desc = "A rustic cobblestone path."
- icon_base = "cobble"
- flags = TURF_REMOVE_CROWBAR
+ name = "cobblestone path"
+ desc = "A rustic cobblestone path."
+ icon_base = "cobble"
+ icon_edge_layer = FLOOR_EDGE_PATH
+ flooring_flags = TURF_REMOVE_CROWBAR
/decl/flooring/path/running_bond
- name = "stone path"
- desc = "A rustic stone path, laid out in a running bond pattern."
- icon_base = "runningbond"
+ name = "stone path"
+ desc = "A rustic stone path, laid out in a running bond pattern."
+ icon_base = "runningbond"
/decl/flooring/path/herringbone
- name = "stone path"
- desc = "A rustic stone path, laid out in a herringbone pattern."
- icon_base = "herringbone"
+ name = "stone path"
+ desc = "A rustic stone path, laid out in a herringbone pattern."
+ icon_base = "herringbone"
diff --git a/code/game/turfs/flooring/flooring_plating.dm b/code/game/turfs/flooring/flooring_plating.dm
new file mode 100644
index 00000000000..f708ff94f77
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_plating.dm
@@ -0,0 +1,8 @@
+/decl/flooring/plating
+ name = "plating"
+ desc = "A layer of rough, undecorated steel plates."
+ icon = 'icons/turf/flooring/plating.dmi'
+ icon_base = "plating"
+ floor_layer = PLATING_LAYER
+ force_material = /decl/material/solid/metal/steel
+ constructed = TRUE
diff --git a/code/game/turfs/flooring/flooring_reinforced.dm b/code/game/turfs/flooring/flooring_reinforced.dm
index 128c23dc438..80fce0d663c 100644
--- a/code/game/turfs/flooring/flooring_reinforced.dm
+++ b/code/game/turfs/flooring/flooring_reinforced.dm
@@ -1,58 +1,60 @@
/decl/flooring/reinforced
- name = "reinforced floor"
- desc = "Heavily reinforced with a latticework on top of regular plating."
- icon = 'icons/turf/flooring/tiles.dmi'
- icon_base = "reinforced"
- flags = TURF_REMOVE_WRENCH | TURF_ACID_IMMUNE
- build_type = /obj/item/stack/material/sheet
+ name = "reinforced floor"
+ desc = "Heavily reinforced with a latticework on top of regular plating."
+ icon = 'icons/turf/flooring/tiles.dmi'
+ icon_base = "reinforced"
+ flooring_flags = TURF_REMOVE_WRENCH | TURF_ACID_IMMUNE
+ build_type = /obj/item/stack/material/sheet
build_material = /decl/material/solid/metal/steel
- build_cost = 1
- build_time = 30
- can_paint = 1
- footstep_type = /decl/footsteps/plating
+ build_cost = 1
+ build_time = 30
+ can_paint = 1
+ footstep_type = /decl/footsteps/plating
+ force_material = /decl/material/solid/metal/steel
+ constructed = TRUE
/decl/flooring/reinforced/circuit
- name = "processing strata"
- icon = 'icons/turf/flooring/circuit.dmi'
- icon_base = "bcircuit"
- build_type = null
- flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_WRENCH
- can_paint = 1
- can_engrave = FALSE
+ name = "processing strata"
+ icon = 'icons/turf/flooring/circuit.dmi'
+ icon_base = "bcircuit"
+ build_type = null
+ flooring_flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_WRENCH
+ can_paint = 1
+ can_engrave = FALSE
/decl/flooring/reinforced/circuit/green
- icon_base = "gcircuit"
+ icon_base = "gcircuit"
/decl/flooring/reinforced/circuit/red
- icon_base = "rcircuit"
- flags = TURF_ACID_IMMUNE
- can_paint = 0
+ icon_base = "rcircuit"
+ flooring_flags = TURF_ACID_IMMUNE
+ can_paint = 0
/decl/flooring/reinforced/shuttle
- name = "floor"
- icon = 'icons/turf/flooring/shuttle.dmi'
- build_type = null
- flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_CROWBAR
- can_paint = 1
- can_engrave = FALSE
+ name = "floor"
+ icon = 'icons/turf/flooring/shuttle.dmi'
+ build_type = null
+ flooring_flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_CROWBAR
+ can_paint = 1
+ can_engrave = FALSE
/decl/flooring/reinforced/shuttle/blue
- icon_base = "floor"
+ icon_base = "floor"
/decl/flooring/reinforced/shuttle/yellow
- icon_base = "floor2"
+ icon_base = "floor2"
/decl/flooring/reinforced/shuttle/white
- icon_base = "floor3"
+ icon_base = "floor3"
/decl/flooring/reinforced/shuttle/red
- icon_base = "floor4"
+ icon_base = "floor4"
/decl/flooring/reinforced/shuttle/purple
- icon_base = "floor5"
+ icon_base = "floor5"
/decl/flooring/reinforced/shuttle/darkred
- icon_base = "floor6"
+ icon_base = "floor6"
/decl/flooring/reinforced/shuttle/black
- icon_base = "floor7"
+ icon_base = "floor7"
diff --git a/code/game/turfs/flooring/flooring_rock.dm b/code/game/turfs/flooring/flooring_rock.dm
new file mode 100644
index 00000000000..88c97f71a37
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_rock.dm
@@ -0,0 +1,14 @@
+/decl/flooring/rock
+ name = "rock floor"
+ desc = "An expanse of bare rock."
+ icon = 'icons/turf/flooring/rock.dmi'
+ icon_base = "rock"
+ has_base_range = null
+ color = null
+ icon_edge_layer = FLOOR_EDGE_VOLCANIC
+
+/decl/flooring/rock/update_turf_strings(turf/floor/target)
+ var/decl/material/material = target?.get_material()
+ ASSERT(material?.adjective_name)
+ target.SetName("[material.adjective_name] [name]")
+ target.desc = "An expanse of bare [material.solid_name]."
diff --git a/code/game/turfs/flooring/flooring_sand.dm b/code/game/turfs/flooring/flooring_sand.dm
new file mode 100644
index 00000000000..d09f5ca8b0c
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_sand.dm
@@ -0,0 +1,56 @@
+/decl/flooring/sand
+ name = "sand"
+ desc = "A fine layer of silica. It's coarse and gets everywhere."
+ footstep_type = /decl/footsteps/sand
+ icon = 'icons/turf/flooring/sand.dmi'
+ icon_base = "sand"
+ icon_edge_layer = FLOOR_EDGE_SAND
+ has_base_range = 4
+ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
+ force_material = /decl/material/solid/sand
+
+/decl/flooring/sand/fire_act(turf/floor/target, datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if((exposed_temperature > T0C + 1700 && prob(5)) || exposed_temperature > T0C + 3000)
+ if(target.get_topmost_flooring() == src)
+ target.set_flooring(/decl/flooring/melted_sand)
+ . = TRUE
+ if(target.get_base_flooring() == src)
+ target.set_base_flooring(/decl/flooring/melted_sand)
+ . = TRUE
+ return . || ..()
+
+/decl/flooring/sand/chlorine
+ name = "chlorinated sand"
+ desc = "Sand that has been heavily contaminated by chlorine."
+ icon = 'icons/turf/flooring/chlorine_sand.dmi'
+ icon_base = "chlorine"
+ has_base_range = 11
+ icon_edge_layer = FLOOR_EDGE_CHLORINE_SAND
+ color = "#d2e0b7"
+ dirt_color = "#d2e0b7"
+ footstep_type = /decl/footsteps/sand
+
+/decl/flooring/sand/chlorine/marsh
+ name = "chlorine marsh"
+ desc = "A pool of noxious liquid chlorine. It's full of silt and plant matter."
+
+/decl/flooring/sand/fake
+ name = "holosand"
+ desc = "Uncomfortably coarse and gritty for a hologram."
+ holographic = TRUE
+
+/decl/flooring/fake_space
+ name = "\proper space"
+ desc = "The final frontier."
+ icon = 'icons/turf/flooring/fake_space.dmi'
+ icon_base = "space"
+ has_base_range = 25
+ holographic = TRUE
+
+/decl/flooring/melted_sand
+ name = "molten silica"
+ desc = "A glassed patch of sand."
+ icon = 'icons/turf/flooring/sand.dmi'
+ icon_base = "glass"
+ has_base_range = null
+ force_material = /decl/material/solid/glass
diff --git a/code/game/turfs/flooring/flooring_snow.dm b/code/game/turfs/flooring/flooring_snow.dm
new file mode 100644
index 00000000000..34de06ab67b
--- /dev/null
+++ b/code/game/turfs/flooring/flooring_snow.dm
@@ -0,0 +1,41 @@
+/decl/flooring/snow
+ name = "snow"
+ desc = "Let it snow, let it snow, let it snow..."
+ icon = 'icons/turf/flooring/snow.dmi'
+ icon_base = "snow"
+ icon_edge_layer = FLOOR_EDGE_SNOW
+ footstep_type = /decl/footsteps/snow
+ has_base_range = 13
+ force_material = /decl/material/solid/ice/snow
+
+/decl/flooring/snow/get_movement_delay(var/travel_dir, var/mob/mover)
+ . = ..()
+ if(mover)
+ var/obj/item/clothing/shoes/shoes = mover.get_equipped_item(slot_shoes_str)
+ if(shoes)
+ . += shoes.snow_slowdown_mod
+ var/decl/species/my_species = mover.get_species()
+ if(my_species)
+ . += my_species.snow_slowdown_mod
+ . = max(., 0)
+
+/decl/flooring/snow/fire_act(turf/floor/target, datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(!target.reagents?.total_volume)
+ if(target.get_topmost_flooring() == src)
+ target.set_flooring(/decl/flooring/permafrost)
+ else if(target.get_base_flooring() == src)
+ target.set_base_flooring(/decl/flooring/permafrost)
+ return
+ return ..()
+
+/decl/flooring/permafrost
+ name = "permafrost"
+ desc = "Let it snow, let it snow, let it snow..."
+ icon = 'icons/turf/flooring/snow.dmi'
+ icon_base = "permafrost"
+ force_material = /decl/material/solid/ice
+
+/decl/flooring/snow/fake
+ name = "holosnow"
+ desc = "Not quite the same as snow on an entertainment terminal, but close."
+ holographic = TRUE
diff --git a/code/game/turfs/flooring/flooring_tiled.dm b/code/game/turfs/flooring/flooring_tiled.dm
index 1a88867eb44..686f2d75d1d 100644
--- a/code/game/turfs/flooring/flooring_tiled.dm
+++ b/code/game/turfs/flooring/flooring_tiled.dm
@@ -1,91 +1,96 @@
/decl/flooring/tiling
- name = "floor"
- desc = "A solid, heavy set of flooring plates."
- icon = 'icons/turf/flooring/tiles.dmi'
- icon_base = "tiled"
- color = COLOR_DARK_GUNMETAL
+ name = "floor"
+ desc = "A solid, heavy set of flooring plates."
+ icon = 'icons/turf/flooring/tiles.dmi'
+ icon_base = "tiled"
+ descriptor = "tiles"
+ color = COLOR_DARK_GUNMETAL
damage_temperature = T0C+1400
- flags = TURF_REMOVE_CROWBAR | TURF_CAN_BREAK | TURF_CAN_BURN
- build_type = /obj/item/stack/tile/floor
- can_paint = 1
- footstep_type = /decl/footsteps/tiles
+ flooring_flags = TURF_REMOVE_CROWBAR | TURF_CAN_BREAK | TURF_CAN_BURN
+ build_type = /obj/item/stack/tile/floor
+ can_paint = 1
+ footstep_type = /decl/footsteps/tiles
+ force_material = /decl/material/solid/metal/steel
+ wall_smooth = SMOOTH_ALL
+ space_smooth = SMOOTH_ALL
+ constructed = TRUE
/decl/flooring/tiling/mono
- icon_base = "monotile"
- build_type = /obj/item/stack/tile/mono
+ icon_base = "monotile"
+ build_type = /obj/item/stack/tile/mono
/decl/flooring/tiling/mono/dark
- color = COLOR_DARK_GRAY
- build_type = /obj/item/stack/tile/mono/dark
+ color = COLOR_DARK_GRAY
+ build_type = /obj/item/stack/tile/mono/dark
/decl/flooring/tiling/mono/white
- icon_base = "monotile_light"
- color = COLOR_OFF_WHITE
- build_type = /obj/item/stack/tile/mono/white
+ icon_base = "monotile_light"
+ color = COLOR_OFF_WHITE
+ build_type = /obj/item/stack/tile/mono/white
/decl/flooring/tiling/white
- icon_base = "tiled_light"
- desc = "How sterile."
- color = COLOR_OFF_WHITE
- build_type = /obj/item/stack/tile/floor_white
+ icon_base = "tiled_light"
+ desc = "A layer of sterile white tiles."
+ color = COLOR_OFF_WHITE
+ build_type = /obj/item/stack/tile/floor_white
/decl/flooring/tiling/dark
- desc = "How ominous."
- color = COLOR_DARK_GRAY
- build_type = /obj/item/stack/tile/floor_dark
+ desc = "A layer of ominously dark tiles."
+ color = COLOR_DARK_GRAY
+ build_type = /obj/item/stack/tile/floor_dark
/decl/flooring/tiling/dark/mono
- icon_base = "monotile"
- build_type = null
+ icon_base = "monotile"
+ build_type = null
/decl/flooring/tiling/freezer
- desc = "Don't slip."
- icon_base = "freezer"
- color = null
- flags = TURF_REMOVE_CROWBAR
- build_type = /obj/item/stack/tile/floor_freezer
+ desc = "A section of non-slip tiles suitable for a cool room or freezer."
+ icon_base = "freezer"
+ color = null
+ flooring_flags = TURF_REMOVE_CROWBAR
+ build_type = /obj/item/stack/tile/floor_freezer
/decl/flooring/tiling/tech
- icon = 'icons/turf/flooring/techfloor.dmi'
- icon_base = "techfloor_gray"
- build_type = /obj/item/stack/tile/techgrey
- color = null
+ icon = 'icons/turf/flooring/techfloor.dmi'
+ icon_base = "techfloor_gray"
+ build_type = /obj/item/stack/tile/techgrey
+ color = null
/decl/flooring/tiling/tech/grid
- icon_base = "techfloor_grid"
- build_type = /obj/item/stack/tile/techgrid
+ icon_base = "techfloor_grid"
+ build_type = /obj/item/stack/tile/techgrid
/decl/flooring/tiling/new_tile
- icon_base = "tile_full"
- color = null
- build_type = null
+ icon_base = "tile_full"
+ color = null
+ build_type = null
/decl/flooring/tiling/new_tile/cargo_one
- icon_base = "cargo_one_full"
- build_type = null
+ icon_base = "cargo_one_full"
+ build_type = null
/decl/flooring/tiling/new_tile/kafel
- icon_base = "kafel_full"
- build_type = null
+ icon_base = "kafel_full"
+ build_type = null
/decl/flooring/tiling/stone
- icon_base = "stone"
- build_type = /obj/item/stack/tile/stone
+ icon_base = "stone"
+ build_type = /obj/item/stack/tile/stone
/decl/flooring/tiling/new_tile/techmaint
- icon_base = "techmaint"
- build_type = /obj/item/stack/tile/techmaint
+ icon_base = "techmaint"
+ build_type = /obj/item/stack/tile/techmaint
/decl/flooring/tiling/new_tile/monofloor
- icon_base = "monofloor"
- color = COLOR_GUNMETAL
+ icon_base = "monofloor"
+ color = COLOR_GUNMETAL
/decl/flooring/tiling/new_tile/steel_grid
- icon_base = "grid"
- color = COLOR_GUNMETAL
- build_type = /obj/item/stack/tile/grid
+ icon_base = "grid"
+ color = COLOR_GUNMETAL
+ build_type = /obj/item/stack/tile/grid
/decl/flooring/tiling/new_tile/steel_ridged
- icon_base = "ridged"
- color = COLOR_GUNMETAL
- build_type = /obj/item/stack/tile/ridge
+ icon_base = "ridged"
+ color = COLOR_GUNMETAL
+ build_type = /obj/item/stack/tile/ridge
diff --git a/code/game/turfs/flooring/flooring_wood.dm b/code/game/turfs/flooring/flooring_wood.dm
index 833645aec76..132cadb1b46 100644
--- a/code/game/turfs/flooring/flooring_wood.dm
+++ b/code/game/turfs/flooring/flooring_wood.dm
@@ -1,35 +1,43 @@
/decl/flooring/wood
- name = "wooden floor"
- desc = "Polished wood planks."
- icon = 'icons/turf/flooring/wood.dmi'
- icon_base = "wood"
+ name = "wooden floor"
+ desc = "Polished wood planks."
+ icon = 'icons/turf/flooring/wood.dmi'
+ icon_base = "wood"
damage_temperature = T0C+200
- descriptor = "planks"
- build_type = /obj/item/stack/tile/wood
- flags = TURF_CAN_BREAK | TURF_IS_FRAGILE | TURF_REMOVE_SCREWDRIVER
- footstep_type = /decl/footsteps/wood
- color = /decl/material/solid/organic/wood::color
+ descriptor = "planks"
+ build_type = /obj/item/stack/tile/wood
+ flooring_flags = TURF_CAN_BREAK | TURF_IS_FRAGILE | TURF_REMOVE_SCREWDRIVER
+ footstep_type = /decl/footsteps/wood
+ color = /decl/material/solid/organic/wood::color
+ force_material = /decl/material/solid/organic/wood
+ constructed = TRUE
/decl/flooring/wood/mahogany
- color = /decl/material/solid/organic/wood/mahogany::color
- build_type = /obj/item/stack/tile/mahogany
+ color = /decl/material/solid/organic/wood/mahogany::color
+ build_type = /obj/item/stack/tile/mahogany
+ force_material = /decl/material/solid/organic/wood/mahogany
/decl/flooring/wood/maple
- color = /decl/material/solid/organic/wood/maple::color
- build_type = /obj/item/stack/tile/maple
+ color = /decl/material/solid/organic/wood/maple::color
+ build_type = /obj/item/stack/tile/maple
+ force_material = /decl/material/solid/organic/wood/maple
/decl/flooring/wood/ebony
- color = /decl/material/solid/organic/wood/ebony::color
- build_type = /obj/item/stack/tile/ebony
+ color = /decl/material/solid/organic/wood/ebony::color
+ build_type = /obj/item/stack/tile/ebony
+ force_material = /decl/material/solid/organic/wood/ebony
/decl/flooring/wood/walnut
- color = /decl/material/solid/organic/wood/walnut::color
- build_type = /obj/item/stack/tile/walnut
+ color = /decl/material/solid/organic/wood/walnut::color
+ build_type = /obj/item/stack/tile/walnut
+ force_material = /decl/material/solid/organic/wood/walnut
/decl/flooring/wood/bamboo
- color = /decl/material/solid/organic/wood/bamboo::color
- build_type = /obj/item/stack/tile/bamboo
+ color = /decl/material/solid/organic/wood/bamboo::color
+ build_type = /obj/item/stack/tile/bamboo
+ force_material = /decl/material/solid/organic/wood/bamboo
/decl/flooring/wood/yew
- color = /decl/material/solid/organic/wood/yew::color
- build_type = /obj/item/stack/tile/yew
+ color = /decl/material/solid/organic/wood/yew::color
+ build_type = /obj/item/stack/tile/yew
+ force_material = /decl/material/solid/organic/wood/yew
diff --git a/code/game/turfs/floors/_floor.dm b/code/game/turfs/floors/_floor.dm
index 193f11c0124..0dd9e8e4365 100644
--- a/code/game/turfs/floors/_floor.dm
+++ b/code/game/turfs/floors/_floor.dm
@@ -12,6 +12,8 @@
zone_membership_candidate = TRUE
open_turf_type = /turf/open/airless
+ // Reagent to use to fill the turf.
+ var/fill_reagent_type
var/can_engrave = TRUE
// Damage to flooring.
@@ -19,115 +21,184 @@
var/_floor_broken
var/_floor_burned
- // Plating data.
- var/base_name = "plating"
- var/base_desc = "The naked hull."
- var/base_icon = 'icons/turf/flooring/plating.dmi'
- var/base_icon_state = "plating"
- var/base_color = COLOR_WHITE
-
// Flooring data.
- var/flooring_override
- var/initial_flooring
- var/decl/flooring/flooring
+ var/floor_icon_state_override
-// Defining this here as a dummy mapping shorthand so mappers can search for 'plating'.
-/turf/floor/plating
+ // TODO:
+ VAR_PROTECTED/decl/flooring/_base_flooring = /decl/flooring/plating
+ VAR_PROTECTED/decl/flooring/_flooring
-/turf/floor/can_climb_from_below(var/mob/climber)
- return TRUE
+ var/const/TRENCH_DEPTH_PER_ACTION = 100
-/turf/floor/is_plating()
- return !flooring
+/turf/floor/Initialize(var/ml, var/floortype)
-/turf/floor/get_base_movement_delay(var/travel_dir, var/mob/mover)
- return flooring?.get_movement_delay(travel_dir, mover) || ..()
+ if(_base_flooring)
+ set_base_flooring(_base_flooring, skip_update = TRUE)
-/turf/floor/protects_atom(var/atom/A)
- return (A.level <= LEVEL_BELOW_PLATING && !is_plating()) || ..()
-
-/turf/floor/Initialize(var/ml, var/floortype)
. = ..(ml)
- if(!floortype && initial_flooring)
- floortype = initial_flooring
+
+ set_turf_materials(floor_material, skip_update = TRUE)
+
+ if(!floortype && ispath(_flooring))
+ floortype = _flooring
if(floortype)
+ set_flooring(GET_DECL(floortype), skip_update = TRUE)
+
+ if(fill_reagent_type && get_physical_height() < 0)
+ add_to_reagents(fill_reagent_type, abs(height))
+
+ if(floor_material || get_topmost_flooring())
if(ml)
- set_flooring(GET_DECL(floortype), skip_update = TRUE)
queue_icon_update()
else
- set_flooring(GET_DECL(floortype))
+ for(var/direction in global.alldirs)
+ var/turf/target_turf = get_step_resolving_mimic(src, direction)
+ if(istype(target_turf))
+ if(TICK_CHECK) // not CHECK_TICK -- only queue if the server is overloaded
+ target_turf.queue_icon_update()
+ else
+ target_turf.update_icon()
+ update_icon()
+
+/turf/floor/ChangeTurf(turf/N, tell_universe, force_lighting_update, keep_air, update_open_turfs_above, keep_height)
+ if(is_processing)
+ STOP_PROCESSING(SSobj, src)
+ . = ..()
+
+/turf/floor/Destroy()
+ set_flooring(null)
+ if(is_processing)
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/turf/floor/can_climb_from_below(var/mob/climber)
+ return TRUE
+
+/turf/floor/proc/has_flooring()
+ return istype(_flooring)
+
+/turf/floor/is_plating()
+ if(density)
+ return FALSE
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return (!istype(flooring) || flooring == get_base_flooring())
+
+/turf/floor/get_base_movement_delay(var/travel_dir, var/mob/mover)
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return istype(flooring) ? flooring.get_movement_delay(travel_dir, mover) : ..()
-/turf/floor/proc/set_flooring(var/decl/flooring/newflooring, skip_update)
+/turf/floor/protects_atom(var/atom/A)
+ return (A.level <= LEVEL_BELOW_PLATING && !is_plating()) || ..()
- if(flooring == newflooring)
+/turf/floor/on_reagent_change()
+ . = ..()
+ var/my_height = get_physical_height()
+ if(!QDELETED(src) && fill_reagent_type && my_height < 0 && !QDELETED(reagents) && reagents.total_volume < abs(my_height))
+ add_to_reagents(fill_reagent_type, abs(my_height) - reagents.total_volume)
+
+/turf/floor/proc/set_base_flooring(new_base_flooring, skip_update)
+ if(ispath(new_base_flooring, /decl/flooring))
+ new_base_flooring = GET_DECL(new_base_flooring)
+ else if(!istype(new_base_flooring, /decl/flooring))
+ new_base_flooring = null
+ if(_base_flooring == new_base_flooring)
return
+ _base_flooring = new_base_flooring
+ if(!_base_flooring) // We can never have a null base flooring.
+ _base_flooring = GET_DECL(initial(_base_flooring)) || GET_DECL(/decl/flooring/plating)
+ update_from_flooring(skip_update)
- if(flooring)
- make_plating(defer_icon_update = TRUE)
- flooring = null
+/turf/floor/proc/get_base_flooring()
+ RETURN_TYPE(/decl/flooring)
+ return istype(_base_flooring) ? _base_flooring : null
- flooring = newflooring
+/turf/floor/proc/get_topmost_flooring()
+ RETURN_TYPE(/decl/flooring)
+ return istype(_flooring) ? _flooring : get_base_flooring()
- var/check_z_flags
- if(flooring)
- check_z_flags = flooring.z_flags
- else
- check_z_flags = initial(z_flags)
+/turf/floor/proc/set_flooring(var/decl/flooring/newflooring, skip_update, place_product)
- if(check_z_flags & ZM_MIMIC_BELOW)
- enable_zmimic(check_z_flags)
- else
- disable_zmimic()
+ if(ispath(newflooring, /decl/flooring))
+ newflooring = GET_DECL(newflooring)
+ else if(!istype(newflooring, /decl/flooring))
+ newflooring = null
- if(flooring)
- layer = TURF_LAYER
+ if(_flooring == newflooring)
+ return FALSE
- levelupdate()
+ if(istype(_flooring))
- if(!skip_update)
- for(var/turf/T as anything in RANGE_TURFS(src, 1))
- T.update_icon()
-
-//This proc will set floor_type to null and the update_icon() proc will then change the icon_state of the turf
-//This proc auto corrects the grass tiles' siding.
-/turf/floor/proc/make_plating(var/place_product, var/defer_icon_update)
-
- LAZYCLEARLIST(decals)
- for(var/obj/effect/decal/writing/W in src)
- qdel(W)
-
- SetName(base_name)
- desc = base_desc
- icon = base_icon
- icon_state = base_icon_state
- color = base_color
- layer = PLATING_LAYER
+ LAZYCLEARLIST(decals)
+ for(var/obj/effect/decal/writing/W in src)
+ qdel(W)
- if(flooring)
- flooring.on_remove()
- if(flooring.build_type && place_product)
+ _flooring.on_remove()
+ if(_flooring.build_type && place_product)
// If build type uses material stack, check for it
// Because material stack uses different arguments
// And we need to use build material to spawn stack
- if(ispath(flooring.build_type, /obj/item/stack/material))
- var/decl/material/M = GET_DECL(flooring.build_material)
+ if(ispath(_flooring.build_type, /obj/item/stack/material))
+ var/decl/material/M = GET_DECL(_flooring.build_material)
if(!M)
- CRASH("[src] at ([x], [y], [z]) cannot create stack because it has a bad build_material path: '[flooring.build_material]'")
- M.create_object(src, flooring.build_cost, flooring.build_type)
+ CRASH("[src] at ([x], [y], [z]) cannot create stack because it has a bad build_material path: '[_flooring.build_material]'")
+ M.create_object(src, _flooring.build_cost, _flooring.build_type)
else
- new flooring.build_type(src)
- flooring = null
+ new _flooring.build_type(src)
+
+ if(_flooring.has_environment_proc && is_processing)
+ STOP_PROCESSING(SSobj, src)
+
+ _flooring = null
+ set_floor_broken(skip_update = TRUE)
+ set_floor_burned()
+
+ else if(is_processing)
+
+ STOP_PROCESSING(SSobj, src)
+
+ _flooring = newflooring
+ floor_icon_state_override = null
+ update_from_flooring(skip_update)
+
+ return TRUE
+
+/turf/floor/proc/update_from_flooring(skip_update)
+
+
+ var/decl/flooring/copy_from = get_topmost_flooring()
+ if(!istype(copy_from))
+ return // this should never be the case
+
+ update_floor_strings()
+
+ layer = copy_from.floor_layer
+ turf_flags = copy_from.turf_flags
+ z_flags = copy_from.z_flags
+
+ if(copy_from.turf_light_range || copy_from.turf_light_power || copy_from.turf_light_color)
+ set_light(copy_from.turf_light_range, copy_from.turf_light_power, copy_from.turf_light_color)
+ else
+ set_light(0)
+
+ if(z_flags & ZM_MIMIC_BELOW)
+ enable_zmimic(z_flags)
+ else
+ disable_zmimic()
+
+ if(copy_from.has_environment_proc && !is_processing)
+ START_PROCESSING(SSobj, src)
- set_light(0)
- set_floor_broken(skip_update = TRUE)
- set_floor_burned()
- flooring_override = null
levelupdate()
- if(!defer_icon_update)
- update_icon(1)
+ if(!skip_update)
+ update_icon()
+ for(var/dir in global.alldirs)
+ var/turf/neighbor = get_step_resolving_mimic(src, dir)
+ if(istype(neighbor))
+ neighbor.update_icon()
/turf/floor/can_engrave()
+ var/decl/flooring/flooring = get_topmost_flooring()
return flooring ? flooring.can_engrave : can_engrave
/turf/floor/shuttle_ceiling
@@ -142,16 +213,80 @@
/turf/floor/is_floor()
return !density && !is_open()
-/turf/floor/get_physical_height()
- return flooring?.height || 0
-
/turf/floor/handle_universal_decay()
if(!is_floor_burned())
burn_tile()
- else if(flooring)
+ else if(has_flooring())
break_tile_to_plating()
else
physically_destroyed()
/turf/floor/get_footstep_sound(var/mob/caller)
- . = ..() || get_footstep_for_mob(flooring?.footstep_type || /decl/footsteps/blank, caller)
+ . = ..()
+ if(!.)
+ var/decl/flooring/use_flooring = get_topmost_flooring()
+ if(istype(use_flooring))
+ return get_footstep_for_mob(use_flooring.footstep_type)
+ return get_footstep_for_mob(/decl/footsteps/blank)
+
+/turf/floor/get_movable_alpha_mask_state(atom/movable/mover)
+ . = ..()
+ if(!.)
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return flooring?.get_movable_alpha_mask_state(mover)
+
+/turf/floor/dismantle_turf(devastated, explode, no_product)
+ if(is_constructed_floor())
+ return ..()
+ return !!switch_to_base_turf()
+
+/turf/floor/get_soil_color()
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return flooring ? flooring.dirt_color : "#7c5e42"
+
+/turf/floor/get_color()
+ if(paint_color)
+ return paint_color
+ var/decl/flooring/flooring = get_topmost_flooring()
+ if(istype(flooring) && !isnull(flooring.color))
+ return flooring.color
+ var/decl/material/my_material = get_material()
+ if(istype(my_material))
+ return my_material.color
+ return color
+
+/turf/floor/proc/get_all_flooring()
+ . = list()
+ if(istype(_flooring))
+ . += _flooring
+ if(istype(_base_flooring))
+ . += _base_flooring
+
+/turf/floor/Process()
+ for(var/decl/flooring/flooring in get_all_flooring())
+ if(flooring.has_environment_proc)
+ return flooring.handle_environment_proc(src)
+ return PROCESS_KILL
+
+// In case a catwalk or other blocking item is destroyed.
+/turf/floor/Exited(atom/movable/AM)
+ . = ..()
+ if(!is_processing)
+ for(var/decl/flooring/flooring in get_all_flooring())
+ if(flooring.has_environment_proc)
+ START_PROCESSING(SSobj, src)
+ break
+
+// In case something of interest enters our turf.
+/turf/floor/Entered(atom/movable/AM)
+ . = ..()
+ for(var/decl/flooring/flooring in get_all_flooring())
+ if(flooring.has_environment_proc)
+ if(!is_processing)
+ START_PROCESSING(SSobj, src)
+ flooring.handle_environment_proc(src)
+ break
+
+/turf/floor/get_plant_growth_rate()
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return flooring ? flooring.growth_value : ..()
diff --git a/code/game/turfs/floors/floor_acts.dm b/code/game/turfs/floors/floor_acts.dm
index 9a9ae3f0833..38bf80eed75 100644
--- a/code/game/turfs/floors/floor_acts.dm
+++ b/code/game/turfs/floors/floor_acts.dm
@@ -25,18 +25,31 @@
break_tile()
hotspot_expose(1000,CELL_VOLUME)
+/turf/floor/fluid_act(var/datum/reagents/fluids)
+ . = ..()
+ if(!QDELETED(fluids) && fluids.total_volume)
+ for(var/decl/flooring/flooring in get_all_flooring())
+ if(flooring.fluid_act(src, fluids))
+ return
+
/turf/floor/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+
+ for(var/decl/flooring/flooring in get_all_flooring())
+ if(flooring.fire_act(src, air, exposed_temperature, exposed_volume))
+ return
+
var/temp_destroy = get_damage_temperature()
if(!is_floor_burned() && prob(5))
burn_tile(exposed_temperature)
- else if(temp_destroy && exposed_temperature >= (temp_destroy + 100) && prob(1) && !is_plating())
- make_plating() //destroy the tile, exposing plating
+ else if(temp_destroy && exposed_temperature >= (temp_destroy + 100) && prob(1) && has_flooring())
+ set_flooring(null) //destroy the tile, exposing plating
burn_tile(exposed_temperature)
return ..()
//should be a little bit lower than the temperature required to destroy the material
/turf/floor/proc/get_damage_temperature()
- return flooring ? flooring.damage_temperature : null
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return flooring?.damage_temperature
/turf/floor/adjacent_fire_act(turf/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume)
var/dir_to = get_dir(src, adj_turf)
diff --git a/code/game/turfs/floors/floor_attackby.dm b/code/game/turfs/floors/floor_attackby.dm
index 6cc34b7544f..c87c7b79ce9 100644
--- a/code/game/turfs/floors/floor_attackby.dm
+++ b/code/game/turfs/floors/floor_attackby.dm
@@ -7,170 +7,166 @@
return TRUE
return ..()
-/turf/floor/attackby(var/obj/item/C, var/mob/user)
+/turf/floor/attackby(var/obj/item/used_item, var/mob/user)
+ if(!used_item || !user)
+ return FALSE
+ if(istype(used_item, /obj/item/stack/tile/roof) || IS_COIL(used_item) || (has_flooring() && istype(used_item, /obj/item/stack/material/rods)))
+ return ..()
+ var/decl/flooring/top_flooring = get_topmost_flooring()
+ if(istype(top_flooring) && top_flooring.handle_item_interaction(src, user, used_item))
+ return TRUE
+ if(try_backfill(used_item, user))
+ return TRUE
+ if(try_stack_build(used_item, user))
+ return TRUE
+ if(try_turf_repair_or_deconstruct(used_item, user))
+ return TRUE
+ return ..()
- if(!C || !user)
- return 0
+/turf/floor/proc/try_build_catwalk(var/obj/item/used_item, var/mob/user)
+ if(!(locate(/obj/structure/catwalk) in src) && istype(used_item, /obj/item/stack/material/rods))
+ var/obj/item/stack/material/rods/R = used_item
+ if (R.use(2))
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
+ new /obj/structure/catwalk(src, R.material.type)
+ return TRUE
+ return FALSE
- if(istype(C, /obj/item/stack/tile/roof) || IS_COIL(C) || (flooring && istype(C, /obj/item/stack/material/rods)))
- return ..()
+/turf/floor/proc/try_stack_build(var/obj/item/stack/S, var/mob/user)
+ if(!istype(S))
+ return FALSE
+
+ if(is_floor_damaged())
+ to_chat(user, SPAN_WARNING("This section is too damaged to support anything. Use a welder to fix the damage."))
+ return TRUE
+
+ if(try_build_catwalk(S, user))
+ return TRUE
- if(!(IS_SCREWDRIVER(C) && flooring && (flooring.flags & TURF_REMOVE_SCREWDRIVER)) && try_graffiti(user, C))
+ var/decl/flooring/use_flooring
+ for(var/decl/flooring/F as anything in decls_repository.get_decls_of_subtype_unassociated(/decl/flooring))
+ if(!F.build_type)
+ continue
+ if((ispath(S.type, F.build_type) || ispath(S.build_type, F.build_type)) && (isnull(F.build_material) || S.material?.type == F.build_material))
+ use_flooring = F
+ break
+ if(!use_flooring)
+ return FALSE
+
+ // Do we have enough?
+ if(use_flooring.build_cost && S.get_amount() < use_flooring.build_cost)
+ to_chat(user, SPAN_WARNING("You require at least [use_flooring.build_cost] [S.name] to complete the [use_flooring.descriptor]."))
+ return TRUE
+ // Stay still and focus...
+ if(use_flooring.build_time && !do_after(user, use_flooring.build_time, src))
+ return TRUE
+ if(has_flooring() || !S || !user || !use_flooring)
return TRUE
+ if(S.use(use_flooring.build_cost))
+ set_flooring(use_flooring)
+ playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
+ return TRUE
+
+/turf/floor/proc/try_backfill(obj/item/stack/material/used_item, mob/user)
+
+ var/decl/flooring/flooring = get_topmost_flooring()
+ if((istype(flooring) && flooring.constructed) || !istype(used_item) || !istype(user))
+ return FALSE
- if(flooring)
- if(IS_CROWBAR(C) && user.a_intent != I_HURT)
+ flooring = get_base_flooring()
+ if(istype(flooring) && flooring.constructed)
+ return FALSE
+
+ if(!istype(used_item, /obj/item/stack/material/ore) && !istype(used_item, /obj/item/stack/material/lump))
+ return FALSE
+
+ if(get_physical_height() >= 0)
+ to_chat(user, SPAN_WARNING("\The [src] is flush with ground level and cannot be backfilled."))
+ return TRUE
+
+ if(!used_item.material?.can_backfill_turf_type)
+ to_chat(user, SPAN_WARNING("You cannot use \the [used_item] to backfill \the [src]."))
+ return TRUE
+
+ var/can_backfill = islist(used_item.material.can_backfill_turf_type) ? is_type_in_list(src, used_item.material.can_backfill_turf_type) : istype(src, used_item.material.can_backfill_turf_type)
+ if(!can_backfill)
+ to_chat(user, SPAN_WARNING("You cannot use \the [used_item] to backfill \the [src]."))
+ return TRUE
+
+ var/obj/item/stack/stack = used_item
+ if(!do_after(user, 1 SECOND, src) || user.get_active_held_item() != stack || get_physical_height() >= 0)
+ return TRUE
+
+ // At best, you get about 5 pieces of clay or dirt from digging the
+ // associated turfs. So we'll make it cost 5 to put some back.
+ // TODO: maybe make this use the diggable loot list.
+ var/stack_depth = ceil((abs(get_physical_height()) / TRENCH_DEPTH_PER_ACTION) * 5)
+ var/using_lumps = max(1, min(stack.amount, min(stack_depth, 5)))
+ if(stack.use(using_lumps))
+ set_physical_height(min(0, get_physical_height() + ((using_lumps / 5) * TRENCH_DEPTH_PER_ACTION)))
+ playsound(src, 'sound/items/shovel_dirt.ogg', 50, TRUE)
+ if(get_physical_height() >= 0)
+ visible_message(SPAN_NOTICE("\The [user] backfills \the [src]!"))
+ else
+ visible_message(SPAN_NOTICE("\The [user] partially backfills \the [src]."))
+ return TRUE
+
+/turf/floor/proc/is_constructed_floor()
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return flooring?.constructed
+
+/turf/floor/proc/try_turf_repair_or_deconstruct(var/obj/item/used_item, var/mob/user)
+
+ if(!is_constructed_floor())
+ return FALSE
+
+ if(IS_CROWBAR(used_item) && is_floor_damaged())
+ playsound(src, 'sound/items/Crowbar.ogg', 80, 1)
+ visible_message(SPAN_NOTICE("\The [user] has begun prying off the damaged plating."))
+ . = TRUE
+ var/turf/T = GetBelow(src)
+ if(T)
+ T.visible_message(SPAN_DANGER("The ceiling above looks as if it's being pried off."))
+
+ if(do_after(user, 10 SECONDS))
+ if(!is_floor_damaged() || !(is_plating()))return
+ visible_message(SPAN_DANGER("\The [user] has pried off the damaged plating!"))
+ new /obj/item/stack/tile/floor(src)
+ physically_destroyed()
+ playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
+ if(T)
+ T.visible_message(SPAN_DANGER("The ceiling above has been pried off!"))
+ return TRUE
+
+ if(IS_WELDER(used_item))
+ var/obj/item/weldingtool/welder = used_item
+ if(welder.isOn() && is_plating() && welder.weld(0, user))
if(is_floor_damaged())
- if(!user.do_skilled(flooring.remove_timer, SKILL_CONSTRUCTION, src, 0.15))
- return TRUE
- if(!flooring)
- return
- to_chat(user, "You remove the broken [flooring.descriptor].")
- make_plating()
- else if(flooring.flags & TURF_IS_FRAGILE)
- if(!user.do_skilled(flooring.remove_timer, SKILL_CONSTRUCTION, src, 0.15))
- return TRUE
- if(!flooring)
- return
- to_chat(user, "You forcefully pry off the [flooring.descriptor], destroying them in the process.")
- make_plating()
- else if(flooring.flags & TURF_REMOVE_CROWBAR)
- if(!user.do_skilled(flooring.remove_timer, SKILL_CONSTRUCTION, src))
- return TRUE
- if(!flooring)
- return
- to_chat(user, "You lever off the [flooring.descriptor].")
- make_plating(TRUE)
+ to_chat(user, SPAN_NOTICE("You fix some damage to \the [src]."))
+ playsound(src, 'sound/items/Welder.ogg', 80, 1)
+ icon_state = "plating"
+ set_floor_burned(skip_update = TRUE)
+ set_floor_broken()
else
- return
- playsound(src, 'sound/items/Crowbar.ogg', 80, 1)
- return TRUE
- else if(IS_SCREWDRIVER(C) && (flooring.flags & TURF_REMOVE_SCREWDRIVER))
- if(is_floor_damaged())
- return
- if(!user.do_skilled(flooring.remove_timer, SKILL_CONSTRUCTION, src))
- return TRUE
- if(!flooring)
- return
- to_chat(user, "You unscrew and remove the [flooring.descriptor].")
- make_plating(TRUE)
- playsound(src, 'sound/items/Screwdriver.ogg', 80, 1)
- return TRUE
- else if(IS_WRENCH(C) && (flooring.flags & TURF_REMOVE_WRENCH))
- if(!user.do_skilled(flooring.remove_timer, SKILL_CONSTRUCTION, src))
- return TRUE
- if(!flooring)
- return
- to_chat(user, "You unwrench and remove the [flooring.descriptor].")
- make_plating(TRUE)
- playsound(src, 'sound/items/Ratchet.ogg', 80, 1)
- return TRUE
- else if(IS_SHOVEL(C) && (flooring.flags & TURF_REMOVE_SHOVEL))
- if(!user.do_skilled(flooring.remove_timer, SKILL_CONSTRUCTION, src))
- return TRUE
- if(!flooring)
- return
- to_chat(user, "You shovel off the [flooring.descriptor].")
- make_plating(TRUE)
- playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
- return TRUE
- else if(IS_COIL(C))
- to_chat(user, "You must remove the [flooring.descriptor] first.")
+ playsound(src, 'sound/items/Welder.ogg', 80, 1)
+ visible_message(SPAN_NOTICE("\The [user] has started melting \the [src]'s reinforcements!"))
+ if(do_after(user, 5 SECONDS) && welder.isOn() && welder_melt())
+ visible_message(SPAN_NOTICE("\The [user] has melted \the [src]'s reinforcements! It should now be possible to pry it off."))
+ playsound(src, 'sound/items/Welder.ogg', 80, 1)
return TRUE
- else
- if(istype(C, /obj/item/stack))
- if(is_floor_damaged())
- to_chat(user, "This section is too damaged to support anything. Use a welder to fix the damage.")
- return TRUE
- //first check, catwalk? Else let flooring do its thing
- if(locate(/obj/structure/catwalk, src))
- return
- if (istype(C, /obj/item/stack/material/rods))
- var/obj/item/stack/material/rods/R = C
- if (R.use(2))
- playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
- new /obj/structure/catwalk(src, R.material.type)
- return TRUE
- return
-
- var/obj/item/stack/S = C
- var/decl/flooring/use_flooring
- var/list/decls = decls_repository.get_decls_of_subtype(/decl/flooring)
- for(var/flooring_type in decls)
- var/decl/flooring/F = decls[flooring_type]
- if(!F.build_type)
- continue
- if((ispath(S.type, F.build_type) || ispath(S.build_type, F.build_type)) && (isnull(F.build_material) || S.material?.type == F.build_material))
- use_flooring = F
- break
-
- if(use_flooring)
- // Do we have enough?
- if(use_flooring.build_cost && S.get_amount() < use_flooring.build_cost)
- to_chat(user, "You require at least [use_flooring.build_cost] [S.name] to complete the [use_flooring.descriptor].")
- return TRUE
- // Stay still and focus...
- if(use_flooring.build_time && !do_after(user, use_flooring.build_time, src))
- return TRUE
- if(flooring || !S || !user || !use_flooring)
- return TRUE
- if(S.use(use_flooring.build_cost))
- set_flooring(use_flooring)
- playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
- return TRUE
-
- // Repairs and Deconstruction.
- else if(IS_CROWBAR(C))
- if(is_floor_damaged())
- playsound(src, 'sound/items/Crowbar.ogg', 80, 1)
- visible_message("[user] has begun prying off the damaged plating.")
- . = TRUE
- var/turf/T = GetBelow(src)
- if(T)
- T.visible_message("The ceiling above looks as if it's being pried off.")
- if(do_after(user, 10 SECONDS))
- if(!is_floor_damaged() || !(is_plating()))return
- visible_message("[user] has pried off the damaged plating.")
- new /obj/item/stack/tile/floor(src)
- physically_destroyed()
- playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
- if(T)
- T.visible_message("The ceiling above has been pried off!")
- return
- else if(IS_WELDER(C))
- var/obj/item/weldingtool/welder = C
- if(welder.isOn() && (is_plating()))
- if(is_floor_damaged())
- if(welder.weld(0, user))
- to_chat(user, "You fix some dents on the broken plating.")
- playsound(src, 'sound/items/Welder.ogg', 80, 1)
- icon_state = "plating"
- set_floor_burned(skip_update = TRUE)
- set_floor_broken()
- return TRUE
- else
- if(welder.weld(0, user))
- playsound(src, 'sound/items/Welder.ogg', 80, 1)
- visible_message("[user] has started melting the plating's reinforcements!")
- . = TRUE
- if(do_after(user, 5 SECONDS) && welder.isOn() && welder_melt())
- visible_message("[user] has melted the plating's reinforcements! It should be possible to pry it off.")
- playsound(src, 'sound/items/Welder.ogg', 80, 1)
- return
- else if(istype(C, /obj/item/gun/energy/plasmacutter) && (is_plating()) && !is_floor_damaged())
- var/obj/item/gun/energy/plasmacutter/cutter = C
- if(!cutter.slice(user))
- return ..()
+ if(istype(used_item, /obj/item/gun/energy/plasmacutter) && (is_plating()) && !is_floor_damaged())
+ var/obj/item/gun/energy/plasmacutter/cutter = used_item
+ if(cutter.slice(user))
playsound(src, 'sound/items/Welder.ogg', 80, 1)
- visible_message("[user] has started slicing through the plating's reinforcements!")
+ visible_message(SPAN_NOTICE("\The [user] has started slicing through \the [src]'s reinforcements!"))
. = TRUE
if(do_after(user, 3 SECONDS) && welder_melt())
- visible_message("[user] has sliced through the plating's reinforcements! It should be possible to pry it off.")
+ visible_message(SPAN_NOTICE("\The [user] has sliced through \the [src]'s reinforcements! It should now be possible to pry it off."))
playsound(src, 'sound/items/Welder.ogg', 80, 1)
- return
+ return TRUE
- return ..()
+ return FALSE
/turf/floor/proc/welder_melt()
if(!(is_plating()) || is_floor_damaged())
diff --git a/code/game/turfs/floors/floor_damage.dm b/code/game/turfs/floors/floor_damage.dm
index 18d1cc775c7..b312a1ab300 100644
--- a/code/game/turfs/floors/floor_damage.dm
+++ b/code/game/turfs/floors/floor_damage.dm
@@ -1,16 +1,18 @@
/turf/floor/proc/break_tile_to_plating()
- if(!is_plating())
- make_plating()
+ if(has_flooring())
+ set_flooring(null)
break_tile()
/turf/floor/proc/break_tile()
- if(!flooring || !(flooring.flags & TURF_CAN_BREAK) || is_floor_broken())
+ var/decl/flooring/flooring = get_topmost_flooring()
+ if(!istype(flooring) || !(flooring.flooring_flags & TURF_CAN_BREAK) || is_floor_broken())
return
set_floor_broken(TRUE)
remove_decals()
/turf/floor/proc/burn_tile(var/exposed_temperature)
- if(!flooring || !(flooring.flags & TURF_CAN_BURN) || is_floor_burned())
+ var/decl/flooring/flooring = get_topmost_flooring()
+ if(!istype(flooring) || !(flooring.flooring_flags & TURF_CAN_BURN) || is_floor_burned())
return
set_floor_burned(TRUE)
remove_decals()
diff --git a/code/game/turfs/floors/floor_digging.dm b/code/game/turfs/floors/floor_digging.dm
new file mode 100644
index 00000000000..4262e953ad8
--- /dev/null
+++ b/code/game/turfs/floors/floor_digging.dm
@@ -0,0 +1,43 @@
+/turf/floor/proc/is_fundament()
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return flooring ? !flooring.constructed : TRUE
+
+/turf/floor/can_be_dug(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
+ // This should be removed before digging trenches.
+ if(!is_fundament())
+ return FALSE
+ var/decl/flooring/flooring = get_base_flooring()
+ if(istype(flooring) && flooring.constructed)
+ return FALSE
+ var/decl/material/my_material = get_material()
+ if(density || is_open() || !istype(my_material))
+ return FALSE
+ if(my_material.hardness > tool_hardness)
+ return FALSE
+ if(using_tool == TOOL_SHOVEL && my_material.hardness > MAT_VALUE_FLEXIBLE)
+ return FALSE
+ if(using_tool == TOOL_PICK && my_material.hardness <= MAT_VALUE_FLEXIBLE)
+ return FALSE
+ return TRUE
+
+/turf/floor/can_dig_trench(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
+ return can_be_dug(tool_hardness, using_tool) && get_physical_height() > -(FLUID_DEEP)
+
+/turf/floor/dig_trench(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
+ if(!is_fundament())
+ return
+ var/new_height = max(get_physical_height()-TRENCH_DEPTH_PER_ACTION, -(FLUID_DEEP))
+ var/height_diff = abs(get_physical_height()-new_height)
+ // Only drop mats if we actually changed the turf height sufficiently.
+ if(height_diff >= TRENCH_DEPTH_PER_ACTION)
+ drop_diggable_resources()
+ set_physical_height(new_height)
+
+/turf/floor/dig_pit(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
+ return has_flooring() ? null : ..()
+
+/turf/floor/get_diggable_resources()
+ var/decl/material/my_material = get_material()
+ if(is_fundament() && istype(my_material) && my_material.dug_drop_type && (get_physical_height() > -(FLUID_DEEP)))
+ return list(my_material.dug_drop_type = list(3, 2))
+ return null
diff --git a/code/game/turfs/floors/natural/_natural_height.dm b/code/game/turfs/floors/floor_height.dm
similarity index 70%
rename from code/game/turfs/floors/natural/_natural_height.dm
rename to code/game/turfs/floors/floor_height.dm
index 41bdb0d3759..2dd080f5edd 100644
--- a/code/game/turfs/floors/natural/_natural_height.dm
+++ b/code/game/turfs/floors/floor_height.dm
@@ -1,10 +1,10 @@
-/turf/floor/natural
+/turf/floor
var/height = 0
-/turf/floor/natural/get_physical_height()
+/turf/floor/get_physical_height()
return density ? 0 : height
-/turf/floor/natural/set_physical_height(new_height)
+/turf/floor/set_physical_height(new_height)
if(height != new_height)
height = new_height
for(var/turf/neighbor as anything in RANGE_TURFS(src, 1))
diff --git a/code/game/turfs/floors/floor_icon.dm b/code/game/turfs/floors/floor_icon.dm
index 50886bfa51d..656b0cf3aeb 100644
--- a/code/game/turfs/floors/floor_icon.dm
+++ b/code/game/turfs/floors/floor_icon.dm
@@ -7,14 +7,43 @@
/// A cache for trench images, keyed by icon and then by color.
VAR_PRIVATE/static/list/_trench_image_cache = list()
+/turf/floor/proc/can_draw_edge_over(turf/floor/turf_to_check)
+ if(istype(turf_to_check))
+ var/my_height = get_physical_height()
+ var/their_height = turf_to_check.get_physical_height()
+ // Uppermost turfs draw over lower turfs if there is a serious difference.
+ if(my_height != their_height)
+ return my_height > their_height
+ // Use edge layer if we're within height range.
+ return can_layer_over(turf_to_check)
+ return TRUE
+
+/turf/floor/proc/can_layer_over(turf/floor/turf_to_check)
+ if(!istype(turf_to_check))
+ return FALSE
+ var/decl/flooring/my_flooring = get_topmost_flooring()
+ if(!istype(my_flooring) || my_flooring.icon_edge_layer == FLOOR_EDGE_NONE)
+ return FALSE
+ var/decl/flooring/their_flooring = turf_to_check.get_topmost_flooring()
+ if(!istype(their_flooring))
+ return TRUE
+ if(their_flooring?.type == my_flooring.neighbour_type)
+ return FALSE
+ return my_flooring.icon_edge_layer > their_flooring.icon_edge_layer
+
/turf/floor/proc/get_trench_icon()
- var/check_icon = (istype(flooring) && flooring.icon) || icon
- if(check_icon && check_state_in_icon("trench", check_icon))
- return check_icon
+ var/decl/flooring/flooring = get_base_flooring() || get_topmost_flooring()
+ if(istype(flooring) && flooring.icon && check_state_in_icon("trench", flooring.icon))
+ return flooring.icon
/turf/floor/proc/update_height_appearance()
- layer = TURF_LAYER
+ var/decl/flooring/flooring = get_topmost_flooring()
+ if(istype(flooring))
+ layer = flooring.floor_layer
+ else
+ layer = initial(layer)
+
if(istype(flooring) && !flooring.render_trenches) // TODO: Update pool tiles/edges to behave properly with this new system.
return FALSE
@@ -43,32 +72,39 @@
return
if(!istype(neighbor) || (neighbor.get_physical_height() > my_height))
+
var/trench_icon = (istype(neighbor) && neighbor.get_trench_icon()) || get_trench_icon()
if(trench_icon)
-
// cache the trench image, keyed by icon and color
var/trench_color = isatom(neighbor) ? neighbor.color : color
var/trench_icon_key = "[ref(trench_icon)][trench_color]"
- if(!_trench_image_cache[trench_icon_key])
- _trench_image_cache[trench_icon_key] = I = image(icon = trench_icon, icon_state = "trench")
+ I = _trench_image_cache[trench_icon_key]
+ if(!I)
+ I = image(icon = trench_icon, icon_state = "trench")
I.pixel_z = world.icon_size
I.appearance_flags |= RESET_COLOR | RESET_ALPHA
I.color = trench_color
+ _trench_image_cache[trench_icon_key] = I
add_overlay(I)
- // look up a shadow for our shadow_alpha in the cache, creating one if needed
- I = _height_north_shadow_cache[shadow_alpha_key]
- if(!I)
- _height_north_shadow_cache[shadow_alpha_key] = I = image(icon = 'icons/effects/height_shadow.dmi', icon_state = "northedge")
- I.pixel_z = world.icon_size
- I.color = COLOR_BLACK
- I.alpha = shadow_alpha
- I.appearance_flags |= RESET_COLOR | RESET_ALPHA
- add_overlay(I)
+ // look up a shadow for our shadow_alpha in the cache, creating one if needed
+ I = _height_north_shadow_cache[shadow_alpha_key]
+ if(!I)
+ I = image(icon = 'icons/effects/height_shadow.dmi', icon_state = "northedge")
+ I.pixel_z = world.icon_size
+ I.color = COLOR_BLACK
+ I.alpha = shadow_alpha
+ I.appearance_flags |= RESET_COLOR | RESET_ALPHA
+ _height_north_shadow_cache[shadow_alpha_key] = I
+ add_overlay(I)
/turf/floor/on_update_icon(var/update_neighbors)
. = ..()
+
+ color = get_color()
+
cut_overlays()
+ update_height_appearance() // Also refreshes out base layer.
update_floor_icon(update_neighbors)
for(var/image/I in decals)
@@ -81,31 +117,42 @@
if(is_floor_burned())
add_overlay(get_turf_damage_overlay(_floor_burned))
- update_height_appearance()
-
- compile_overlays()
-
if(update_neighbors)
for(var/turf/floor/F in orange(src, 1))
F.queue_ao()
F.queue_icon_update()
-/turf/floor/proc/update_floor_icon(update_neighbors)
+ compile_overlays()
+
+/turf/floor/proc/update_floor_strings()
+ var/decl/flooring/flooring = get_topmost_flooring()
if(istype(flooring))
- flooring.update_turf_icon(src)
+ SetName(flooring.name)
+ desc = flooring.desc
+ else
+ SetName(initial(name))
+ desc = initial(desc)
+
+/turf/floor/proc/update_floor_icon(update_neighbors)
+ var/decl/flooring/use_flooring = get_topmost_flooring()
+ if(istype(use_flooring))
+ use_flooring.update_turf_icon(src)
/turf/floor/proc/is_floor_broken()
- return !isnull(_floor_broken) && (!flooring || (flooring.flags & TURF_CAN_BREAK))
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return !isnull(_floor_broken) && (!istype(flooring) || (flooring.flooring_flags & TURF_CAN_BREAK))
/turf/floor/proc/is_floor_burned()
- return !isnull(_floor_burned) && (!flooring || (flooring.flags & TURF_CAN_BURN))
+ var/decl/flooring/flooring = get_topmost_flooring()
+ return !isnull(_floor_burned) && (!istype(flooring) || (flooring.flooring_flags & TURF_CAN_BURN))
/turf/floor/proc/is_floor_damaged()
return is_floor_broken() || is_floor_burned()
/turf/floor/proc/set_floor_broken(new_broken, skip_update)
- if(flooring && !(flooring.flags & TURF_CAN_BREAK))
+ var/decl/flooring/flooring = get_topmost_flooring()
+ if(istype(flooring) && !(flooring.flooring_flags & TURF_CAN_BREAK))
return FALSE
// Hardcoded because they're bundled into the same icon file at the moment.
@@ -127,7 +174,8 @@
/turf/floor/proc/set_floor_burned(new_burned, skip_update)
- if(flooring && !(flooring.flags & TURF_CAN_BURN))
+ var/decl/flooring/flooring = get_topmost_flooring()
+ if(istype(flooring) && !(flooring.flooring_flags & TURF_CAN_BURN))
return FALSE
// Hardcoded because they're bundled into the same icon file at the moment.
@@ -158,41 +206,42 @@
return global.flooring_cache[cache_key]
/decl/flooring/proc/test_link(var/turf/origin, var/turf/opponent)
- var/is_linked = FALSE
- if(istype(origin) && istype(opponent))
- //is_wall is true for wall turfs and for floors containing a low wall
- if(opponent.is_wall())
- if(wall_smooth == SMOOTH_ALL)
- is_linked = TRUE
- //If is_hole is true, then it's space or openspace
- else if(opponent.is_open())
- if(space_smooth == SMOOTH_ALL)
- is_linked = TRUE
-
- //If we get here then its a normal floor
- else if (istype(opponent, /turf/floor))
- var/turf/floor/floor_opponent = opponent
- //If the floor is the same as us,then we're linked,
- if (istype(src, floor_opponent.flooring))
- is_linked = TRUE
- else if (floor_smooth == SMOOTH_ALL)
- is_linked = TRUE
- else if (floor_smooth != SMOOTH_NONE)
- //If we get here it must be using a whitelist or blacklist
- if (floor_smooth == SMOOTH_WHITELIST)
- if (flooring_whitelist[floor_opponent.flooring.type])
- //Found a match on the typecache
- is_linked = TRUE
- else if(floor_smooth == SMOOTH_BLACKLIST)
- is_linked = TRUE //Default to true for the blacklist, then make it false if a match comes up
- if (flooring_blacklist[floor_opponent.flooring.type])
- //Found a match on the typecache
- is_linked = FALSE
- //Check for window frames.
- if (!is_linked && wall_smooth == SMOOTH_ALL)
- if(locate(/obj/structure/wall_frame) in opponent)
- is_linked = TRUE
- return is_linked
+ if(!istype(origin) || !istype(opponent))
+ return FALSE
+
+ . = FALSE
+ //is_wall is true for wall turfs and for floors containing a low wall
+ if(opponent.is_wall())
+ if(wall_smooth == SMOOTH_ALL)
+ . = TRUE
+ //If is_hole is true, then it's space or openspace
+ else if(opponent.is_open())
+ if(space_smooth == SMOOTH_ALL)
+ . = TRUE
+
+ //If we get here then its a normal floor
+ else if (istype(opponent, /turf/floor))
+ var/turf/floor/floor_opponent = opponent
+ var/decl/flooring/opponent_flooring = floor_opponent.get_topmost_flooring()
+ if (floor_smooth == SMOOTH_ALL)
+ . = TRUE
+ //If the floor is the same as us,then we're linked,
+ else if (istype(opponent_flooring, neighbour_type))
+ . = TRUE
+ //If we get here it must be using a whitelist or blacklist
+ else if (floor_smooth == SMOOTH_WHITELIST)
+ if (flooring_whitelist[opponent_flooring.type])
+ //Found a match on the typecache
+ . = TRUE
+ else if(floor_smooth == SMOOTH_BLACKLIST)
+ . = TRUE //Default to true for the blacklist, then make it false if a match comes up
+ if (flooring_blacklist[opponent_flooring.type])
+ //Found a match on the typecache
+ . = FALSE
+ //Check for window frames.
+ if (!. && wall_smooth == SMOOTH_ALL)
+ if(locate(/obj/structure/wall_frame) in opponent)
+ . = TRUE
/decl/flooring/proc/symmetric_test_link(var/turf/A, var/turf/B)
return test_link(A, B) && test_link(B,A)
diff --git a/code/game/turfs/floors/floor_materials.dm b/code/game/turfs/floors/floor_materials.dm
new file mode 100644
index 00000000000..17dbe09f0a9
--- /dev/null
+++ b/code/game/turfs/floors/floor_materials.dm
@@ -0,0 +1,24 @@
+/turf/floor
+ VAR_PROTECTED/decl/material/floor_material
+
+/turf/floor/set_turf_materials(decl/material/new_material, decl/material/new_reinf_material, force, decl/material/new_girder_material, skip_update)
+
+ if(ispath(new_material))
+ new_material = GET_DECL(new_material)
+
+ if(floor_material != new_material || force)
+ floor_material = new_material
+ if(!istype(floor_material))
+ if(floor_material)
+ PRINT_STACK_TRACE("Floor turf has been supplied non-material '[istype(floor_material, /datum) ? floor_material.type : (floor_material || "NULL")]'.")
+ floor_material = get_default_material()
+ . = TRUE
+
+ if(. && !skip_update)
+ queue_icon_update()
+
+/turf/floor/get_material()
+ var/decl/flooring/flooring = get_topmost_flooring()
+ if(istype(flooring) && istype(flooring.force_material))
+ return flooring.force_material
+ return floor_material
diff --git a/code/game/turfs/floors/natural/_natural.dm b/code/game/turfs/floors/natural/_natural.dm
deleted file mode 100644
index fa616749e33..00000000000
--- a/code/game/turfs/floors/natural/_natural.dm
+++ /dev/null
@@ -1,127 +0,0 @@
-/turf/floor/natural
-
- name = "ground"
- gender = PLURAL
- icon = 'icons/turf/flooring/barren.dmi'
- desc = "Bare, barren sand."
- icon_state = "0"
- footstep_type = /decl/footsteps/asteroid
- turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH
-
- base_name = "ground"
- base_desc = "Bare, barren sand."
- base_icon = 'icons/turf/flooring/barren.dmi'
- base_icon_state = "0"
- base_color = null
-
- can_engrave = FALSE
-
- var/dirt_color = "#7c5e42"
- var/possible_states = 0
- var/icon_edge_layer = -1
- var/icon_edge_states
- var/icon_has_corners = FALSE
- /// The type to use when determining if a turf is our neighbour. If null, defaults to src's type.
- var/neighbour_type
-
- ///Overrides the level's strata for this turf.
- var/strata_override
- var/decl/material/material
-
- var/is_fundament_turf = FALSE
- var/reagent_type
- var/const/TRENCH_DEPTH_PER_ACTION = 100
-
-/turf/floor/natural/get_plant_growth_rate()
- return 0.1
-
-/turf/floor/natural/Initialize(mapload, no_update_icon = FALSE)
-
- if(base_color)
- color = base_color
- else
- color = null
-
- if(possible_states > 0)
- icon_state = "[rand(0, possible_states)]"
-
- neighbour_type ||= type
-
- // TEMP: set these so putting tiles over natural turfs doesn't make green sand.
- base_name = name
- base_desc = desc
- base_icon = icon
- base_icon_state = icon_state
- base_color = color
- // END TEMP
-
- if(material)
- set_turf_materials(material, skip_update = no_update_icon)
-
- . = ..(mapload) // second param is our own, don't pass to children
-
- if(!no_update_icon)
- // If this is a mapload, then our neighbors will be updating their own icons too -- doing it for them is rude.
- if(!mapload)
- for(var/direction in global.alldirs)
- var/turf/target_turf = get_step_resolving_mimic(src, direction)
- if(istype(target_turf))
- if(TICK_CHECK) // not CHECK_TICK -- only queue if the server is overloaded
- target_turf.queue_icon_update()
- else
- target_turf.update_icon()
- update_icon()
-
- if(reagent_type && height < 0)
- add_to_reagents(reagent_type, abs(height))
-
-/turf/floor/natural/attackby(obj/item/W, mob/user)
-
- if(!istype(flooring) && (istype(W, /obj/item/stack/material/ore) || istype(W, /obj/item/stack/material/lump)))
-
- if(get_physical_height() >= 0)
- to_chat(user, SPAN_WARNING("\The [src] is flush with ground level and cannot be backfilled."))
- return TRUE
-
- if(!W.material?.can_backfill_turf_type)
- to_chat(user, SPAN_WARNING("You cannot use \the [W] to backfill \the [src]."))
- return TRUE
-
- var/can_backfill = islist(W.material.can_backfill_turf_type) ? is_type_in_list(src, W.material.can_backfill_turf_type) : istype(src, W.material.can_backfill_turf_type)
- if(!can_backfill)
- to_chat(user, SPAN_WARNING("You cannot use \the [W] to backfill \the [src]."))
- return TRUE
-
- var/obj/item/stack/stack = W
- if(!do_after(user, 1 SECOND, src) || user.get_active_held_item() != stack || get_physical_height() >= 0)
- return TRUE
-
- // At best, you get about 5 pieces of clay or dirt from digging the
- // associated turfs. So we'll make it cost 5 to put some back.
- // TODO: maybe make this use the diggable loot list.
- var/stack_depth = ceil((abs(get_physical_height()) / TRENCH_DEPTH_PER_ACTION) * 5)
- var/using_lumps = max(1, min(stack.amount, min(stack_depth, 5)))
- if(stack.use(using_lumps))
- set_physical_height(min(0, get_physical_height() + ((using_lumps / 5) * TRENCH_DEPTH_PER_ACTION)))
- playsound(src, 'sound/items/shovel_dirt.ogg', 50, TRUE)
- if(get_physical_height() >= 0)
- visible_message(SPAN_NOTICE("\The [user] backfills \the [src]!"))
- else
- visible_message(SPAN_NOTICE("\The [user] partially backfills \the [src]."))
- return TRUE
-
- return ..()
-
-/turf/floor/natural/on_reagent_change()
-
- if(!(. = ..()))
- return
-
- if(!QDELETED(src) && reagent_type && height < 0 && !QDELETED(reagents) && reagents.total_volume < abs(height))
- add_to_reagents(reagent_type, abs(height) - reagents.total_volume)
-
-/turf/floor/natural/dismantle_turf(devastated, explode, no_product, keep_air = TRUE)
- return !!switch_to_base_turf(keep_air)
-
-/turf/floor/natural/get_soil_color()
- return dirt_color
diff --git a/code/game/turfs/floors/natural/_natural_digging.dm b/code/game/turfs/floors/natural/_natural_digging.dm
deleted file mode 100644
index dc5f8d3197e..00000000000
--- a/code/game/turfs/floors/natural/_natural_digging.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-/turf/floor/natural/get_diggable_resources()
- if(istype(material) && material.dug_drop_type && (get_physical_height() > -(FLUID_DEEP)))
- return list(material.dug_drop_type = list(3, 2))
-
-/turf/floor/natural/can_be_dug(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
- . = !density && !is_open() && material
- if(.)
- if(material.hardness > tool_hardness)
- return FALSE
- if(using_tool == TOOL_SHOVEL && material.hardness > MAT_VALUE_FLEXIBLE)
- return FALSE
- if(using_tool == TOOL_PICK && material.hardness <= MAT_VALUE_FLEXIBLE)
- return FALSE
-
-/turf/floor/natural/dig_pit(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
- if(is_fundament_turf)
- return ..()
- drop_diggable_resources()
- ChangeTurf(/turf/floor/natural/dirt, keep_air = TRUE, keep_height = TRUE)
-
-/turf/floor/natural/dig_farm(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
- if(is_fundament_turf)
- return ..()
- drop_diggable_resources()
- ChangeTurf(/turf/floor/natural/dirt, keep_air = TRUE, keep_height = TRUE)
-
-/turf/floor/natural/dig_trench(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
- if(is_fundament_turf)
- var/new_height = max(get_physical_height()-TRENCH_DEPTH_PER_ACTION, -(FLUID_DEEP))
- var/height_diff = abs(get_physical_height()-new_height)
- // Only drop mats if we actually changed the turf height sufficiently.
- if(height_diff >= TRENCH_DEPTH_PER_ACTION)
- drop_diggable_resources()
- set_physical_height(new_height)
- else
- drop_diggable_resources()
- ChangeTurf(/turf/floor/natural/dirt, keep_air = TRUE, keep_height = TRUE)
diff --git a/code/game/turfs/floors/natural/_natural_icon.dm b/code/game/turfs/floors/natural/_natural_icon.dm
deleted file mode 100644
index 7467910b6dc..00000000000
--- a/code/game/turfs/floors/natural/_natural_icon.dm
+++ /dev/null
@@ -1,43 +0,0 @@
-/turf/floor/natural/proc/can_draw_edge_over(turf/floor/natural/turf_to_check)
- if(istype(turf_to_check))
- var/my_height = get_physical_height()
- var/their_height = turf_to_check.get_physical_height()
- // Uppermost turfs draw over lower turfs if there is a serious difference.
- if(my_height != their_height)
- return my_height > their_height
- // Use edge layer if we're within height range.
- return icon_edge_layer > turf_to_check.icon_edge_layer
- return TRUE
-
-/turf/floor/natural/update_floor_icon(update_neighbors)
-
- if(flooring)
- return ..()
-
- if(icon_edge_layer < 0)
- return
-
- var/my_height = get_physical_height()
- for(var/direction in (icon_has_corners ? global.alldirs : global.cardinal))
-
- var/turf/floor/natural/turf_to_check = get_step_resolving_mimic(src, direction)
- if(!isturf(turf_to_check) || turf_to_check.density)
- continue
-
- if(istype(turf_to_check, neighbour_type) && my_height == turf_to_check.get_physical_height())
- continue
-
- if(!can_draw_edge_over(turf_to_check))
- continue
-
- var/image/I = image(icon, "edge[direction][icon_edge_states > 0 ? rand(0, icon_edge_states) : ""]")
- I.layer = layer + icon_edge_layer
- if(direction & NORTH)
- I.pixel_y += world.icon_size
- else if(direction & SOUTH)
- I.pixel_y -= world.icon_size
- if(direction & EAST)
- I.pixel_x += world.icon_size
- else if(direction & WEST)
- I.pixel_x -= world.icon_size
- add_overlay(I)
diff --git a/code/game/turfs/floors/natural/_natural_materials.dm b/code/game/turfs/floors/natural/_natural_materials.dm
deleted file mode 100644
index 8d74dd68323..00000000000
--- a/code/game/turfs/floors/natural/_natural_materials.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-/turf/floor/natural/set_turf_materials(decl/material/new_material, decl/material/new_reinf_material, force, decl/material/new_girder_material, skip_update)
-
- if(ispath(new_material))
- new_material = GET_DECL(new_material)
-
- if(material != new_material || force)
- material = new_material
- if(!istype(material))
- PRINT_STACK_TRACE("Exterior turf has been supplied non-material '[material]'.")
- material = get_default_material()
- . = TRUE
-
- if(.)
- update_from_material()
- if(!skip_update)
- queue_icon_update()
-
-/turf/floor/natural/proc/update_from_material()
- return
-
-/turf/floor/natural/get_material()
- return material
-
-/turf/floor/natural/get_strata_material_type()
- //Turf strata overrides level strata
- if(ispath(strata_override, /decl/strata))
- var/decl/strata/S = GET_DECL(strata_override)
- if(length(S.base_materials))
- return pick(S.base_materials)
- //Otherwise, just use level strata
- return ..()
\ No newline at end of file
diff --git a/code/game/turfs/floors/natural/natural_barren.dm b/code/game/turfs/floors/natural/natural_barren.dm
deleted file mode 100644
index b9d7b458640..00000000000
--- a/code/game/turfs/floors/natural/natural_barren.dm
+++ /dev/null
@@ -1,14 +0,0 @@
-/turf/floor/natural/barren
- name = "ground"
- icon = 'icons/turf/flooring/barren.dmi'
- icon_edge_layer = EXT_EDGE_BARREN
- is_fundament_turf = TRUE
- material = /decl/material/solid/sand
-
-/turf/floor/natural/barren/airless
- initial_gas = null
-
-/turf/floor/natural/barren/Initialize()
- if(prob(20))
- LAZYADD(decals, image('icons/turf/flooring/decals.dmi', "asteroid[rand(0,9)]"))
- . = ..()
diff --git a/code/game/turfs/floors/natural/natural_chlorine.dm b/code/game/turfs/floors/natural/natural_chlorine.dm
deleted file mode 100644
index e143aecb79c..00000000000
--- a/code/game/turfs/floors/natural/natural_chlorine.dm
+++ /dev/null
@@ -1,16 +0,0 @@
-/turf/floor/natural/chlorine_sand
- name = "chlorinated sand"
- desc = "Sand that has been heavily contaminated by chlorine."
- icon = 'icons/turf/flooring/chlorine_sand.dmi'
- possible_states = 11
- icon_edge_layer = EXT_EDGE_CHLORINE_SAND
- dirt_color = "#d2e0b7"
- footstep_type = /decl/footsteps/sand
- is_fundament_turf = TRUE
- material = /decl/material/solid/sand
-
-/turf/floor/natural/chlorine_sand/marsh
- name = "chlorine marsh"
- desc = "A pool of noxious liquid chlorine. It's full of silt and plant matter."
- reagent_type = /decl/material/gas/chlorine
- height = -(FLUID_SHALLOW)
diff --git a/code/game/turfs/floors/natural/natural_dirt.dm b/code/game/turfs/floors/natural/natural_dirt.dm
deleted file mode 100644
index 198472c41ce..00000000000
--- a/code/game/turfs/floors/natural/natural_dirt.dm
+++ /dev/null
@@ -1,25 +0,0 @@
-/turf/floor/natural/dirt
- name = "dirt"
- desc = "A flat expanse of dry, cracked earth."
- icon = 'icons/turf/flooring/dirt.dmi'
- icon_edge_layer = EXT_EDGE_DIRT
- color = "#41311b"
- base_color = "#41311b"
- footstep_type = /decl/footsteps/asteroid
- is_fundament_turf = TRUE
- material = /decl/material/solid/soil
- turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
-
-/turf/floor/natural/dirt/get_plant_growth_rate()
- return 1
-
-/turf/floor/natural/dirt/fluid_act(var/datum/reagents/fluids)
- if(fluids?.total_volume < FLUID_PUDDLE)
- return ..()
- var/turf/new_turf = ChangeTurf(/turf/floor/natural/mud, keep_air = TRUE, keep_height = TRUE)
- return new_turf.fluid_act(fluids)
-
-/turf/floor/natural/dirt/drop_diggable_resources()
- if(get_physical_height() > -(FLUID_DEEP) && prob(10))
- new /obj/item/food/worm(src)
- return ..()
diff --git a/code/game/turfs/floors/natural/natural_grass.dm b/code/game/turfs/floors/natural/natural_grass.dm
deleted file mode 100644
index e6e2c5fc8ab..00000000000
--- a/code/game/turfs/floors/natural/natural_grass.dm
+++ /dev/null
@@ -1,79 +0,0 @@
-/turf/floor/natural/grass
- name = "grass"
- desc = "A patch of grass, growing steadily and healthily."
- possible_states = 1
- icon = 'icons/turf/flooring/grass.dmi'
- footstep_type = /decl/footsteps/grass
- icon_edge_layer = EXT_EDGE_GRASS
- icon_has_corners = TRUE
- color = "#5e7a3b"
- base_color = "#5e7a3b"
- turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
- material = /decl/material/solid/organic/plantmatter/grass
-
-/turf/floor/natural/grass/get_plant_growth_rate()
- return 1.2 // Shouldn't really matter since you can't plant on grass, it turns to dirt first.
-
-/turf/floor/natural/grass/wild
- name = "wild grass"
- desc = "Tall, lush grass that reaches past your ankles."
- possible_states = null
- icon = 'icons/turf/flooring/wildgrass.dmi'
- icon_edge_layer = EXT_EDGE_GRASS_WILD
- footstep_type = /decl/footsteps/grass
- color = "#5e7a3b"
- base_color = "#5e7a3b"
-
-/turf/floor/natural/grass/wild/get_movable_alpha_mask_state(atom/movable/mover)
- . = ..() || "mask_grass"
-
-/obj/item/stack/material/bundle/grass
- drying_wetness = 60
- dried_type = /obj/item/stack/material/bundle/grass/dry
- material = /decl/material/solid/organic/plantmatter/grass
- color = /decl/material/solid/organic/plantmatter/grass::color
- is_spawnable_type = TRUE
-
-/obj/item/stack/material/bundle/grass/dry
- drying_wetness = null
- dried_type = null
- material = /decl/material/solid/organic/plantmatter/grass/dry
- color = /decl/material/solid/organic/plantmatter/grass/dry::color
-
-/turf/floor/natural/grass/wild/attackby(obj/item/W, mob/user)
- if(IS_KNIFE(W) && !istype(flooring))
- if(W.do_tool_interaction(TOOL_KNIFE, user, src, 3 SECONDS, start_message = "harvesting", success_message = "harvesting"))
- if(QDELETED(src) || !istype(src, /turf/floor/natural/grass/wild))
- return TRUE
- new /obj/item/stack/material/bundle/grass(src, rand(2,5))
- ChangeTurf(/turf/floor/natural/grass, keep_air = TRUE)
- return TRUE
- return ..()
-
-/turf/floor/natural/grass/wild/Initialize(mapload, no_update_icon)
- . = ..()
- //It's possible we're created on a level that's not a planet!
- var/datum/planetoid_data/P = SSmapping.planetoid_data_by_z[z]
- var/grass_color = P?.get_grass_color()
- if(grass_color)
- color = grass_color
-
-/turf/floor/natural/grass/wild/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- // smoothly scale between 1/5 chance to scorch at ignition_point and 100% chance to scorch at ignition_point * 4
- if(temperature >= material.ignition_point && prob(20 + temperature * 80 / (material.ignition_point * 4)))
- handle_melting()
- return ..()
-
-/turf/floor/natural/grass/wild/handle_melting(list/meltable_materials)
- . = ..()
- ChangeTurf(/turf/floor/natural/scorched)
-
-/turf/floor/natural/scorched
- name = "scorched ground"
- desc = "What was once lush grass has been reduced to burnt ashes."
- icon = 'icons/turf/flooring/wildgrass.dmi'
- icon_state = "scorched"
- possible_states = null
- footstep_type = /decl/footsteps/asteroid // closest we have to "stepping on carbonized grass"
- material = /decl/material/solid/carbon
- turf_flags = TURF_FLAG_BACKGROUND
diff --git a/code/game/turfs/floors/natural/natural_ice.dm b/code/game/turfs/floors/natural/natural_ice.dm
deleted file mode 100644
index 93a2e517fca..00000000000
--- a/code/game/turfs/floors/natural/natural_ice.dm
+++ /dev/null
@@ -1,48 +0,0 @@
-/turf/floor/natural/ice
- name = "ice"
- desc = "A sheet of smooth, slick ice. Be careful not to slip..."
- icon = 'icons/turf/flooring/ice.dmi'
- footstep_type = /decl/footsteps/plating
- base_color = COLOR_LIQUID_WATER
- color = COLOR_LIQUID_WATER
- material = /decl/material/solid/ice
- can_engrave = TRUE
-
-/turf/floor/natural/ice/Initialize()
- . = ..()
- update_icon()
-
-/turf/floor/natural/ice/on_update_icon()
- . = ..()
- var/image/I = image(icon, "shine")
- I.appearance_flags |= RESET_COLOR
- add_overlay(I)
-
-/turf/floor/natural/snow
- name = "snow"
- desc = "Let it snow, let it snow, let it snow..."
- icon = 'icons/turf/flooring/snow.dmi'
- icon_edge_layer = EXT_EDGE_SNOW
- footstep_type = /decl/footsteps/snow
- possible_states = 13
- dirt_color = "#e3e7e8"
- material = /decl/material/solid/ice/snow
-
-/turf/floor/natural/snow/get_base_movement_delay(travel_dir, mob/mover)
- . = ..()
- if(mover)
- var/obj/item/clothing/shoes/shoes = mover.get_equipped_item(slot_shoes_str)
- if(shoes)
- . += shoes.snow_slowdown_mod
- var/decl/species/my_species = mover.get_species()
- if(my_species)
- . += my_species.snow_slowdown_mod
- . = max(., 0)
-
-/turf/floor/natural/snow/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- handle_melting()
- return ..()
-
-/turf/floor/natural/snow/handle_melting(list/meltable_materials)
- . = ..()
- ChangeTurf(/turf/floor/natural/ice, keep_air = TRUE, keep_height = TRUE)
diff --git a/code/game/turfs/floors/natural/natural_lava.dm b/code/game/turfs/floors/natural/natural_lava.dm
deleted file mode 100644
index 30889dec344..00000000000
--- a/code/game/turfs/floors/natural/natural_lava.dm
+++ /dev/null
@@ -1,50 +0,0 @@
-/turf/floor/natural/lava
- name = "lava"
- desc = "Incredibly hot molten rock. You can feel the heat radiating even from a distance."
- icon = 'icons/turf/flooring/lava.dmi'
- movement_delay = 4
- dirt_color = COLOR_GRAY20
- footstep_type = /decl/footsteps/lava
- is_fundament_turf = TRUE
- material = /decl/material/solid/stone/basalt // TODO: inherent turf temperature
- var/list/victims
-
-/turf/floor/natural/lava/Initialize()
- . = ..()
- set_light(2, l_color = LIGHT_COLOR_LAVA)
-
-/turf/floor/natural/lava/Destroy()
- STOP_PROCESSING(SSobj, src)
- . = ..()
-
-/turf/floor/natural/lava/Entered(atom/movable/AM)
- ..()
- if(locate(/obj/structure/catwalk/) in src)
- return
- var/mob/living/L = AM
- if (istype(L) && L.can_overcome_gravity())
- return
- if(AM.is_burnable())
- LAZYADD(victims, weakref(AM))
- START_PROCESSING(SSobj, src)
-
-/turf/floor/natural/lava/Exited(atom/movable/AM)
- . = ..()
- LAZYREMOVE(victims, weakref(AM))
-
-/turf/floor/natural/lava/Process()
- if(locate(/obj/structure/catwalk/) in src)
- victims = null
- return PROCESS_KILL
- for(var/weakref/W in victims)
- var/atom/movable/AM = W.resolve()
- if (AM == null || get_turf(AM) != src || AM.is_burnable() == FALSE)
- victims -= W
- continue
- var/datum/gas_mixture/environment = return_air()
- var/pressure = environment.return_pressure()
- var/destroyed = AM.lava_act(environment, 5000 + environment.temperature, pressure)
- if(destroyed == TRUE)
- victims -= W
- if(!LAZYLEN(victims))
- return PROCESS_KILL
diff --git a/code/game/turfs/floors/natural/natural_mud.dm b/code/game/turfs/floors/natural/natural_mud.dm
deleted file mode 100644
index 2f681c8d88b..00000000000
--- a/code/game/turfs/floors/natural/natural_mud.dm
+++ /dev/null
@@ -1,78 +0,0 @@
-/turf/floor/natural/clay
- name = "clay"
- desc = "Thick, claggy clay."
- icon = 'icons/turf/flooring/mud_light.dmi'
- icon_edge_layer = EXT_EDGE_CLAY
- footstep_type = /decl/footsteps/mud
- is_fundament_turf = TRUE
- material = /decl/material/solid/clay
- turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
-
-/turf/floor/natural/clay/drop_diggable_resources()
- if(get_physical_height() >= -(FLUID_DEEP) && prob(15))
- new /obj/item/rock/flint(src)
- return ..()
-
-// the internet tells me clay holds water well and is full of nutrients plants crave
-/turf/floor/natural/clay/get_plant_growth_rate()
- return 1.2
-
-/turf/floor/natural/clay/flooded
- flooded = /decl/material/liquid/water
-
-/turf/floor/natural/mud
- name = "mud"
- desc = "Thick, waterlogged mud."
- icon = 'icons/turf/flooring/mud_dark.dmi'
- icon_edge_layer = EXT_EDGE_MUD
- footstep_type = /decl/footsteps/mud
- is_fundament_turf = TRUE
- material = /decl/material/solid/soil
- turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
-
-/turf/floor/natural/mud/drop_diggable_resources()
- if(get_physical_height() > -(FLUID_DEEP) && prob(15))
- new /obj/item/food/worm(src)
- return ..()
-
-/turf/floor/natural/mud/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- // scaling taken from /turf/floor/natural/grass/wild/fire_act
- // smoothly scale between 1/5 chance to scorch at the boiling point of water and 100% chance to scorch at boiling point * 4
- if(!reagents?.total_volume && temperature >= /decl/material/liquid/water::boiling_point && prob(20 + temperature * 80 / (/decl/material/liquid/water::boiling_point * 4)))
- ChangeTurf(/turf/floor/natural/dry, keep_air = TRUE, keep_height = TRUE)
- return
- return ..()
-
-/turf/floor/natural/mud/get_plant_growth_rate()
- return 1.1
-
-/turf/floor/natural/mud/water
- color = COLOR_SKY_BLUE
- reagent_type = /decl/material/liquid/water
- height = -(FLUID_SHALLOW)
-
-/turf/floor/natural/mud/water/deep
- color = COLOR_BLUE
- height = -(FLUID_DEEP)
-
-/turf/floor/natural/mud/flooded
- flooded = /decl/material/liquid/water
-
-/turf/floor/natural/dry
- name = "dry mud"
- desc = "Should have stayed hydrated."
- dirt_color = "#ae9e66"
- icon = 'icons/turf/flooring/seafloor.dmi'
- is_fundament_turf = TRUE
- material = /decl/material/solid/soil
-
-// Just wet the damn dirt first!!
-/turf/floor/natural/dry/get_plant_growth_rate()
- return 0.0
-
-/turf/floor/natural/dry/fluid_act(datum/reagents/fluids)
- if(fluids?.total_volume < FLUID_PUDDLE)
- return ..()
- var/turf/new_turf = ChangeTurf(/turf/floor/natural/mud, keep_air = TRUE, keep_height = TRUE)
- return new_turf.fluid_act(fluids)
-
diff --git a/code/game/turfs/floors/natural/natural_rock.dm b/code/game/turfs/floors/natural/natural_rock.dm
deleted file mode 100644
index 2053c558076..00000000000
--- a/code/game/turfs/floors/natural/natural_rock.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-/turf/floor/natural/rock
- name = "rock"
- desc = "A patch of rough, rocky ground."
- icon = 'icons/turf/flooring/rock.dmi'
- icon_edge_layer = EXT_EDGE_VOLCANIC
- is_fundament_turf = TRUE
- can_engrave = TRUE
-
-/turf/floor/natural/rock/Initialize(mapload, no_update_icon)
- material = material || get_strata_material_type() || /decl/material/solid/stone/sandstone
- . = ..()
-
-/turf/floor/natural/rock/update_from_material()
- if(istype(material))
- name = "[material.adjective_name] [initial(name)]"
- base_color = material.color
- else
- name = initial(name)
- base_color = initial(base_color)
- dirt_color = base_color
- color = base_color
-
-/turf/floor/natural/rock/volcanic
- name = "volcanic floor"
- color = COLOR_DARK_GRAY
- strata_override = /decl/strata/igneous
- material = /decl/material/solid/stone/basalt
-
-/turf/floor/natural/rock/basalt
- color = COLOR_DARK_GRAY
- material = /decl/material/solid/stone/basalt
diff --git a/code/game/turfs/floors/natural/natural_sand.dm b/code/game/turfs/floors/natural/natural_sand.dm
deleted file mode 100644
index 2bdb8d380b8..00000000000
--- a/code/game/turfs/floors/natural/natural_sand.dm
+++ /dev/null
@@ -1,44 +0,0 @@
-/turf/floor/natural/sand
- name = "sand"
- desc = "It's coarse and gets everywhere."
- dirt_color = "#ae9e66"
- footstep_type = /decl/footsteps/sand
- icon = 'icons/turf/flooring/sand.dmi'
- icon_edge_layer = EXT_EDGE_SAND
- icon_has_corners = TRUE
- possible_states = 4
- turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
- material = /decl/material/solid/sand
- is_fundament_turf = TRUE
-
-/turf/floor/natural/sand/get_plant_growth_rate()
- return 0.5
-
-/turf/floor/natural/sand/drop_diggable_resources()
- if(get_physical_height() >= -(FLUID_DEEP) && prob(15))
- new /obj/item/rock/flint(src)
- return ..()
-
-/turf/floor/natural/sand/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- if((temperature > T0C + 1700 && prob(5)) || temperature > T0C + 3000)
- handle_melting()
- return ..()
-
-/turf/floor/natural/sand/water
- color = COLOR_SKY_BLUE
- reagent_type = /decl/material/liquid/water
- height = -(FLUID_SHALLOW)
-
-/turf/floor/natural/sand/water/deep
- color = COLOR_BLUE
- height = -(FLUID_DEEP)
-
-/turf/floor/natural/sand/handle_melting(list/meltable_materials)
- . = ..()
- if(icon_state != "glass")
- set_turf_materials(/decl/material/solid/glass, skip_update = TRUE)
- SetName("molten silica")
- desc = "A glassed patch of sand."
- icon_state = "glass"
- icon_edge_layer = -1
- clear_diggable_resources()
diff --git a/code/game/turfs/floors/natural/natural_seafloor.dm b/code/game/turfs/floors/natural/natural_seafloor.dm
deleted file mode 100644
index af3e7fe1286..00000000000
--- a/code/game/turfs/floors/natural/natural_seafloor.dm
+++ /dev/null
@@ -1,21 +0,0 @@
-/turf/floor/natural/seafloor
- name = "sea floor"
- gender = NEUTER
- desc = "A thick layer of silt and debris from above."
- icon = 'icons/turf/flooring/seafloor.dmi'
- icon_edge_layer = EXT_EDGE_SEAFLOOR
- turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
- material = /decl/material/solid/sand
- is_fundament_turf = TRUE
-
-/turf/floor/natural/seafloor/get_plant_growth_rate()
- return 0.8
-
-/turf/floor/natural/seafloor/flooded
- flooded = /decl/material/liquid/water
- color = COLOR_LIQUID_WATER
-
-/turf/floor/natural/seafloor/Initialize()
- if(prob(20))
- LAZYADD(decals, image("asteroid[rand(0,9)]", 'icons/turf/mining_decals.dmi'))
- . = ..()
diff --git a/code/game/turfs/floors/natural/natural_shrouded.dm b/code/game/turfs/floors/natural/natural_shrouded.dm
deleted file mode 100644
index b3daada9389..00000000000
--- a/code/game/turfs/floors/natural/natural_shrouded.dm
+++ /dev/null
@@ -1,19 +0,0 @@
-/turf/floor/natural/shrouded
- name = "packed sand"
- icon = 'icons/turf/flooring/shrouded.dmi'
- desc = "Sand that has been packed in to solid earth."
- dirt_color = "#3e3960"
- possible_states = 8
- turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID
- material = /decl/material/solid/sand
- is_fundament_turf = TRUE
-
-/turf/floor/natural/shrouded/get_plant_growth_rate()
- return 0.5
-
-/turf/floor/natural/shrouded/tar
- name = "tar"
- desc = "A pool of viscous and sticky tar."
- movement_delay = 12
- reagent_type = /decl/material/liquid/tar
- height = -(FLUID_SHALLOW)
diff --git a/code/game/turfs/floors/subtypes/floor_carpet.dm b/code/game/turfs/floors/subtypes/floor_carpet.dm
index 879743c7783..6911f3500e5 100644
--- a/code/game/turfs/floors/subtypes/floor_carpet.dm
+++ b/code/game/turfs/floors/subtypes/floor_carpet.dm
@@ -3,44 +3,44 @@
name = "brown carpet"
icon = 'icons/turf/flooring/carpet.dmi'
icon_state = "brown"
- initial_flooring = /decl/flooring/carpet
+ _flooring = /decl/flooring/carpet
/turf/floor/carpet/blue
name = "blue carpet"
icon_state = "blue1"
- initial_flooring = /decl/flooring/carpet/blue
+ _flooring = /decl/flooring/carpet/blue
/turf/floor/carpet/blue2
name = "pale blue carpet"
icon_state = "blue2"
- initial_flooring = /decl/flooring/carpet/blue2
+ _flooring = /decl/flooring/carpet/blue2
/turf/floor/carpet/blue3
name = "sea blue carpet"
icon_state = "blue3"
- initial_flooring = /decl/flooring/carpet/blue3
+ _flooring = /decl/flooring/carpet/blue3
/turf/floor/carpet/magenta
name = "magenta carpet"
icon_state = "magenta"
- initial_flooring = /decl/flooring/carpet/magenta
+ _flooring = /decl/flooring/carpet/magenta
/turf/floor/carpet/purple
name = "purple carpet"
icon_state = "purple"
- initial_flooring = /decl/flooring/carpet/purple
+ _flooring = /decl/flooring/carpet/purple
/turf/floor/carpet/orange
name = "orange carpet"
icon_state = "orange"
- initial_flooring = /decl/flooring/carpet/orange
+ _flooring = /decl/flooring/carpet/orange
/turf/floor/carpet/green
name = "green carpet"
icon_state = "green"
- initial_flooring = /decl/flooring/carpet/green
+ _flooring = /decl/flooring/carpet/green
/turf/floor/carpet/red
name = "red carpet"
icon_state = "red"
- initial_flooring = /decl/flooring/carpet/red
+ _flooring = /decl/flooring/carpet/red
diff --git a/code/game/turfs/floors/subtypes/floor_circuit.dm b/code/game/turfs/floors/subtypes/floor_circuit.dm
index 8bf154871e8..7f934481deb 100644
--- a/code/game/turfs/floors/subtypes/floor_circuit.dm
+++ b/code/game/turfs/floors/subtypes/floor_circuit.dm
@@ -2,7 +2,7 @@
name = "mainframe floor"
icon = 'icons/turf/flooring/circuit.dmi'
icon_state = "bcircuit"
- initial_flooring = /decl/flooring/reinforced/circuit
+ _flooring = /decl/flooring/reinforced/circuit
light_range = 2
light_power = 3
light_color = COLOR_BLUE
@@ -16,7 +16,7 @@
name = "mainframe floor"
icon = 'icons/turf/flooring/circuit.dmi'
icon_state = "gcircuit"
- initial_flooring = /decl/flooring/reinforced/circuit/green
+ _flooring = /decl/flooring/reinforced/circuit/green
light_range = 2
light_power = 3
light_color = COLOR_GREEN
@@ -33,7 +33,7 @@
name = "mainframe floor"
icon = 'icons/turf/flooring/circuit.dmi'
icon_state = "rcircuit"
- initial_flooring = /decl/flooring/reinforced/circuit/red
+ _flooring = /decl/flooring/reinforced/circuit/red
light_range = 2
light_power = 2
light_color = COLOR_RED
diff --git a/code/game/turfs/floors/subtypes/floor_concrete.dm b/code/game/turfs/floors/subtypes/floor_concrete.dm
index d0a5362b8ee..2c1380031ff 100644
--- a/code/game/turfs/floors/subtypes/floor_concrete.dm
+++ b/code/game/turfs/floors/subtypes/floor_concrete.dm
@@ -1,19 +1,13 @@
/turf/floor/concrete
- name = "concrete"
- desc = "A flat expanse of artificial stone-like artificial material."
- icon = 'icons/turf/flooring/concrete.dmi'
- icon_state = "inset"
- initial_flooring = null
-// material = /decl/material/solid/stone/concrete
-
- base_name = "concrete"
- base_desc = "A flat expanse of artificial stone-like artificial material."
- base_icon = 'icons/turf/flooring/concrete.dmi'
- base_icon_state = "inset"
+ name = "concrete"
+ icon = 'icons/turf/flooring/concrete.dmi'
+ icon_state = "inset"
+ _flooring = /decl/flooring/concrete
+ _base_flooring = /decl/flooring/dirt
+ floor_material = /decl/material/solid/stone/concrete
/turf/floor/concrete/smooth
icon_state = "concrete"
- base_icon_state = "concrete"
/turf/floor/concrete/flooded
flooded = /decl/material/liquid/water
@@ -21,11 +15,8 @@
/turf/floor/concrete/reinforced
name = "reinforced concrete"
- desc = "Stone-like artificial material. It has been reinforced with an unknown compound."
icon_state = "hexacrete"
- base_name = "reinforced concrete"
- base_desc = "Stone-like artificial material. It has been reinforced with an unknown compound."
- base_icon_state = "hexacrete"
+ _flooring = /decl/flooring/concrete/reinforced
/turf/floor/concrete/reinforced/damaged/LateInitialize()
. = ..()
@@ -35,5 +26,4 @@
name = "asphalt"
color = COLOR_GRAY40
icon_state = "concrete"
- base_color = COLOR_GRAY40
- base_icon_state = "concrete"
+ _flooring = /decl/flooring/concrete/asphalt
diff --git a/code/game/turfs/floors/subtypes/floor_misc.dm b/code/game/turfs/floors/subtypes/floor_misc.dm
index 78d48815a65..437b1cb3398 100644
--- a/code/game/turfs/floors/subtypes/floor_misc.dm
+++ b/code/game/turfs/floors/subtypes/floor_misc.dm
@@ -2,7 +2,7 @@
name = "lino"
icon = 'icons/turf/flooring/linoleum.dmi'
icon_state = "lino"
- initial_flooring = /decl/flooring/linoleum
+ _flooring = /decl/flooring/linoleum
/turf/floor/airless
name = "airless plating"
@@ -13,45 +13,46 @@
name = "crystal floor"
icon = 'icons/turf/flooring/crystal.dmi'
icon_state = "crystal"
- initial_flooring = /decl/flooring/crystal
+ _flooring = /decl/flooring/crystal
/turf/floor/glass
name = "glass floor"
icon = 'icons/turf/flooring/glass.dmi'
icon_state = "glass"
- initial_flooring = /decl/flooring/glass
+ _flooring = /decl/flooring/glass
/turf/floor/glass/boro
- initial_flooring = /decl/flooring/glass/boro
+ _flooring = /decl/flooring/glass/boro
/turf/floor/pool
name = "pool floor"
icon = 'icons/turf/flooring/pool.dmi'
icon_state = "pool"
- initial_flooring = /decl/flooring/pool
+ height = -(FLUID_OVER_MOB_HEAD) - 50
+ _flooring = /decl/flooring/pool
/turf/floor/pool/deep
- name = "deep pool floor"
- icon = 'icons/turf/flooring/pool.dmi'
- icon_state = "pool"
- initial_flooring = /decl/flooring/pool/deep
+ height = -FLUID_DEEP - 50
/turf/floor/fake_grass
name = "grass patch"
icon = 'icons/turf/flooring/fakegrass.dmi'
icon_state = "grass0"
- initial_flooring = /decl/flooring/fake_grass
+ _flooring = /decl/flooring/grass/fake
/turf/floor/woven
name = "floor"
icon = 'icons/turf/flooring/woven.dmi'
icon_state = "woven"
color = COLOR_BEIGE
- initial_flooring = /decl/flooring/woven
+ _flooring = /decl/flooring/woven
/turf/floor/straw
name = "loose straw"
- // TEMPORARY ICON, CHANGE LATER
icon = 'icons/turf/flooring/wildgrass.dmi'
- icon_state = "0"
- color = COLOR_WHEAT
\ No newline at end of file
+ icon_state = "wildgrass"
+ color = COLOR_WHEAT
+ _flooring = /decl/flooring/straw
+
+// Defining this here as a dummy mapping shorthand so mappers can search for 'plating'.
+/turf/floor/plating
diff --git a/code/game/turfs/floors/subtypes/floor_natural.dm b/code/game/turfs/floors/subtypes/floor_natural.dm
new file mode 100644
index 00000000000..e1620e5b899
--- /dev/null
+++ b/code/game/turfs/floors/subtypes/floor_natural.dm
@@ -0,0 +1,136 @@
+/turf/floor/barren
+ name = "ground"
+ icon = 'icons/turf/flooring/barren.dmi'
+ icon_state = "barren"
+ _base_flooring = /decl/flooring/barren
+
+/turf/floor/dirt
+ name = "dirt"
+ icon = 'icons/turf/flooring/dirt.dmi'
+ icon_state = "dirt"
+ color = "#41311b"
+ _base_flooring = /decl/flooring/dirt
+
+/turf/floor/dirt/walnut
+ name = "wooden floor"
+ icon = 'icons/turf/flooring/wood.dmi'
+ icon_state = "wood"
+ color = /decl/material/solid/organic/wood/walnut::color
+ _flooring = /decl/flooring/wood/walnut
+
+/turf/floor/chlorine_sand
+ name = "chlorinated sand"
+ icon = 'icons/turf/flooring/chlorine_sand.dmi'
+ icon_state = "chlorine0"
+ _base_flooring = /decl/flooring/sand/chlorine
+
+/turf/floor/chlorine_sand/marsh
+ name = "chlorine marsh"
+ fill_reagent_type = /decl/material/gas/chlorine
+ _base_flooring = /decl/flooring/sand/chlorine/marsh
+ height = -(FLUID_SHALLOW)
+
+/turf/floor/lava
+ name = "lava"
+ icon = 'icons/turf/flooring/lava.dmi'
+ icon_state = "lava"
+ _base_flooring = /decl/flooring/lava
+
+/turf/floor/grass
+ name = "grass"
+ icon = 'icons/turf/flooring/grass.dmi'
+ icon_state = "grass0"
+ color = "#5e7a3b"
+ _flooring = /decl/flooring/grass
+ _base_flooring = /decl/flooring/dirt
+
+/turf/floor/grass/wild
+ name = "wild grass"
+ icon = 'icons/turf/flooring/wildgrass.dmi'
+ icon_state = "wildgrass"
+ _flooring = /decl/flooring/grass/wild
+ _base_flooring = /decl/flooring/dirt
+
+/turf/floor/ice
+ name = "ice"
+ icon = 'icons/turf/flooring/ice.dmi'
+ icon_state = "ice"
+ color = COLOR_LIQUID_WATER
+ _flooring = /decl/flooring/ice
+ _base_flooring = /decl/flooring/dirt
+
+/turf/floor/snow
+ name = "snow"
+ icon = 'icons/turf/flooring/snow.dmi'
+ icon_state = "snow0"
+ _flooring = /decl/flooring/snow
+ _base_flooring = /decl/flooring/dirt
+
+/turf/floor/clay
+ name = "clay"
+ icon = 'icons/turf/flooring/clay.dmi'
+ icon_state = "clay"
+ _base_flooring = /decl/flooring/clay
+
+/turf/floor/clay/flooded
+ flooded = /decl/material/liquid/water
+
+/turf/floor/mud
+ name = "mud"
+ icon = 'icons/turf/flooring/mud.dmi'
+ icon_state = "mud"
+ _base_flooring = /decl/flooring/mud
+
+/turf/floor/mud/water
+ color = COLOR_SKY_BLUE
+ fill_reagent_type = /decl/material/liquid/water
+ height = -(FLUID_SHALLOW)
+
+/turf/floor/mud/water/deep
+ color = COLOR_BLUE
+ height = -(FLUID_DEEP)
+
+/turf/floor/mud/flooded
+ flooded = /decl/material/liquid/water
+
+/turf/floor/dry
+ name = "dry mud"
+ icon = 'icons/turf/flooring/seafloor.dmi'
+ icon_state = "seafloor"
+ _base_flooring = /decl/flooring/dry_mud
+
+/turf/floor/rock/sand
+ name = "sand"
+ icon = 'icons/turf/flooring/sand.dmi'
+ icon_state = "sand0"
+ color = "#ae9e66"
+ _flooring = /decl/flooring/sand
+
+/turf/floor/rock/sand/water
+ color = COLOR_SKY_BLUE
+ fill_reagent_type = /decl/material/liquid/water
+ height = -(FLUID_SHALLOW)
+
+/turf/floor/rock/sand/water/deep
+ color = COLOR_BLUE
+ height = -(FLUID_DEEP)
+
+/turf/floor/seafloor
+ name = "sea floor"
+ icon = 'icons/turf/flooring/seafloor.dmi'
+ icon_state = "seafloor"
+ _base_flooring = /decl/flooring/seafloor
+
+/turf/floor/seafloor/flooded
+ flooded = /decl/material/liquid/water
+ color = COLOR_LIQUID_WATER
+
+/turf/floor/shrouded
+ name = "packed sand"
+ icon = 'icons/turf/flooring/shrouded.dmi'
+ icon_state = "shrouded0"
+ _base_flooring = /decl/flooring/shrouded
+
+/turf/floor/shrouded/tar
+ height = -(FLUID_SHALLOW)
+ fill_reagent_type = /decl/material/liquid/tar
diff --git a/code/game/turfs/floors/subtypes/floor_path.dm b/code/game/turfs/floors/subtypes/floor_path.dm
index 13e4018bf96..8a984656793 100644
--- a/code/game/turfs/floors/subtypes/floor_path.dm
+++ b/code/game/turfs/floors/subtypes/floor_path.dm
@@ -1,24 +1,18 @@
-// These need conversion to flooring decls but I am leaving it till after this PR.
-/turf/floor/natural/path
- name = "path"
- gender = NEUTER
- desc = "A cobbled path made of loose stones."
- color = COLOR_GRAY
- base_color = COLOR_GRAY
- icon_edge_layer = EXT_EDGE_PATH
- icon = 'icons/turf/flooring/legacy/cobblestone.dmi'
- icon_state = "0"
- material = /decl/material/solid/stone/sandstone
- neighbour_type = /turf/floor/natural/path
-// initial_flooring = /decl/flooring/path/cobblestone
- // If null, this is just skipped.
- var/paving_adjective = "cobbled"
- var/paver_adjective = "loose"
- // This one should never be null.
- var/paver_noun = "stones"
-/turf/floor/natural/path/Initialize(mapload, no_update_icon)
+/turf/floor/path
+ name = "path"
+ gender = NEUTER
+ desc = "A cobbled path made of loose stones."
+ color = COLOR_GRAY
+ icon = 'icons/turf/flooring/path.dmi'
+ icon_state = "cobble"
+ _flooring = /decl/flooring/path/cobblestone
+ floor_material = /decl/material/solid/stone/sandstone
+ _base_flooring = /decl/flooring/dirt
+
+/turf/floor/path/Initialize(mapload, no_update_icon)
. = ..()
+ set_turf_materials(floor_material || get_strata_material_type() || /decl/material/solid/stone/sandstone, skip_update = no_update_icon)
if(mapload && is_outside() && prob(20))
var/image/moss = image('icons/effects/decals/plant_remains.dmi', "leafy_bits", DECAL_LAYER)
moss.pixel_x = rand(-6, 6)
@@ -33,71 +27,54 @@
moss.transform = M
LAZYADD(decals, moss)
-/turf/floor/natural/path/update_from_material()
- SetName("[material.adjective_name] [initial(name)]")
- ASSERT(material?.adjective_name)
- ASSERT(paver_noun)
- desc = "[jointext_no_nulls(list("A", paving_adjective, "path made of", paver_adjective, material?.adjective_name, paver_noun), " ")]."
-
-/turf/floor/natural/path/running_bond
- icon = 'icons/turf/flooring/legacy/running_bond.dmi'
- paving_adjective = null
- paver_adjective = "staggered"
- paver_noun = "bricks"
- icon_edge_layer = -1
-// initial_flooring = /decl/flooring/path/running_bond
+/turf/floor/path/running_bond
+ icon_state = "runningbond"
+ _flooring = /decl/flooring/path/running_bond
-/turf/floor/natural/path/herringbone
- icon = 'icons/turf/flooring/legacy/herringbone.dmi'
- paving_adjective = "herringbone"
- paver_adjective = null
- paver_noun = "bricks"
- icon_edge_layer = -1
-// initial_flooring = /decl/flooring/path/herringbone
+/turf/floor/path/herringbone
+ icon_state = "herringbone"
+ _flooring = /decl/flooring/path/herringbone
// Material subtypes.
#define PATH_MATERIAL_SUBTYPES(material_name) \
-/turf/floor/natural/path/##material_name { \
- color = /decl/material/solid/stone/##material_name::color; \
- base_color = /decl/material/solid/stone/##material_name::color; \
- material = /decl/material/solid/stone/##material_name; \
+/turf/floor/path/##material_name { \
+ color = /decl/material/solid/stone/##material_name::color; \
+ floor_material = /decl/material/solid/stone/##material_name; \
} \
-/turf/floor/natural/path/herringbone/##material_name { \
- color = /decl/material/solid/stone/##material_name::color; \
- base_color = /decl/material/solid/stone/##material_name::color; \
- material = /decl/material/solid/stone/##material_name; \
+/turf/floor/path/herringbone/##material_name { \
+ color = /decl/material/solid/stone/##material_name::color; \
+ floor_material = /decl/material/solid/stone/##material_name; \
} \
-/turf/floor/natural/path/running_bond/##material_name { \
- color = /decl/material/solid/stone/##material_name::color; \
- base_color = /decl/material/solid/stone/##material_name::color; \
- material = /decl/material/solid/stone/##material_name; \
+/turf/floor/path/running_bond/##material_name { \
+ color = /decl/material/solid/stone/##material_name::color; \
+ floor_material = /decl/material/solid/stone/##material_name; \
} \
-/turf/floor/natural/path/##material_name/water { \
- color = COLOR_SKY_BLUE; \
- reagent_type = /decl/material/liquid/water; \
- height = -(FLUID_SHALLOW); \
+/turf/floor/path/##material_name/water { \
+ color = COLOR_SKY_BLUE; \
+ fill_reagent_type = /decl/material/liquid/water; \
+ height = -(FLUID_SHALLOW); \
} \
-/turf/floor/natural/path/##material_name/water/deep {\
- color = COLOR_BLUE; \
- height = -(FLUID_DEEP); \
+/turf/floor/path/##material_name/water/deep {\
+ color = COLOR_BLUE; \
+ height = -(FLUID_DEEP); \
} \
-/turf/floor/natural/path/herringbone/##material_name/water { \
- color = COLOR_SKY_BLUE; \
- reagent_type = /decl/material/liquid/water; \
- height = -(FLUID_SHALLOW); \
+/turf/floor/path/herringbone/##material_name/water { \
+ color = COLOR_SKY_BLUE; \
+ fill_reagent_type = /decl/material/liquid/water; \
+ height = -(FLUID_SHALLOW); \
} \
-/turf/floor/natural/path/herringbone/##material_name/water/deep { \
- color = COLOR_BLUE; \
- height = -(FLUID_DEEP); \
+/turf/floor/path/herringbone/##material_name/water/deep { \
+ color = COLOR_BLUE; \
+ height = -(FLUID_DEEP); \
} \
-/turf/floor/natural/path/running_bond/##material_name/water { \
- color = COLOR_SKY_BLUE; \
- reagent_type = /decl/material/liquid/water; \
- height = -(FLUID_SHALLOW); \
+/turf/floor/path/running_bond/##material_name/water { \
+ color = COLOR_SKY_BLUE; \
+ fill_reagent_type = /decl/material/liquid/water; \
+ height = -(FLUID_SHALLOW); \
} \
-/turf/floor/natural/path/running_bond/##material_name/water/deep { \
- color = COLOR_BLUE; \
- height = -(FLUID_DEEP); \
+/turf/floor/path/running_bond/##material_name/water/deep { \
+ color = COLOR_BLUE; \
+ height = -(FLUID_DEEP); \
}
PATH_MATERIAL_SUBTYPES(basalt)
PATH_MATERIAL_SUBTYPES(granite)
diff --git a/code/game/turfs/floors/subtypes/floor_reinforced.dm b/code/game/turfs/floors/subtypes/floor_reinforced.dm
index 9715d8f49b9..60239d44d9c 100644
--- a/code/game/turfs/floors/subtypes/floor_reinforced.dm
+++ b/code/game/turfs/floors/subtypes/floor_reinforced.dm
@@ -2,7 +2,7 @@
name = "reinforced floor"
icon = 'icons/turf/flooring/tiles.dmi'
icon_state = "reinforced"
- initial_flooring = /decl/flooring/reinforced
+ _flooring = /decl/flooring/reinforced
/turf/floor/reinforced/airless
initial_gas = null
diff --git a/code/game/turfs/floors/subtypes/floor_rock.dm b/code/game/turfs/floors/subtypes/floor_rock.dm
new file mode 100644
index 00000000000..de364ec1cc9
--- /dev/null
+++ b/code/game/turfs/floors/subtypes/floor_rock.dm
@@ -0,0 +1,17 @@
+/turf/floor/rock
+ name = "rock floor"
+ icon = 'icons/turf/flooring/rock.dmi'
+ icon_state = "rock"
+ _base_flooring = /decl/flooring/rock
+
+/turf/floor/rock/Initialize(mapload, no_update_icon)
+ . = ..()
+ set_turf_materials(floor_material || get_strata_material_type() || /decl/material/solid/stone/sandstone, skip_update = no_update_icon)
+
+/turf/floor/rock/volcanic
+ name = "volcanic floor"
+ floor_material = /decl/material/solid/stone/basalt
+
+/turf/floor/rock/basalt
+ color = /decl/material/solid/stone/basalt::color
+ floor_material = /decl/material/solid/stone/basalt
diff --git a/code/game/turfs/floors/subtypes/floor_shuttle.dm b/code/game/turfs/floors/subtypes/floor_shuttle.dm
index f8e05f25f3a..10b72a1f105 100644
--- a/code/game/turfs/floors/subtypes/floor_shuttle.dm
+++ b/code/game/turfs/floors/subtypes/floor_shuttle.dm
@@ -2,36 +2,32 @@
name = "shuttle floor"
icon = 'icons/turf/flooring/shuttle.dmi'
desc = "A synthetic floor plate commonly seen in shuttles and other vehicles."
- base_name = "shuttle floor"
- base_desc = "A synthetic floor plate commonly seen in shuttles and other vehicles."
- base_icon = 'icons/turf/flooring/shuttle.dmi'
- base_icon_state = "plating"
- initial_flooring = null
+ _flooring = /decl/flooring/reinforced/shuttle
/turf/floor/shuttle/blue
icon_state = "floor"
- initial_flooring = /decl/flooring/reinforced/shuttle/blue
+ _flooring = /decl/flooring/reinforced/shuttle/blue
/turf/floor/shuttle/yellow
icon_state = "floor2"
- initial_flooring = /decl/flooring/reinforced/shuttle/yellow
+ _flooring = /decl/flooring/reinforced/shuttle/yellow
/turf/floor/shuttle/white
icon_state = "floor3"
- initial_flooring = /decl/flooring/reinforced/shuttle/white
+ _flooring = /decl/flooring/reinforced/shuttle/white
/turf/floor/shuttle/red
icon_state = "floor4"
- initial_flooring = /decl/flooring/reinforced/shuttle/red
+ _flooring = /decl/flooring/reinforced/shuttle/red
/turf/floor/shuttle/purple
icon_state = "floor5"
- initial_flooring = /decl/flooring/reinforced/shuttle/purple
+ _flooring = /decl/flooring/reinforced/shuttle/purple
/turf/floor/shuttle/darkred
icon_state = "floor6"
- initial_flooring = /decl/flooring/reinforced/shuttle/darkred
+ _flooring = /decl/flooring/reinforced/shuttle/darkred
/turf/floor/shuttle/black
icon_state = "floor7"
- initial_flooring = /decl/flooring/reinforced/shuttle/black
+ _flooring = /decl/flooring/reinforced/shuttle/black
diff --git a/code/game/turfs/floors/subtypes/floor_static.dm b/code/game/turfs/floors/subtypes/floor_static.dm
index 48f8e90ca3f..d55afe9df24 100644
--- a/code/game/turfs/floors/subtypes/floor_static.dm
+++ b/code/game/turfs/floors/subtypes/floor_static.dm
@@ -5,7 +5,7 @@
name = "floor"
icon = 'icons/turf/flooring/tiles.dmi'
icon_state = "steel"
- initial_flooring = null
+ _flooring = null
footstep_type = /decl/footsteps/plating
is_outside = OUTSIDE_AREA
@@ -20,7 +20,7 @@
/turf/floor/fixed/is_plating()
return 0
-/turf/floor/fixed/set_flooring(var/decl/flooring/newflooring, skip_update)
+/turf/floor/fixed/set_flooring(var/decl/flooring/newflooring, skip_update, place_product)
return
/turf/floor/fixed/alium
diff --git a/code/game/turfs/floors/subtypes/floor_tiled.dm b/code/game/turfs/floors/subtypes/floor_tiled.dm
index 896409b9850..2adff8faa9b 100644
--- a/code/game/turfs/floors/subtypes/floor_tiled.dm
+++ b/code/game/turfs/floors/subtypes/floor_tiled.dm
@@ -3,17 +3,17 @@
name = "floor"
icon = 'icons/turf/flooring/tiles.dmi'
icon_state = "tiled"
- initial_flooring = /decl/flooring/tiling
+ _flooring = /decl/flooring/tiling
/turf/floor/tiled/dark
name = "dark floor"
icon_state = "dark"
- initial_flooring = /decl/flooring/tiling/dark
+ _flooring = /decl/flooring/tiling/dark
/turf/floor/tiled/dark/monotile
name = "floor"
icon_state = "monotiledark"
- initial_flooring = /decl/flooring/tiling/mono/dark
+ _flooring = /decl/flooring/tiling/mono/dark
/turf/floor/tiled/dark/airless
initial_gas = null
@@ -21,17 +21,17 @@
/turf/floor/tiled/white
name = "white floor"
icon_state = "white"
- initial_flooring = /decl/flooring/tiling/white
+ _flooring = /decl/flooring/tiling/white
/turf/floor/tiled/white/monotile
name = "floor"
icon_state = "monotile"
- initial_flooring = /decl/flooring/tiling/mono/white
+ _flooring = /decl/flooring/tiling/mono/white
/turf/floor/tiled/monofloor
name = "floor"
icon_state = "steel_monofloor"
- initial_flooring = /decl/flooring/tiling/mono
+ _flooring = /decl/flooring/tiling/mono
/turf/floor/tiled/white/airless
name = "airless floor"
@@ -41,64 +41,64 @@
/turf/floor/tiled/freezer
name = "tiles"
icon_state = "freezer"
- initial_flooring = /decl/flooring/tiling/freezer
+ _flooring = /decl/flooring/tiling/freezer
/turf/floor/tiled/techmaint
name = "floor"
icon = 'icons/turf/flooring/tiles.dmi'
icon_state = "techmaint"
- initial_flooring = /decl/flooring/tiling/new_tile/techmaint
+ _flooring = /decl/flooring/tiling/new_tile/techmaint
/turf/floor/tiled/monofloor
name = "floor"
icon_state = "steel_monofloor"
- initial_flooring = /decl/flooring/tiling/new_tile/monofloor
+ _flooring = /decl/flooring/tiling/new_tile/monofloor
/turf/floor/tiled/techfloor
name = "floor"
icon = 'icons/turf/flooring/techfloor.dmi'
icon_state = "techfloor_gray"
- initial_flooring = /decl/flooring/tiling/tech
+ _flooring = /decl/flooring/tiling/tech
/turf/floor/tiled/monotile
name = "floor"
icon_state = "steel_monotile"
- initial_flooring = /decl/flooring/tiling/mono
+ _flooring = /decl/flooring/tiling/mono
/turf/floor/tiled/steel_grid
name = "floor"
icon_state = "steel_grid"
- initial_flooring = /decl/flooring/tiling/new_tile/steel_grid
+ _flooring = /decl/flooring/tiling/new_tile/steel_grid
/turf/floor/tiled/steel_ridged
name = "floor"
icon_state = "steel_ridged"
- initial_flooring = /decl/flooring/tiling/new_tile/steel_ridged
+ _flooring = /decl/flooring/tiling/new_tile/steel_ridged
/turf/floor/tiled/old_tile
name = "floor"
icon_state = "tile_full"
- initial_flooring = /decl/flooring/tiling/new_tile
+ _flooring = /decl/flooring/tiling/new_tile
/turf/floor/tiled/old_cargo
name = "floor"
icon_state = "cargo_one_full"
- initial_flooring = /decl/flooring/tiling/new_tile/cargo_one
+ _flooring = /decl/flooring/tiling/new_tile/cargo_one
/turf/floor/tiled/kafel_full
name = "floor"
icon_state = "kafel_full"
- initial_flooring = /decl/flooring/tiling/new_tile/kafel
+ _flooring = /decl/flooring/tiling/new_tile/kafel
/turf/floor/tiled/stone
name = "stone slab floor"
icon_state = "stone"
- initial_flooring = /decl/flooring/tiling/stone
+ _flooring = /decl/flooring/tiling/stone
/turf/floor/tiled/techfloor/grid
name = "floor"
icon_state = "techfloor_grid"
- initial_flooring = /decl/flooring/tiling/tech/grid
+ _flooring = /decl/flooring/tiling/tech/grid
/turf/floor/tiled/airless
name = "airless floor"
diff --git a/code/game/turfs/floors/subtypes/floor_wood.dm b/code/game/turfs/floors/subtypes/floor_wood.dm
index 4f625786a47..89a834a2956 100644
--- a/code/game/turfs/floors/subtypes/floor_wood.dm
+++ b/code/game/turfs/floors/subtypes/floor_wood.dm
@@ -3,28 +3,28 @@
icon = 'icons/turf/flooring/wood.dmi'
icon_state = "wood"
color = /decl/material/solid/organic/wood::color
- initial_flooring = /decl/flooring/wood
+ _flooring = /decl/flooring/wood
/turf/floor/wood/mahogany
color = /decl/material/solid/organic/wood/mahogany::color
- initial_flooring = /decl/flooring/wood/mahogany
+ _flooring = /decl/flooring/wood/mahogany
/turf/floor/wood/maple
color = /decl/material/solid/organic/wood/maple::color
- initial_flooring = /decl/flooring/wood/maple
+ _flooring = /decl/flooring/wood/maple
/turf/floor/wood/ebony
color = /decl/material/solid/organic/wood/ebony::color
- initial_flooring = /decl/flooring/wood/ebony
+ _flooring = /decl/flooring/wood/ebony
/turf/floor/wood/walnut
color = /decl/material/solid/organic/wood/walnut::color
- initial_flooring = /decl/flooring/wood/walnut
+ _flooring = /decl/flooring/wood/walnut
/turf/floor/wood/bamboo
color = /decl/material/solid/organic/wood/bamboo::color
- initial_flooring = /decl/flooring/wood/bamboo
+ _flooring = /decl/flooring/wood/bamboo
/turf/floor/wood/yew
color = /decl/material/solid/organic/wood/yew::color
- initial_flooring = /decl/flooring/wood/yew
+ _flooring = /decl/flooring/wood/yew
diff --git a/code/game/turfs/initialization/combo.dm b/code/game/turfs/initialization/combo.dm
new file mode 100644
index 00000000000..ccd8397683d
--- /dev/null
+++ b/code/game/turfs/initialization/combo.dm
@@ -0,0 +1,19 @@
+/// Runs multiple turf initialisers in sequence.
+/decl/turf_initializer/combo
+ abstract_type = /decl/turf_initializer/combo
+ /// A list of initialisers to run, in sequence.
+ var/list/initialisers
+
+/decl/turf_initializer/combo/Initialize()
+ . = ..()
+ var/list/new_initialisers = list()
+ for(var/initialiser in initialisers)
+ new_initialisers += GET_DECL(initialiser)
+ initialisers = new_initialisers
+ ASSERT(length(initialisers))
+
+/decl/turf_initializer/combo/InitializeTurf(var/turf/tile)
+ if(!istype(tile) || !tile.simulated)
+ return
+ for(var/decl/turf_initializer/initialiser in initialisers)
+ initialiser.InitializeTurf(tile)
\ No newline at end of file
diff --git a/code/game/turfs/initialization/indoors.dm b/code/game/turfs/initialization/indoors.dm
new file mode 100644
index 00000000000..594f52716d4
--- /dev/null
+++ b/code/game/turfs/initialization/indoors.dm
@@ -0,0 +1,94 @@
+// Makes indoor areas dirty and spawns webs in corners.
+/decl/turf_initializer/spiderwebs
+ /// The chance a turf in a corner will attempt to place a web.
+ var/web_probability = 25
+ /// The chance a dormant spiderling will spawn in a placed web.
+ var/spiderling_probability = 5
+ /// The maximum amount of dirt added to a turf.
+ var/min_base_dirt = 0
+ /// The maximum amount of dirt added to a turf.
+ var/max_base_dirt = 40
+ /// The maximum amount of dirt added to each turf per dirty neighbour turf.
+ var/max_dirt_per_turf = 5
+
+
+/decl/turf_initializer/spiderwebs/proc/get_dirt_amount()
+ return rand(min_base_dirt, max_base_dirt)
+
+/decl/turf_initializer/spiderwebs/InitializeTurf(var/turf/tile)
+ if(!istype(tile) || tile.density || !tile.simulated)
+ return
+ // Quick and dirty check to avoid placing things inside windows
+ if(locate(/obj/structure/grille, tile))
+ return
+
+ var/add_dirt = get_dirt_amount()
+ // If a neighbor is dirty, then we get dirtier.
+ var/how_dirty = dirty_neighbors(tile)
+ for(var/i = 0; i < how_dirty; i++)
+ add_dirt += rand(0, max_dirt_per_turf)
+ tile.add_dirt(add_dirt)
+
+ if(prob(web_probability)) // Keep in mind that only "corners" get any sort of web
+ attempt_web(tile)
+
+/// Returns the number of cardinally adjacent turfs with at least 25 dirt (halfway to visible)
+/decl/turf_initializer/spiderwebs/proc/dirty_neighbors(var/turf/center)
+ var/how_dirty = 0
+ for(var/turf/neighbour in center.CardinalTurfs())
+ // Considered dirty if more than halfway to visible dirt
+ if(neighbour.get_dirt() > 25)
+ how_dirty++
+ return how_dirty
+
+/decl/turf_initializer/spiderwebs/proc/attempt_web(var/turf/tile)
+ if(!istype(tile) || !tile.simulated)
+ return
+
+ var/turf/north_turf = get_step_resolving_mimic(tile, NORTH)
+ if(!north_turf || !north_turf.density)
+ return
+
+ for(var/dir in list(WEST, EAST)) // For the sake of efficiency, west wins over east in the case of 1-tile valid spots, rather than doing pick()
+ var/turf/neighbour = get_step_resolving_mimic(tile, dir)
+ if(!neighbour || !neighbour.density)
+ continue
+ switch(dir)
+ if(WEST)
+ new /obj/effect/decal/cleanable/cobweb(tile)
+ if(EAST)
+ new /obj/effect/decal/cleanable/cobweb2(tile)
+ if(prob(spiderling_probability))
+ var/obj/effect/spider/spiderling/spiderling = new /obj/effect/spider/spiderling/mundane/dormant(tile)
+ spiderling.pixel_y = spiderling.shift_range
+ spiderling.pixel_x = dir == WEST ? -spiderling.shift_range : spiderling.shift_range
+ break // only place one web
+
+/// Spawns random 'kitchen' grime near tables: flour spills, smashed eggs, fruit smudges, etc.
+/decl/turf_initializer/kitchen
+ /// The probability of attempting to place clutter for a turf.
+ var/clutter_probability = 10
+ /// Clutter types to pick from when placing clutter on a turf.
+ var/list/clutter = list(
+ /obj/effect/decal/cleanable/flour,
+ /obj/effect/decal/cleanable/tomato_smudge,
+ /obj/effect/decal/cleanable/egg_smudge
+ )
+
+/decl/turf_initializer/kitchen/InitializeTurf(var/turf/tile)
+ if(!istype(tile) || tile.density || !tile.simulated)
+ return
+ if(!prob(clutter_probability))
+ return
+ var/adjacent_tables = 0
+ for(var/obj/structure/table/table in orange(tile, 1))
+ adjacent_tables++
+ break
+ if(!adjacent_tables)
+ return
+ if(!prob(adjacent_tables * 25)) // far more likely in table corners with 3 or more tables adjacent
+ return
+ var/obj/clutter_to_spawn = pick(clutter)
+ if(!clutter_to_spawn)
+ return
+ new clutter_to_spawn(tile)
\ No newline at end of file
diff --git a/code/game/turfs/initialization/maintenance.dm b/code/game/turfs/initialization/maintenance.dm
index 4431a959bcf..e859322e053 100644
--- a/code/game/turfs/initialization/maintenance.dm
+++ b/code/game/turfs/initialization/maintenance.dm
@@ -14,65 +14,66 @@
vermin_probability = 0
web_probability = 0
-/decl/turf_initializer/maintenance/InitializeTurf(var/turf/T)
- if(!istype(T) || T.density || !T.simulated)
+/decl/turf_initializer/maintenance/InitializeTurf(var/turf/tile)
+ if(!istype(tile) || tile.density || !tile.simulated)
return
// Quick and dirty check to avoid placing things inside windows
- if(locate(/obj/structure/grille, T))
+ if(locate(/obj/structure/grille, tile))
return
- var/cardinal_turfs = T.CardinalTurfs()
-
var/add_dirt = get_dirt_amount()
// If a neighbor is dirty, then we get dirtier.
- var/how_dirty = dirty_neighbors(cardinal_turfs)
+ var/how_dirty = dirty_neighbors(tile)
for(var/i = 0; i < how_dirty; i++)
add_dirt += rand(0,5)
- T.add_dirt(add_dirt)
+ tile.add_dirt(add_dirt)
if(prob(oil_probability))
- new /obj/effect/decal/cleanable/blood/oil(T)
+ new /obj/effect/decal/cleanable/blood/oil(tile)
if(prob(clutter_probability))
- new /obj/random/junk(T)
+ new /obj/random/junk(tile)
if(prob(vermin_probability))
if(prob(80))
- new /mob/living/simple_animal/passive/mouse(T)
+ new /mob/living/simple_animal/passive/mouse(tile)
else
- new /mob/living/simple_animal/lizard(T)
+ new /mob/living/simple_animal/lizard(tile)
if(prob(web_probability)) // Keep in mind that only "corners" get any sort of web
- attempt_web(T, cardinal_turfs)
+ attempt_web(tile)
-/decl/turf_initializer/maintenance/proc/dirty_neighbors(var/list/cardinal_turfs)
+/// Returns the number of cardinally adjacent turfs with at least 25 dirt (halfway to visible)
+/decl/turf_initializer/maintenance/proc/dirty_neighbors(var/turf/center)
var/how_dirty = 0
- for(var/turf/T in cardinal_turfs)
+ for(var/turf/neighbour in center.CardinalTurfs())
// Considered dirty if more than halfway to visible dirt
- if(T.get_dirt() > 25)
+ if(neighbour.get_dirt() > 25)
how_dirty++
return how_dirty
-/decl/turf_initializer/maintenance/proc/attempt_web(var/turf/T)
+/decl/turf_initializer/maintenance/proc/attempt_web(var/turf/tile)
- if(!istype(T) || !T.simulated)
+ if(!istype(tile) || !tile.simulated)
return
- var/turf/north_turf = get_step(T, NORTH)
+ var/turf/north_turf = get_step(tile, NORTH)
if(!north_turf || !north_turf.density)
return
- for(var/dir in list(WEST, EAST)) // For the sake of efficiency, west wins over east in the case of 1-tile valid spots, rather than doing pick()
- var/turf/neighbour = get_step(T, dir)
- if(neighbour && neighbour.density)
- if(dir == WEST)
- new /obj/effect/decal/cleanable/cobweb(T)
- if(dir == EAST)
- new /obj/effect/decal/cleanable/cobweb2(T)
- if(prob(web_probability))
- var/obj/effect/spider/spiderling/spiderling = new /obj/effect/spider/spiderling/mundane/dormant(T)
- spiderling.pixel_y = spiderling.shift_range
- spiderling.pixel_x = dir == WEST ? -spiderling.shift_range : spiderling.shift_range
+ for(var/dir in list(WEST, EAST)) // For the sake of efficiency, west wins over east in the case of 1-tile valid spots, rather than doing pick()
+ var/turf/neighbour = get_step_resolving_mimic(tile, dir)
+ if(!neighbour || !neighbour.density)
+ continue
+ switch(dir)
+ if(WEST)
+ new /obj/effect/decal/cleanable/cobweb(tile)
+ if(EAST)
+ new /obj/effect/decal/cleanable/cobweb2(tile)
+ if(prob(web_probability))
+ var/obj/effect/spider/spiderling/spiderling = new /obj/effect/spider/spiderling/mundane/dormant(tile)
+ spiderling.pixel_y = spiderling.shift_range
+ spiderling.pixel_x = dir == WEST ? -spiderling.shift_range : spiderling.shift_range
/decl/turf_initializer/maintenance/proc/get_dirt_amount()
return rand(10, 50) + rand(0, 50)
diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm
index bd4d7d01541..9ba40c9bfe3 100644
--- a/code/game/turfs/open/_open.dm
+++ b/code/game/turfs/open/_open.dm
@@ -12,6 +12,17 @@
initial_gas = GAS_STANDARD_AIRMIX
zone_membership_candidate = TRUE
+/turf/open/Initialize(mapload, ...)
+ . = ..()
+ if(!mapload)
+ for(var/direction in global.alldirs)
+ var/turf/target_turf = get_step_resolving_mimic(src, direction)
+ if(istype(target_turf))
+ if(TICK_CHECK) // not CHECK_TICK -- only queue if the server is overloaded
+ target_turf.queue_icon_update()
+ else
+ target_turf.update_icon()
+
/turf/open/flooded
name = "open water"
flooded = /decl/material/liquid/water
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index fa977ac8e1b..2f6f9fcbf35 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -36,7 +36,7 @@
var/fluid_blocked_dirs = 0
var/flooded // Whether or not this turf is absolutely flooded ie. a water source.
var/footstep_type
- var/open_turf_type // Which open turf type to use by default above this turf in a multiz context. Overridden by area.
+ var/open_turf_type = /turf/open // Which open turf type to use by default above this turf in a multiz context. Overridden by area.
var/tmp/changing_turf
var/tmp/prev_type // Previous type of the turf, prior to turf translation.
@@ -84,9 +84,13 @@
// Temporary list of weakrefs of atoms who should be excepted from falling into us
var/list/skip_height_fall_for
+ var/paint_color
+
/turf/Initialize(mapload, ...)
. = null && ..() // This weird construct is to shut up the 'parent proc not called' warning without disabling the lint for child types. We explicitly return an init hint so this won't change behavior.
+ color = null
+
// atom/Initialize has been copied here for performance (or at least the bits of it that turfs use has been)
if(atom_flags & ATOM_FLAG_INITIALIZED)
PRINT_STACK_TRACE("Warning: [src]([type]) initialized multiple times!")
@@ -782,6 +786,14 @@
/turf/proc/get_soil_color()
return null
+/turf/get_color()
+ if(paint_color)
+ return paint_color
+ var/decl/material/material = get_material()
+ if(material)
+ return material.color
+ return color
+
/turf/proc/get_fishing_result(obj/item/food/bait)
var/area/A = get_area(src)
return A.get_fishing_result(src, bait)
diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm
index 1c774d4db2b..ce53c478566 100644
--- a/code/game/turfs/turf_changing.dm
+++ b/code/game/turfs/turf_changing.dm
@@ -201,7 +201,9 @@
if(!..())
return FALSE
- set_flooring(other.flooring)
+ // Unlint this to copy the actual raw vars.
+ UNLINT(_flooring = other._flooring)
+ UNLINT(_base_flooring = other._base_flooring)
set_floor_broken(other._floor_broken, TRUE)
set_floor_burned(other._floor_burned)
return TRUE
diff --git a/code/game/turfs/unsimulated/floor.dm b/code/game/turfs/unsimulated/floor.dm
index 2bb713b9a09..21f843cf699 100644
--- a/code/game/turfs/unsimulated/floor.dm
+++ b/code/game/turfs/unsimulated/floor.dm
@@ -37,12 +37,12 @@
/turf/unsimulated/floor/snow
name = "snow"
icon = 'icons/turf/flooring/snow.dmi'
- icon_state = "0"
+ icon_state = "snow0"
/turf/unsimulated/floor/ice
name = "ice"
icon = 'icons/turf/flooring/ice.dmi'
- icon_state = "0"
+ icon_state = "ice"
color = COLOR_SKY_BLUE
/turf/unsimulated/floor/snow_plating
diff --git a/code/game/turfs/walls/_wall.dm b/code/game/turfs/walls/_wall.dm
index a2dcfb4eb4d..f85c812bf9e 100644
--- a/code/game/turfs/walls/_wall.dm
+++ b/code/game/turfs/walls/_wall.dm
@@ -31,6 +31,7 @@ var/global/list/wall_fullblend_objects = list(
turf_flags = TURF_IS_HOLOMAP_OBSTACLE
initial_gas = GAS_STANDARD_AIRMIX
zone_membership_candidate = TRUE
+ layer = TURF_OVER_EDGE_LAYER
/// If set, will prevent merges between walls with different IDs.
var/unique_merge_identifier
@@ -46,7 +47,6 @@ var/global/list/wall_fullblend_objects = list(
/// A list of connections to non-walls for each corner, used for icon generation. Can be converted to a list of dirs with corner_states_to_dirs().
var/list/other_connections
var/floor_type = /turf/floor/plating //turf it leaves after destruction
- var/paint_color
var/stripe_color
var/handle_structure_blending = TRUE
var/min_dismantle_amount = 2
@@ -82,6 +82,14 @@ var/global/list/wall_fullblend_objects = list(
/turf/wall/LateInitialize(var/ml)
..()
update_material(!ml)
+ if(!ml)
+ for(var/direction in global.alldirs)
+ var/turf/target_turf = get_step_resolving_mimic(src, direction)
+ if(istype(target_turf))
+ if(TICK_CHECK) // not CHECK_TICK -- only queue if the server is overloaded
+ target_turf.queue_icon_update()
+ else
+ target_turf.update_icon()
/turf/wall/Destroy()
STOP_PROCESSING(SSturf, src)
@@ -115,6 +123,7 @@ var/global/list/wall_fullblend_objects = list(
return PROCESS_KILL
/turf/wall/get_material()
+ RETURN_TYPE(/decl/material)
return material
/turf/wall/bullet_act(var/obj/item/projectile/Proj)
@@ -297,9 +306,6 @@ var/global/list/wall_fullblend_objects = list(
addtimer(CALLBACK(W, TYPE_PROC_REF(/turf/wall, burn), temperature/4), 2)
physically_destroyed()
-/turf/wall/get_color()
- return paint_color
-
/turf/wall/set_color(new_color)
paint_color = new_color
update_icon()
diff --git a/code/game/turfs/walls/wall_attacks.dm b/code/game/turfs/walls/wall_attacks.dm
index 8569156c6ce..4c567def785 100644
--- a/code/game/turfs/walls/wall_attacks.dm
+++ b/code/game/turfs/walls/wall_attacks.dm
@@ -152,66 +152,8 @@
// Basic dismantling.
if(isnull(construction_stage) || !reinf_material)
-
- var/cut_delay = (6 SECONDS) - material.cut_delay
- var/dismantle_verb
- var/dismantle_sound
-
- if(IS_WELDER(W))
-
- if(material && !material.removed_by_welder)
- to_chat(user, SPAN_WARNING("\The [src] is too delicate to be dismantled with \the [W]; try a crowbar."))
- return TRUE
-
- var/obj/item/weldingtool/WT = W
- if(!WT.weld(0,user))
- return
- dismantle_verb = "cutting through"
- dismantle_sound = 'sound/items/Welder.ogg'
- cut_delay *= 0.7
-
- else if(IS_CROWBAR(W))
-
- if(material && material.removed_by_welder)
- to_chat(user, SPAN_WARNING("\The [src] is too robust to be dismantled with \the [W]; try a welding tool."))
- return TRUE
-
- dismantle_verb = "dismantling"
- dismantle_sound = 'sound/items/Crowbar.ogg'
- cut_delay *= 1.2
-
- else if(W.is_special_cutting_tool())
- if(istype(W, /obj/item/gun/energy/plasmacutter))
- var/obj/item/gun/energy/plasmacutter/cutter = W
- if(!cutter.slice(user))
- return TRUE
- dismantle_sound = "sparks"
- dismantle_verb = "slicing through"
- cut_delay *= 0.5
-
- else if(IS_PICK(W))
-
- if(W.material?.hardness < material.hardness)
- to_chat(user, SPAN_WARNING("\The [W] is not hard enough to cut through [material.solid_name]."))
- return TRUE
-
- dismantle_verb = W.get_tool_message(TOOL_PICK)
- dismantle_sound = W.get_tool_sound(TOOL_PICK)
- cut_delay = W.get_expected_tool_use_delay(TOOL_PICK, cut_delay)
-
- if(dismantle_verb)
-
- to_chat(user, "You begin [dismantle_verb] \the [src].")
- if(dismantle_sound)
- playsound(src, dismantle_sound, 100, 1)
-
- if(cut_delay<0)
- cut_delay = 0
-
- if(do_after(user,cut_delay,src))
- to_chat(user, "You remove the outer plating.")
- user.visible_message("\The [user] finishes [dismantle_verb] \the [src]!")
- dismantle_turf()
+ var/datum/extension/demolisher/demolition = get_extension(W, /datum/extension/demolisher)
+ if(istype(demolition) && demolition.try_demolish(user, src))
return TRUE
//Reinforced dismantling.
diff --git a/code/game/turfs/walls/wall_brick.dm b/code/game/turfs/walls/wall_brick.dm
index a8535f6472b..5317df3af83 100644
--- a/code/game/turfs/walls/wall_brick.dm
+++ b/code/game/turfs/walls/wall_brick.dm
@@ -2,7 +2,7 @@
icon_state = "brick"
material = /decl/material/solid/stone/sandstone
girder_material = null
- floor_type = null
+ floor_type = /turf/floor/dirt
min_dismantle_amount = 3
max_dismantle_amount = 5
diff --git a/code/game/turfs/walls/wall_icon.dm b/code/game/turfs/walls/wall_icon.dm
index b30263d23b4..c682d4f266f 100644
--- a/code/game/turfs/walls/wall_icon.dm
+++ b/code/game/turfs/walls/wall_icon.dm
@@ -98,7 +98,6 @@
wall_connections = dirs_to_corner_states(wall_dirs)
other_connections = dirs_to_corner_states(other_dirs)
-
/turf/wall/proc/update_wall_icon()
var/material_icon_base = get_wall_icon()
var/base_color = material.color
diff --git a/code/game/turfs/walls/wall_log.dm b/code/game/turfs/walls/wall_log.dm
index 90ca4b057e3..eb44eda2bef 100644
--- a/code/game/turfs/walls/wall_log.dm
+++ b/code/game/turfs/walls/wall_log.dm
@@ -3,7 +3,7 @@
material = /decl/material/solid/organic/wood
color = /decl/material/solid/organic/wood::color
girder_material = null
- floor_type = null
+ floor_type = /turf/floor/dirt
min_dismantle_amount = 3
max_dismantle_amount = 5
diff --git a/code/game/turfs/walls/wall_natural.dm b/code/game/turfs/walls/wall_natural.dm
index f6b20cff7f4..e878e59747e 100644
--- a/code/game/turfs/walls/wall_natural.dm
+++ b/code/game/turfs/walls/wall_natural.dm
@@ -3,7 +3,7 @@
desc = "A rough natural wall."
turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_OBSTACLE
girder_material = null
- floor_type = /turf/floor/natural/barren
+ floor_type = /turf/floor/rock
construction_stage = -1
var/strata_override
var/ramp_slope_direction
diff --git a/code/game/turfs/walls/wall_natural_subtypes.dm b/code/game/turfs/walls/wall_natural_subtypes.dm
index ee192c9fc23..976b793664f 100644
--- a/code/game/turfs/walls/wall_natural_subtypes.dm
+++ b/code/game/turfs/walls/wall_natural_subtypes.dm
@@ -35,32 +35,32 @@
/turf/wall/natural/ice
strata_override = /decl/strata/permafrost
- floor_type = /turf/floor/natural/ice
+ floor_type = /turf/floor/ice
/turf/wall/natural/random/ice
strata_override = /decl/strata/permafrost
- floor_type = /turf/floor/natural/ice
+ floor_type = /turf/floor/ice
/turf/wall/natural/random/high_chance/ice
strata_override = /decl/strata/permafrost
- floor_type = /turf/floor/natural/ice
+ floor_type = /turf/floor/ice
/turf/wall/natural/dirt
material = /decl/material/solid/soil
color = "#41311b"
- floor_type = /turf/floor/natural/dirt
+ floor_type = /turf/floor/dirt
/turf/wall/natural/basalt
material = /decl/material/solid/stone/basalt
color = COLOR_DARK_GRAY
- floor_type = /turf/floor/natural/rock/basalt
+ floor_type = /turf/floor/rock/basalt
/turf/wall/natural/random/basalt
material = /decl/material/solid/stone/basalt
color = COLOR_DARK_GRAY
- floor_type = /turf/floor/natural/rock/basalt
+ floor_type = /turf/floor/rock/basalt
/turf/wall/natural/random/high_chance/basalt
material = /decl/material/solid/stone/basalt
color = COLOR_DARK_GRAY
- floor_type = /turf/floor/natural/rock/basalt
+ floor_type = /turf/floor/rock/basalt
diff --git a/code/modules/abstract/airlock_helper.dm b/code/modules/abstract/airlock_helper.dm
new file mode 100644
index 00000000000..3e70efba8d4
--- /dev/null
+++ b/code/modules/abstract/airlock_helper.dm
@@ -0,0 +1,148 @@
+/*
+Note that these have to be within range of world.view (7 tiles), centered on the controller for them to function.
+You still need to set the controller's "id_tag" to something unique.
+*/
+/obj/abstract/airlock_helper
+ icon = 'icons/effects/airlock_helper.dmi'
+ abstract_type = /obj/abstract/airlock_helper
+ is_spawnable_type = FALSE
+ layer = ABOVE_DOOR_LAYER
+ /// The controller we're using. Set to a type to locate the type during Initialize().
+ var/obj/machinery/embedded_controller/radio/my_controller = /obj/machinery/embedded_controller/radio/airlock
+ /// The device we're setting up. Set to a type to locate the type during Initialize().
+ var/my_device
+ /// Adjusts the various radio tags used to configure airlock devices.
+ var/tag_addon
+
+/obj/abstract/airlock_helper/Initialize()
+ ..()
+ my_controller = get_controller()
+ if(!my_controller)
+ log_error("Airlock helper '[name]' couldn't find a controller at: X:[x] Y:[y] Z:[z]")
+ return INITIALIZE_HINT_QDEL
+
+ if(!my_controller.id_tag)
+ log_error("Airlock helper '[name]' found a controller without an 'id_tag' set: X:[x] Y:[y] Z:[z]")
+ return INITIALIZE_HINT_QDEL
+
+ my_device = locate(my_device) in loc
+ if(!my_device)
+ log_error("Airlock helper '[name]' couldn't find the device it wanted at: X:[x] Y:[y] Z:[z]")
+ return INITIALIZE_HINT_QDEL
+
+ configure_associated_device()
+ return INITIALIZE_HINT_QDEL
+
+/obj/abstract/airlock_helper/Destroy()
+ my_controller = null
+ my_device = null
+ return ..()
+
+/obj/abstract/airlock_helper/proc/get_controller()
+ var/closest_distance = INFINITY
+ for(var/obj/O in range(world.view, src))
+ if(istype(O, my_controller))
+ if(!.)
+ . = O
+ else
+ var/check_distance = get_dist(src, O)
+ if(check_distance < closest_distance)
+ closest_distance = check_distance
+ . = O
+
+/// Stub for subtypes to override to deal with their specific devices.
+/obj/abstract/airlock_helper/proc/configure_associated_device()
+ return
+
+/*
+ Doors
+*/
+/obj/abstract/airlock_helper/door
+ name = "use a subtype! - airlock door"
+ my_device = /obj/machinery/door/airlock
+
+/obj/abstract/airlock_helper/door/configure_associated_device()
+ var/obj/machinery/door/airlock/my_airlock = my_device
+ my_airlock.lock()
+ my_airlock.set_id_tag(my_controller.id_tag + tag_addon)
+ for(var/obj/item/stock_parts/radio/R in my_airlock.get_all_components_of_type(/obj/item/stock_parts/radio))
+ R.set_id_tag(my_controller.id_tag + tag_addon)
+
+/obj/abstract/airlock_helper/door/ext_door
+ name = "exterior airlock door"
+ icon_state = "doorout"
+ tag_addon = "_outer"
+
+/obj/abstract/airlock_helper/door/int_door
+ name = "interior airlock door"
+ icon_state = "doorin"
+ tag_addon = "_inner"
+
+/obj/abstract/airlock_helper/door/simple
+ name = "simple docking controller hatch"
+ icon_state = "doorsimple"
+ tag_addon = "_hatch"
+ my_controller = /obj/machinery/embedded_controller/radio/simple_docking_controller
+
+
+/*
+ Atmos
+*/
+/obj/abstract/airlock_helper/atmos
+ name = "use a subtype! - airlock pump"
+ my_device = /obj/machinery/atmospherics/unary/vent_pump
+
+/obj/abstract/airlock_helper/atmos/configure_associated_device()
+ var/obj/machinery/atmospherics/unary/vent_pump/my_pump = my_device
+ my_pump.set_id_tag(my_controller.id_tag + tag_addon)
+ for(var/obj/item/stock_parts/radio/R in my_pump.get_all_components_of_type(/obj/item/stock_parts/radio))
+ R.set_id_tag(my_controller.id_tag + tag_addon)
+
+/obj/abstract/airlock_helper/atmos/chamber_pump
+ name = "chamber pump"
+ icon_state = "pump"
+ tag_addon = "_pump"
+
+/obj/abstract/airlock_helper/atmos/pump_out_internal
+ name = "air dump intake"
+ icon_state = "pumpdin"
+ tag_addon = "_pump_out_internal"
+
+/obj/abstract/airlock_helper/atmos/pump_out_external
+ name = "air dump output"
+ icon_state = "pumpdout"
+ tag_addon = "_pump_out_external"
+
+
+/*
+ Sensors
+*/
+/obj/abstract/airlock_helper/sensor
+ my_device = /obj/machinery/airlock_sensor
+
+/obj/abstract/airlock_helper/sensor/configure_associated_device()
+ var/obj/machinery/airlock_sensor/my_sensor = my_device
+ my_sensor.set_id_tag(my_controller.id_tag + tag_addon)
+
+/obj/abstract/airlock_helper/sensor/ext_sensor
+ name = "exterior sensor"
+ icon_state = "sensout"
+ tag_addon = "_exterior_sensor"
+
+/obj/abstract/airlock_helper/sensor/chamber_sensor
+ name = "chamber sensor"
+ icon_state = "sens"
+ tag_addon = "_sensor"
+
+/obj/abstract/airlock_helper/sensor/int_sensor
+ name = "interior sensor"
+ icon_state = "sensin"
+ tag_addon = "_interior_sensor"
+
+/*
+ Buttons - at one point in time, sensors also worked as buttons, but now that isn't the case.
+*/
+/obj/abstract/airlock_helper/button
+ my_device = /obj/machinery/button/access
+ icon_state = "button"
+ tag_addon = "_airlock"
diff --git a/code/modules/backgrounds/location/_location_events.dm b/code/modules/backgrounds/location/_location_events.dm
index d05b9035753..0cc5d9380e4 100644
--- a/code/modules/backgrounds/location/_location_events.dm
+++ b/code/modules/backgrounds/location/_location_events.dm
@@ -4,27 +4,27 @@
/decl/location_event/big_game_hunters/announce(var/decl/background_detail/location)
. = "Game hunters on [location.name] "
if(prob(33))
- . += "were surprised when an unusual species experts have since identified as \
+ . += "were surprised when an unusual species that experts have since identified as \
[pick("a subclass of mammal","a divergent abhuman species","an intelligent species of lemur","organic/cyborg hybrids")] turned up. Believed to have been brought in by \
[pick("alien smugglers","early colonists","mercenary raiders","unwitting tourists")], this is the first such specimen discovered in the wild."
else if(prob(50))
- . += "were attacked by a vicious [pick("nas'r","diyaab","samak","predator which has not yet been identified")]\
- . Officials urge caution, and locals are advised to stock up on armaments."
+ . += "were attacked by a vicious [pick("nas'r","diyaab","samak","predator which has not yet been identified")]. \
+ Officials urge caution, and locals are advised to stock up on armaments."
else
. += "brought in an unusually [pick("valuable","rare","large","vicious","intelligent")] specimen for inspection \
[pick("today","yesterday","last week")]. Speculators suggest they may be tipped to break several records."
/decl/location_event/riots/announce(var/decl/background_detail/location)
- . = "[pick("Riots have","Unrest has")] broken out on planet [location.name]. Authorities call for calm, as [pick("various parties","rebellious elements","peacekeeping forces","\'REDACTED\'")] begin stockpiling weaponry and armour. Meanwhile, food and mineral prices are dropping as local industries attempt empty their stocks in expectation of looting."
+ . = "[pick("Riots have","Unrest has")] broken out on planet [location.name]. Authorities call for calm, as [pick("various parties","rebellious elements","peacekeeping forces","\'REDACTED\'")] begin stockpiling weaponry and armour. Meanwhile, food and mineral prices are dropping as local industries attempt to empty their stocks in expectation of looting."
/decl/location_event/wild_animal_attack/announce(var/decl/background_detail/location)
- . = "Local [pick("wildlife","animal life","fauna")] on planet [location.name] has been increasing in agression and raiding outlying settlements for food. Big game hunters have been called in to help alleviate the problem, but numerous injuries have already occurred."
+ . = "Local [pick("wildlife","animal life","fauna")] on planet [location.name] has been increasing in aggression and raiding outlying settlements for food. Big game hunters have been called in to help alleviate the problem, but numerous injuries have already occurred."
/decl/location_event/industrial_accident/announce(var/decl/background_detail/location)
. = "[pick("An industrial accident","A smelting accident","A malfunction","A malfunctioning piece of machinery","Negligent maintenance","A cooleant leak","A ruptured conduit")] at a [pick("factory","installation","power plant","dockyards")] on [location.name] resulted in severe structural damage and numerous injuries. Repairs are ongoing."
/decl/location_event/biohazard_outbreak/announce(var/decl/background_detail/location)
- . = "[pick("A \'REDACTED\'","A biohazard","An outbreak","A virus")] on [location.name] has resulted in quarantine, stopping much shipping in the area. Although the quarantine is now lifted, authorities are calling for deliveries of medical supplies to treat the infected, and gas to replace contaminated stocks."
+ . = "[pick("A \'REDACTED\'","A biohazard","An outbreak","A virus")] on [location.name] has resulted in quarantine, stopping most shipping in the area. Although the quarantine is now lifted, authorities are calling for deliveries of medical supplies to treat the infected, and gas to replace contaminated stocks."
/decl/location_event/pirates/announce(var/decl/background_detail/location)
. = "[pick("Pirates","Criminal elements","A [pick("mercenary","Donk Co.","Waffle Co.","\'REDACTED\'")] strike force")] have [pick("raided","blockaded","attempted to blackmail","attacked")] [location.name] today. Security has been tightened, but many valuable minerals were taken."
@@ -34,12 +34,12 @@
/decl/location_event/alien_raiders/announce(var/decl/background_detail/location)
if(prob(20))
- . = "The Tiger Co-operative have raided [location.name] today, no doubt on orders from their enigmatic masters. Stealing wildlife, farm animals, medical research materials and kidnapping civilians. [global.using_map.company_name] authorities are standing by to counter attempts at bio-terrorism."
+ . = "The Tiger Co-operative have raided [location.name] today, no doubt on orders from their enigmatic masters, stealing wildlife, farm animals, medical research materials and kidnapping civilians. [global.using_map.company_name] authorities are standing by to counter attempts at bio-terrorism."
else
- . = "[pick("The alien species designated \'United Exolitics\'","The alien species designated \'REDACTED\'","An unknown alien species")] have raided [location.name] today, stealing wildlife, farm animals, medical research materials and kidnapping civilians. It seems they desire to learn more about us, so the Navy will be standing by to accomodate them next time they try."
+ . = "[pick("The alien species designated \'United Exolitics\'","The alien species designated \'REDACTED\'","An unknown alien species")] have raided [location.name] today, stealing wildlife, farm animals, medical research materials and kidnapping civilians. It seems they desire to learn more about us, so the Navy will be standing by to accomodate them the next time they try."
/decl/location_event/ai_liberation/announce(var/decl/background_detail/location)
- . = "A [pick("\'REDACTED\' was detected on","S.E.L.F operative infiltrated","malignant computer virus was detected on","rogue [pick("slicer","hacker")] was apprehended on")] [location.name] today, and managed to infect [pick("\'REDACTED\'","a sentient sub-system","a class one AI","a sentient defence installation")] before it could be stopped. Many lives were lost as it systematically begin murdering civilians, and considerable work must be done to repair the affected areas."
+ . = "A [pick("\'REDACTED\' was detected on","S.E.L.F operative infiltrated","malignant computer virus was detected on","rogue [pick("slicer","hacker")] was apprehended on")] [location.name] today, and managed to infect [pick("\'REDACTED\'","a sentient sub-system","a class one AI","a sentient defence installation")] before it could be stopped. Many lives were lost as it began systematically murdering civilians, and considerable work must be done to repair the affected areas."
/decl/location_event/mourning/announce(var/decl/background_detail/location)
. = "[pick("The popular","The well-liked","The eminent","The well-known")] [pick("professor","entertainer","singer","researcher","public servant","administrator","ship captain","\'REDACTED\'")], [pick( random_name(pick(MALE,FEMALE)), 40; "\'REDACTED\'" )] has [pick("passed away","committed suicide","been murdered","died in a freakish accident")] on [location.name] today. The entire planet is in mourning, and prices have dropped for industrial goods as worker morale drops."
@@ -146,4 +146,3 @@
. = "Tourists are flocking to [location.name] after the surprise announcement of [pick("major shopping bargains by a wily retailer",\
"a huge new ARG by a popular entertainment company","a secret tour by popular artiste [random_name(pick(MALE,FEMALE))]")]. \
Nyx Daily is offering discount tickets for two to see [random_name(pick(MALE,FEMALE))] live in return for eyewitness reports and up to the minute coverage."
-
diff --git a/code/modules/butchery/butchery_data_animal.dm b/code/modules/butchery/butchery_data_animal.dm
index 2c5b8a45313..d3b44a7f762 100644
--- a/code/modules/butchery/butchery_data_animal.dm
+++ b/code/modules/butchery/butchery_data_animal.dm
@@ -83,6 +83,7 @@
skin_material = /decl/material/solid/organic/skin/fur/white
gut_type = /obj/item/food/butchery/offal/small
must_use_hook = FALSE
+ butchery_offset = list(-6, 0)
/decl/butchery_data/animal/rabbit/brown
skin_material = /decl/material/solid/organic/skin/fur/brown
diff --git a/code/modules/butchery/butchery_products.dm b/code/modules/butchery/butchery_products.dm
index d01bf962e7e..b29bcf55f64 100644
--- a/code/modules/butchery/butchery_products.dm
+++ b/code/modules/butchery/butchery_products.dm
@@ -164,6 +164,12 @@
slice_path = null
slice_num = null
+/obj/item/food/butchery/offal/beef
+ meat_name = "beef"
+
+/obj/item/food/butchery/offal/small/beef
+ meat_name = "beef"
+
/obj/item/food/butchery/haunch
name = "haunch"
desc = "A severed leg of some unfortunate beast, cleaned and ready for cooking."
@@ -192,9 +198,15 @@
var/decl/material/fat = GET_DECL(fat_material)
add_overlay(overlay_image(icon, "[icon_state]-fat", fat.color, RESET_COLOR))
+/obj/item/food/butchery/haunch/beef
+ meat_name = "beef"
+
/obj/item/food/butchery/haunch/shoulder
name = "shoulder"
+/obj/item/food/butchery/haunch/shoulder/beef
+ meat_name = "beef"
+
/obj/item/food/butchery/haunch/side
name = "side of meat"
desc = "Approximately half the torso and body of an unfortunate animal, split lengthways, cleaned, and ready for cooking."
@@ -210,6 +222,9 @@
meat_name = new_meat_name
SetName("side of [new_meat_name]")
+/obj/item/food/butchery/haunch/side/beef
+ meat_name = "beef"
+
// TODO: unify with organ/internal/stomach?
/obj/item/food/butchery/stomach
name = "stomach"
diff --git a/code/modules/butchery/butchery_products_cutlet.dm b/code/modules/butchery/butchery_products_cutlet.dm
index b8062e4c23a..20b1fc037e6 100644
--- a/code/modules/butchery/butchery_products_cutlet.dm
+++ b/code/modules/butchery/butchery_products_cutlet.dm
@@ -22,3 +22,7 @@
dried_type = /obj/item/food/jerky/cutlet
nutriment_amt = 2
material_alteration = MAT_FLAG_ALTERATION_COLOR
+
+/obj/item/food/butchery/cutlet/raw/beef
+ meat_name = "beef"
+ desc = "A thin piece of raw beef."
\ No newline at end of file
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index cc84ffe4feb..38e1f834f67 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -381,7 +381,6 @@ var/global/list/time_prefs_fixed = list()
character.set_gender(gender)
character.blood_type = blood_type
- character.set_eye_colour(eye_colour, skip_update = TRUE)
character.set_skin_colour(skin_colour, skip_update = TRUE)
character.skin_tone = skin_tone
@@ -407,6 +406,8 @@ var/global/list/time_prefs_fixed = list()
for(var/trait_type in traits)
character.set_trait(trait_type, (traits[trait_type] || TRAIT_LEVEL_EXISTS))
+ character.set_eye_colour(eye_colour, skip_update = TRUE)
+
for(var/obj/item/organ/external/O in character.get_external_organs())
for(var/decl/sprite_accessory_category/sprite_category in O.get_sprite_accessory_categories())
if(!sprite_category.clear_in_pref_apply)
diff --git a/code/modules/clothing/_clothing.dm b/code/modules/clothing/_clothing.dm
index a1a5d29d40f..b0ea6c2e268 100644
--- a/code/modules/clothing/_clothing.dm
+++ b/code/modules/clothing/_clothing.dm
@@ -83,10 +83,10 @@
/obj/item/clothing/proc/setup_equip_flags()
if(!isnull(bodytype_equip_flags))
- if(bodytype_equip_flags & BODY_FLAG_EXCLUDE)
- bodytype_equip_flags |= BODY_FLAG_QUADRUPED
+ if(bodytype_equip_flags & BODY_EQUIP_FLAG_EXCLUDE)
+ bodytype_equip_flags |= BODY_EQUIP_FLAG_QUADRUPED
else
- bodytype_equip_flags &= ~BODY_FLAG_QUADRUPED
+ bodytype_equip_flags &= ~BODY_EQUIP_FLAG_QUADRUPED
/obj/item/clothing/can_contaminate()
return TRUE
@@ -258,7 +258,7 @@
var/decl/bodytype/root_bodytype = user?.get_bodytype()
if(!root_bodytype || isnull(bodytype_equip_flags) || (slot in user.get_held_item_slots()))
return
- if(bodytype_equip_flags & BODY_FLAG_EXCLUDE)
+ if(bodytype_equip_flags & BODY_EQUIP_FLAG_EXCLUDE)
. = !(bodytype_equip_flags & root_bodytype.bodytype_flag)
else
. = (bodytype_equip_flags & root_bodytype.bodytype_flag)
diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm
index df999d9d245..b97d5aed843 100644
--- a/code/modules/clothing/gloves/_gloves.dm
+++ b/code/modules/clothing/gloves/_gloves.dm
@@ -13,7 +13,7 @@
slot_flags = SLOT_HANDS
attack_verb = list("challenged")
blood_overlay_type = "bloodyhands"
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
fallback_slot = slot_gloves_str
var/obj/item/clothing/gloves/ring/covering_ring
diff --git a/code/modules/clothing/jumpsuits/misc.dm b/code/modules/clothing/jumpsuits/misc.dm
index 87bdd416cfb..afb30f30c5a 100644
--- a/code/modules/clothing/jumpsuits/misc.dm
+++ b/code/modules/clothing/jumpsuits/misc.dm
@@ -38,4 +38,4 @@
name = "caretaker's jumpsuit"
desc = "A holy jumpsuit. Treat it well."
icon = 'icons/clothing/jumpsuits/caretaker.dmi'
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
diff --git a/code/modules/clothing/spacesuits/void/void.dm b/code/modules/clothing/spacesuits/void/void.dm
index 380639cdde7..7f2d8ecfe17 100644
--- a/code/modules/clothing/spacesuits/void/void.dm
+++ b/code/modules/clothing/spacesuits/void/void.dm
@@ -3,7 +3,7 @@
name = "void helmet"
desc = "A high-tech dark red space suit helmet. Used for AI satellite maintenance."
icon = 'icons/clothing/spacesuit/void/nasa/helmet.dmi'
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
heat_protection = SLOT_HEAD
armor = list(
ARMOR_MELEE = ARMOR_MELEE_RESISTANT,
@@ -22,7 +22,7 @@
/obj/item/clothing/suit/space/void
name = "voidsuit"
icon = 'icons/clothing/spacesuit/void/nasa/suit.dmi'
- bodytype_equip_flags = BODY_FLAG_HUMANOID
+ bodytype_equip_flags = BODY_EQUIP_FLAG_HUMANOID
w_class = ITEM_SIZE_HUGE//bulky item
desc = "A high-tech dark red space suit. Used for AI satellite maintenance."
armor = list(
diff --git a/code/modules/crafting/stack_recipes/recipes_bricks.dm b/code/modules/crafting/stack_recipes/recipes_bricks.dm
index 65844e2b491..1901075e8e0 100644
--- a/code/modules/crafting/stack_recipes/recipes_bricks.dm
+++ b/code/modules/crafting/stack_recipes/recipes_bricks.dm
@@ -115,15 +115,15 @@
/decl/stack_recipe/turfs/floor/brick
name = "cobblestone path"
- result_type = /turf/floor/natural/path
+ result_type = /turf/floor/path
craft_stack_types = /obj/item/stack/material/brick
/decl/stack_recipe/turfs/floor/brick/herringbone
name = "herringbone path"
- result_type = /turf/floor/natural/path/herringbone
+ result_type = /turf/floor/path/herringbone
difficulty = MAT_VALUE_HARD_DIY
/decl/stack_recipe/turfs/floor/brick/running_bond
name = "running bond path"
- result_type = /turf/floor/natural/path/running_bond
+ result_type = /turf/floor/path/running_bond
difficulty = MAT_VALUE_HARD_DIY
diff --git a/code/modules/crafting/stack_recipes/recipes_turfs.dm b/code/modules/crafting/stack_recipes/recipes_turfs.dm
index 63d003e467d..dfdb81b2b9b 100644
--- a/code/modules/crafting/stack_recipes/recipes_turfs.dm
+++ b/code/modules/crafting/stack_recipes/recipes_turfs.dm
@@ -43,5 +43,5 @@
/decl/stack_recipe/turfs/floor
abstract_type = /decl/stack_recipe/turfs/floor
- expected_product_type = /turf/floor/natural
+ expected_product_type = /turf/floor
category = "floors"
diff --git a/code/modules/fabrication/fabricator_bioprinter.dm b/code/modules/fabrication/fabricator_bioprinter.dm
index 28c92d0c73f..06781729536 100644
--- a/code/modules/fabrication/fabricator_bioprinter.dm
+++ b/code/modules/fabrication/fabricator_bioprinter.dm
@@ -44,7 +44,7 @@
var/weakref/R = sample["donor"]
var/mob/living/human/H = R.resolve()
if(H && istype(H) && H.species)
- loaded_dna = H.get_mob_snapshot()
+ loaded_dna = H.get_mob_snapshot(check_dna = TRUE)
if(loaded_dna)
to_chat(user, SPAN_INFO("You inject the blood sample into \the [src]."))
S.remove_any_reagents(BIOPRINTER_BLOOD_SAMPLE_SIZE)
diff --git a/code/modules/fabrication/fabricator_food.dm b/code/modules/fabrication/fabricator_food.dm
index 0a1a9d41e24..5b9ab57e29c 100644
--- a/code/modules/fabrication/fabricator_food.dm
+++ b/code/modules/fabrication/fabricator_food.dm
@@ -7,6 +7,14 @@
base_icon_state = "replicator"
base_storage_capacity_mult = 5
+/obj/machinery/fabricator/replicator/Initialize()
+ . = ..()
+ global.listening_objects += src
+
+/obj/machinery/fabricator/replicator/Destroy()
+ global.listening_objects -= src
+ return ..()
+
/obj/machinery/fabricator/replicator/hear_talk(var/mob/M, var/text, var/verb, var/decl/language/speaking)
if(speaking && !speaking.machine_understands)
return ..()
diff --git a/code/modules/fluids/_fluid.dm b/code/modules/fluids/_fluid.dm
index c3e1c66018d..ef00dac2cea 100644
--- a/code/modules/fluids/_fluid.dm
+++ b/code/modules/fluids/_fluid.dm
@@ -21,14 +21,15 @@
// Update layer.
var/new_layer
- if(reagent_volume > FLUID_DEEP)
+ var/turf/T = get_turf(src)
+ var/effective_depth = T?.get_physical_height() + reagent_volume
+ if(effective_depth < 0)
+ new_layer = T.layer + 0.2
+ else if(reagent_volume > FLUID_DEEP)
new_layer = DEEP_FLUID_LAYER
else
- var/turf/T = get_turf(src)
- if(T?.get_physical_height() < 0)
- new_layer = T.layer + 0.2
- else
- new_layer = SHALLOW_FLUID_LAYER
+ new_layer = SHALLOW_FLUID_LAYER
+
if(layer != new_layer)
layer = new_layer
diff --git a/code/modules/food/cooking/_recipe.dm b/code/modules/food/cooking/_recipe.dm
index de45c984a14..262b8b8c09d 100644
--- a/code/modules/food/cooking/_recipe.dm
+++ b/code/modules/food/cooking/_recipe.dm
@@ -189,7 +189,8 @@ var/global/list/_cooking_recipe_cache = list()
if(contained_atoms)
contained_atoms -= produced
for(var/obj/O in contained_atoms)
- O.reagents.trans_to_obj(produced, O.reagents.total_volume)
+ if(O.reagents)
+ O.reagents.trans_to_obj(produced, O.reagents.total_volume)
qdel(O)
return produced
@@ -211,11 +212,11 @@ var/global/list/_cooking_recipe_cache = list()
return new result(container)
/// Return a data list to pass to a reagent creation proc. Allows for overriding/mutation based on ingredients.
-/// Actually place or create the result of the recipe. Returns the produced item, or the container for reagents.
/decl/recipe/proc/get_result_data(atom/container, list/used_ingredients)
return result_data
// food-related
+/// Actually place or create the result of the recipe. Returns the produced item(s), or null if only reagents were produced.
/decl/recipe/proc/produce_result(obj/container)
/*
@@ -229,7 +230,7 @@ var/global/list/_cooking_recipe_cache = list()
// the result proc needs to check the list for procedural products.
var/list/used_ingredients = list(
"items" = list(),
- "fruit" = list(),
+ "fruits" = list(),
"reagents" = list()
)
@@ -256,8 +257,9 @@ var/global/list/_cooking_recipe_cache = list()
continue
for(var/item_count in 1 to max(1, items[item_type]))
var/obj/item/item = locate(item_type) in container_contents
- container_contents -= item
- used_ingredients["items"] += item
+ if(item)
+ container_contents -= item
+ used_ingredients["items"] += item
// Find fruits that we need.
if(LAZYLEN(fruit))
diff --git a/code/modules/food/cooking/recipes/recipe_baked.dm b/code/modules/food/cooking/recipes/recipe_baked.dm
index cc72b6e3aa3..3b0ccc0693b 100644
--- a/code/modules/food/cooking/recipes/recipe_baked.dm
+++ b/code/modules/food/cooking/recipes/recipe_baked.dm
@@ -153,10 +153,11 @@
/decl/recipe/baked/fortunecookie/produce_result(obj/container)
var/obj/item/paper/paper = locate() in container
paper.forceMove(null) //prevent deletion
- var/obj/item/food/fortunecookie/being_cooked = ..(container)
- paper.forceMove(being_cooked)
- being_cooked.trash = paper //so the paper is left behind as trash without special-snowflake(TM Nodrak) code ~carn
- return being_cooked
+ var/list/obj/item/food/fortunecookie/results = ..(container)
+ for(var/obj/item/food/fortunecookie/being_cooked in results)
+ paper.forceMove(being_cooked)
+ being_cooked.trash = paper //so the paper is left behind as trash without special-snowflake(TM Nodrak) code ~carn
+ return results
/decl/recipe/baked/fortunecookie/check_items(var/obj/container)
. = ..()
diff --git a/code/modules/food/cooking/recipes/recipe_tossed.dm b/code/modules/food/cooking/recipes/recipe_tossed.dm
index 9c18c28ae24..045cc69aeba 100644
--- a/code/modules/food/cooking/recipes/recipe_tossed.dm
+++ b/code/modules/food/cooking/recipes/recipe_tossed.dm
@@ -6,10 +6,10 @@
result = /obj/item/food/tossedsalad
/decl/recipe/tossed/aesirsalad
- fruit = list("goldapple" = 1, "biteleafdeus" = 1)
+ fruit = list("goldapple" = 1, "ambrosiadeus" = 1)
result = /obj/item/food/aesirsalad
/decl/recipe/tossed/validsalad
- fruit = list("potato" = 1, "biteleaf" = 3)
+ fruit = list("potato" = 1, "ambrosiavulgaris" = 3)
items = list(/obj/item/food/meatball)
result = /obj/item/food/validsalad
diff --git a/code/modules/food/utensils/utensil_chopsticks.dm b/code/modules/food/utensils/utensil_chopsticks.dm
index 7ab29c96a3e..5be0baed66b 100644
--- a/code/modules/food/utensils/utensil_chopsticks.dm
+++ b/code/modules/food/utensils/utensil_chopsticks.dm
@@ -11,3 +11,7 @@
/obj/item/utensil/chopsticks/aluminium
material = /decl/material/solid/metal/aluminium
+
+/obj/item/utensil/chopsticks/bamboo
+ material = /decl/material/solid/organic/wood/bamboo
+ color = /decl/material/solid/organic/wood/bamboo::color
\ No newline at end of file
diff --git a/code/modules/food/utensils/utensil_spoon.dm b/code/modules/food/utensils/utensil_spoon.dm
index 94fafb1d8cb..e6efc4af303 100644
--- a/code/modules/food/utensils/utensil_spoon.dm
+++ b/code/modules/food/utensils/utensil_spoon.dm
@@ -16,3 +16,7 @@
/obj/item/utensil/spoon/plastic
material = /decl/material/solid/organic/plastic
+
+/obj/item/utensil/spoon/wood
+ material = /decl/material/solid/organic/wood
+ color = /decl/material/solid/organic/wood::color
diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm
index 0da1001b8d1..95d296ae679 100644
--- a/code/modules/holodeck/HolodeckObjects.dm
+++ b/code/modules/holodeck/HolodeckObjects.dm
@@ -13,120 +13,104 @@
return
// HOLOFLOOR DOES NOT GIVE A FUCK
-/turf/floor/holofloor/set_flooring(var/decl/flooring/newflooring, skip_update)
- return
-
/turf/floor/holofloor/carpet
name = "brown carpet"
icon = 'icons/turf/flooring/carpet.dmi'
icon_state = "brown"
- initial_flooring = /decl/flooring/carpet
+ _flooring = /decl/flooring/carpet
/turf/floor/holofloor/concrete
name = "brown carpet"
icon = 'icons/turf/flooring/carpet.dmi'
icon_state = "brown"
- initial_flooring = /decl/flooring/carpet
+ _flooring = /decl/flooring/carpet
/turf/floor/holofloor/concrete
name = "floor"
icon = 'icons/turf/flooring/misc.dmi'
icon_state = "concrete"
- initial_flooring = null
+ _flooring = null
/turf/floor/holofloor/tiled
name = "floor"
icon = 'icons/turf/flooring/tiles.dmi'
icon_state = "steel"
- initial_flooring = /decl/flooring/tiling
+ _flooring = /decl/flooring/tiling
/turf/floor/holofloor/tiled/dark
name = "dark floor"
icon_state = "dark"
- initial_flooring = /decl/flooring/tiling/dark
+ _flooring = /decl/flooring/tiling/dark
/turf/floor/holofloor/tiled/stone
name = "stone floor"
icon_state = "stone"
- initial_flooring = /decl/flooring/tiling/stone
+ _flooring = /decl/flooring/tiling/stone
/turf/floor/holofloor/lino
name = "lino"
icon = 'icons/turf/flooring/linoleum.dmi'
icon_state = "lino"
- initial_flooring = /decl/flooring/linoleum
+ _flooring = /decl/flooring/linoleum
/turf/floor/holofloor/wood
name = "wooden floor"
icon = 'icons/turf/flooring/wood.dmi'
icon_state = "wood"
color = WOOD_COLOR_CHOCOLATE
- initial_flooring = /decl/flooring/wood
+ _flooring = /decl/flooring/wood
/turf/floor/holofloor/grass
name = "lush grass"
icon = 'icons/turf/flooring/fakegrass.dmi'
icon_state = "grass0"
- initial_flooring = /decl/flooring/fake_grass
+ _flooring = /decl/flooring/grass/fake
/turf/floor/holofloor/snow
name = "snow"
- base_name = "snow"
- icon = 'icons/turf/floors.dmi'
- base_icon = 'icons/turf/floors.dmi'
- icon_state = "snow"
- base_icon_state = "snow"
+ icon = 'icons/turf/flooring/snow.dmi'
+ icon_state = "snow0"
+ _flooring = /decl/flooring/snow/fake
/turf/floor/holofloor/space
- icon = 'icons/turf/space.dmi'
name = "\proper space"
- icon_state = "0"
+ icon = 'icons/turf/flooring/fake_space.dmi'
+ icon_state = "space0"
+ _flooring = /decl/flooring/fake_space
/turf/floor/holofloor/reinforced
icon = 'icons/turf/flooring/tiles.dmi'
- initial_flooring = /decl/flooring/reinforced
+ _flooring = /decl/flooring/reinforced
name = "reinforced holofloor"
icon_state = "reinforced"
-/turf/floor/holofloor/space/Initialize()
- . = ..()
- icon_state = "[((x + y) ^ ~(x * y) + z) % 25]"
-
/turf/floor/holofloor/beach
desc = "Uncomfortably gritty for a hologram."
- base_desc = "Uncomfortably gritty for a hologram."
icon = 'icons/misc/beach.dmi'
- base_icon = 'icons/misc/beach.dmi'
- initial_flooring = null
+ _flooring = /decl/flooring/sand/fake
abstract_type = /turf/floor/holofloor/beach
/turf/floor/holofloor/beach/sand
name = "sand"
icon_state = "desert0"
- base_icon_state = "desert0"
/turf/floor/holofloor/beach/coastline
name = "coastline"
icon = 'icons/misc/beach2.dmi'
icon_state = "sandwater"
- base_icon = 'icons/misc/beach2.dmi'
- base_icon_state = "sandwater"
+ _flooring = /decl/flooring/sand/fake
/turf/floor/holofloor/beach/water
name = "water"
icon_state = "seashallow"
- base_icon_state = "seashallow"
+ _flooring = /decl/flooring/fake_water
/turf/floor/holofloor/desert
name = "desert sand"
- base_name = "desert sand"
desc = "Uncomfortably gritty for a hologram."
- base_desc = "Uncomfortably gritty for a hologram."
- icon_state = "0"
- base_icon_state = "0"
+ icon_state = "barren"
icon = 'icons/turf/flooring/barren.dmi'
- base_icon = 'icons/turf/flooring/barren.dmi'
- initial_flooring = null
+ _flooring = /decl/flooring/sand/fake
/turf/floor/holofloor/desert/Initialize(var/ml)
. = ..()
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_themes/radiation_bombing.dm b/code/modules/maps/template_types/random_exoplanet/planet_themes/radiation_bombing.dm
index b84dc2427c7..3eb3b962693 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_themes/radiation_bombing.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_themes/radiation_bombing.dm
@@ -33,7 +33,7 @@
source.range = 4
SSradiation.add_source(source)
crater_center.set_light(2, 0.4, PIPE_COLOR_GREEN)
- for(var/turf/floor/natural/crater in circlerangeturfs(crater_center, 3))
+ for(var/turf/floor/crater in circlerangeturfs(crater_center, 3))
if(prob(10))
new/obj/item/remains/xeno/charred(crater)
crater.handle_melting()
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_types/barren.dm b/code/modules/maps/template_types/random_exoplanet/planet_types/barren.dm
index 6e36216c345..7ef37a05e79 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_types/barren.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_types/barren.dm
@@ -13,7 +13,7 @@
/datum/level_data/planetoid/exoplanet/barren
base_area = /area/exoplanet/barren
- base_turf = /turf/floor/natural/barren
+ base_turf = /turf/floor
exterior_atmosphere = null //Generate me
exterior_atmos_temp = null //Generate me
level_generators = list(
@@ -99,7 +99,7 @@
///Generator for fauna and flora spawners for the surface of the barren exoplanet
/datum/random_map/noise/exoplanet/barren
descriptor = "barren exoplanet"
- land_type = /turf/floor/natural/barren
+ land_type = /turf/floor
flora_prob = 0.1
large_flora_prob = 0
fauna_prob = 0
@@ -111,7 +111,7 @@
/area/exoplanet/barren
name = "\improper Planetary surface"
- base_turf = /turf/floor/natural/barren
+ base_turf = /turf/floor
is_outside = OUTSIDE_YES
ambience = list(
'sound/effects/wind/wind_2_1.ogg',
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_types/chlorine.dm b/code/modules/maps/template_types/random_exoplanet/planet_types/chlorine.dm
index e9c8e13a654..c45df0faf7c 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_types/chlorine.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_types/chlorine.dm
@@ -16,7 +16,7 @@
/datum/level_data/planetoid/exoplanet/chlorine
base_area = /area/exoplanet/chlorine
- base_turf = /turf/floor/natural/chlorine_sand
+ base_turf = /turf/floor/chlorine_sand
exterior_atmosphere = null
exterior_atmos_temp = null
level_generators = list(
@@ -100,8 +100,8 @@
/datum/random_map/noise/exoplanet/chlorine
descriptor = "chlorine exoplanet"
- land_type = /turf/floor/natural/chlorine_sand
- water_type = /turf/floor/natural/chlorine_sand/marsh
+ land_type = /turf/floor/chlorine_sand
+ water_type = /turf/floor/chlorine_sand/marsh
water_level_min = 2
water_level_max = 3
fauna_prob = 2
@@ -122,4 +122,4 @@
'sound/effects/wind/desert4.ogg',
'sound/effects/wind/desert5.ogg'
)
- base_turf = /turf/floor/natural/chlorine_sand
\ No newline at end of file
+ base_turf = /turf/floor/chlorine_sand
\ No newline at end of file
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_types/desert.dm b/code/modules/maps/template_types/random_exoplanet/planet_types/desert.dm
index 50436fad324..93053b6b88e 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_types/desert.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_types/desert.dm
@@ -12,7 +12,7 @@
////////////////////////////////////////////////////////////////////////////
/datum/level_data/planetoid/exoplanet/desert
- base_turf = /turf/floor/natural/sand
+ base_turf = /turf/floor/rock/sand
base_area = /area/exoplanet/desert
exterior_atmosphere = null
exterior_atmos_temp = null
@@ -108,7 +108,7 @@
/datum/random_map/noise/exoplanet/desert
descriptor = "desert exoplanet"
- land_type = /turf/floor/natural/sand
+ land_type = /turf/floor/rock/sand
flora_prob = 5
grass_prob = 2
large_flora_prob = 0
@@ -123,7 +123,7 @@
/datum/random_map/noise/exoplanet/desert/get_appropriate_path(var/value)
. = ..()
if(noise2value(value) > 6)
- return /turf/floor/natural/dry
+ return /turf/floor/dry
////////////////////////////////////////////////////////////////////////////
// Areas
@@ -138,4 +138,4 @@
'sound/effects/wind/desert4.ogg',
'sound/effects/wind/desert5.ogg'
)
- base_turf = /turf/floor/natural/sand
+ base_turf = /turf/floor/rock/sand
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_types/grass.dm b/code/modules/maps/template_types/random_exoplanet/planet_types/grass.dm
index 0caffb22cff..f3bc7a90522 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_types/grass.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_types/grass.dm
@@ -19,7 +19,7 @@
///Surface of a grass exoplanet
/datum/level_data/planetoid/exoplanet/grass
base_area = /area/exoplanet/grass
- base_turf = /turf/floor/natural/grass/wild
+ base_turf = /turf/floor/grass/wild
exterior_atmosphere = null
exterior_atmos_temp = null
level_generators = list(
@@ -133,9 +133,9 @@
///Map generator for the grass exoplanet surface
/datum/random_map/noise/exoplanet/grass
descriptor = "grass exoplanet"
- land_type = /turf/floor/natural/grass/wild
- water_type = /turf/floor/natural/mud/water
- coast_type = /turf/floor/natural/mud
+ land_type = /turf/floor/grass/wild
+ water_type = /turf/floor/mud/water
+ coast_type = /turf/floor/mud
water_level_min = 3
flora_prob = 10
grass_prob = 50
@@ -147,7 +147,7 @@
///Area for the grass exoplanet surface
/area/exoplanet/grass
- base_turf = /turf/floor/natural/grass/wild
+ base_turf = /turf/floor/grass/wild
ambience = list(
'sound/effects/wind/wind_2_1.ogg',
'sound/effects/wind/wind_2_2.ogg',
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_types/meat.dm b/code/modules/maps/template_types/random_exoplanet/planet_types/meat.dm
index 7ab94ca69c2..90aaf8dad69 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_types/meat.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_types/meat.dm
@@ -13,7 +13,7 @@
/datum/level_data/planetoid/exoplanet/meat
base_area = /area/exoplanet/meat
- base_turf = /turf/floor/natural/meat
+ base_turf = /turf/floor/meat
exterior_atmosphere = null
exterior_atmos_temp = null
level_generators = list(
@@ -110,15 +110,15 @@
megafauna_spawn_prob = 2 //Remember to change this if more types are added.
water_level_max = 3
water_level_min = 2
- land_type = /turf/floor/natural/meat
- water_type = /turf/floor/natural/meat/acid
+ land_type = /turf/floor/meat
+ water_type = /turf/floor/meat/acid
////////////////////////////////////////////////////////////////////////////
// Areas
////////////////////////////////////////////////////////////////////////////
/area/exoplanet/meat
- base_turf = /turf/floor/natural/meat
+ base_turf = /turf/floor/meat
forced_ambience = list(
"sound/ambience/spookyspace1.ogg",
"sound/ambience/spookyspace2.ogg"
@@ -128,17 +128,16 @@
// Turfs
////////////////////////////////////////////////////////////////////////////
-/turf/floor/natural/meat
- name = "fleshy ground"
- icon = 'icons/turf/flooring/flesh.dmi'
- desc = "It's disgustingly soft to the touch. And warm. Too warm."
- dirt_color = "#c40031"
- footstep_type = /decl/footsteps/mud
- material = /decl/material/solid/organic/meat
-
-/turf/floor/natural/meat/acid
- name = "juices"
- desc = "Half-digested chunks of vines are floating in the puddle of some liquid."
- gender = PLURAL
- reagent_type = /decl/material/liquid/acid/stomach
- height = -(FLUID_SHALLOW)
+/turf/floor/meat
+ name = "fleshy ground"
+ icon = 'icons/turf/flooring/flesh.dmi'
+ icon_state = "meat"
+ _base_flooring = /decl/flooring/meat
+ floor_material = /decl/material/solid/organic/meat
+
+/turf/floor/meat/acid
+ name = "juices"
+ desc = "Half-digested chunks of vines are floating in the puddle of some liquid."
+ gender = PLURAL
+ fill_reagent_type = /decl/material/liquid/acid/stomach
+ height = -(FLUID_SHALLOW)
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_types/shrouded.dm b/code/modules/maps/template_types/random_exoplanet/planet_types/shrouded.dm
index a9433c7822c..07b282eb4da 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_types/shrouded.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_types/shrouded.dm
@@ -16,7 +16,7 @@
/datum/level_data/planetoid/exoplanet/shrouded
base_area = /area/exoplanet/shrouded
- base_turf = /turf/floor/natural/shrouded
+ base_turf = /turf/floor/shrouded
exterior_atmosphere = null
exterior_atmos_temp = null
level_generators = list(
@@ -108,8 +108,8 @@
megafauna_spawn_prob = 2 //Remember to change this if more types are added.
water_level_max = 3
water_level_min = 2
- land_type = /turf/floor/natural/shrouded
- water_type = /turf/floor/natural/shrouded/tar
+ land_type = /turf/floor/shrouded
+ water_type = /turf/floor/shrouded/tar
/datum/random_map/noise/exoplanet/shrouded/get_additional_spawns(var/value, var/turf/T)
..()
@@ -125,4 +125,4 @@
"sound/ambience/spookyspace1.ogg",
"sound/ambience/spookyspace2.ogg"
)
- base_turf = /turf/floor/natural/shrouded
+ base_turf = /turf/floor/shrouded
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_types/snow.dm b/code/modules/maps/template_types/random_exoplanet/planet_types/snow.dm
index 2aba847c6c0..6926e0d004d 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_types/snow.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_types/snow.dm
@@ -13,7 +13,7 @@
/datum/level_data/planetoid/exoplanet/snow
base_area = /area/exoplanet/snow
- base_turf = /turf/floor/natural/snow
+ base_turf = /turf/floor/snow
exterior_atmosphere = null
exterior_atmos_temp = null
level_generators = list(
@@ -95,8 +95,8 @@
flora_prob = 5
large_flora_prob = 10
water_level_max = 3
- land_type = /turf/floor/natural/snow
- water_type = /turf/floor/natural/ice
+ land_type = /turf/floor/snow
+ water_type = /turf/floor/ice
smoothing_iterations = 1
////////////////////////////////////////////////////////////////////////////
@@ -104,7 +104,7 @@
////////////////////////////////////////////////////////////////////////////
/area/exoplanet/snow
- base_turf = /turf/floor/natural/snow
+ base_turf = /turf/floor/snow
ambience = list(
'sound/effects/wind/tundra0.ogg',
'sound/effects/wind/tundra1.ogg',
diff --git a/code/modules/maps/template_types/random_exoplanet/planet_types/volcanic.dm b/code/modules/maps/template_types/random_exoplanet/planet_types/volcanic.dm
index 697b58503dd..f6f5febc037 100644
--- a/code/modules/maps/template_types/random_exoplanet/planet_types/volcanic.dm
+++ b/code/modules/maps/template_types/random_exoplanet/planet_types/volcanic.dm
@@ -16,7 +16,7 @@
/datum/level_data/planetoid/exoplanet/volcanic
base_area = /area/exoplanet/volcanic
- base_turf = /turf/floor/natural/rock/volcanic
+ base_turf = /turf/floor/rock/volcanic
exterior_atmosphere = null
exterior_atmos_temp = null
level_generators = list(
@@ -111,8 +111,8 @@
/datum/random_map/noise/exoplanet/volcanic
descriptor = "volcanic exoplanet"
smoothing_iterations = 5
- land_type = /turf/floor/natural/rock/volcanic
- water_type = /turf/floor/natural/lava
+ land_type = /turf/floor/rock/volcanic
+ water_type = /turf/floor/lava
water_level_min = 5
water_level_max = 6
fauna_prob = 1
@@ -127,4 +127,4 @@
/area/exoplanet/volcanic
forced_ambience = list('sound/ambience/magma.ogg')
- base_turf = /turf/floor/natural/rock/volcanic
+ base_turf = /turf/floor/rock/volcanic
diff --git a/code/modules/maps/template_types/random_exoplanet/random_map.dm b/code/modules/maps/template_types/random_exoplanet/random_map.dm
index 193a5167eef..95994ad4327 100644
--- a/code/modules/maps/template_types/random_exoplanet/random_map.dm
+++ b/code/modules/maps/template_types/random_exoplanet/random_map.dm
@@ -153,8 +153,8 @@
/datum/random_map/noise/exoplanet/mantle
descriptor = "planetary mantle"
smoothing_iterations = 3
- land_type = /turf/floor/natural/rock/volcanic
- water_type = /turf/floor/natural/lava
+ land_type = /turf/floor/rock/volcanic
+ water_type = /turf/floor/lava
water_level_min = 4
water_level_max = 6
fauna_prob = 0
@@ -166,7 +166,7 @@
//Random map generator to create rock walls underground
/datum/random_map/automata/cave_system/mantle
descriptor = "planetary mantle caves"
- target_turf_type = /turf/floor/natural/rock/volcanic //Only let it apply to non-lava turfs
+ target_turf_type = /turf/floor/rock/volcanic //Only let it apply to non-lava turfs
floor_type = null
wall_type = /turf/wall/natural
diff --git a/code/modules/maps/template_types/random_exoplanet/random_planet_level_data.dm b/code/modules/maps/template_types/random_exoplanet/random_planet_level_data.dm
index 86c7758698f..2a5173d788d 100644
--- a/code/modules/maps/template_types/random_exoplanet/random_planet_level_data.dm
+++ b/code/modules/maps/template_types/random_exoplanet/random_planet_level_data.dm
@@ -15,14 +15,14 @@
///Level data for generating surface levels on exoplanets
/datum/level_data/planetoid/exoplanet
base_area = /area/exoplanet
- base_turf = /turf/floor/natural/dirt
+ base_turf = /turf/floor/dirt
daycycle_id = null // will be generated
daycycle_type = /datum/daycycle/exoplanet
///Level data for generating underground levels on exoplanets
/datum/level_data/planetoid/exoplanet/underground
base_area = /area/exoplanet/underground
- base_turf = /turf/floor/natural/rock
+ base_turf = /turf/floor/rock
level_generators = list(
/datum/random_map/noise/exoplanet/mantle,
/datum/random_map/automata/cave_system/mantle,
diff --git a/code/modules/materials/_materials.dm b/code/modules/materials/_materials.dm
index 109671b7b88..aa824ec2453 100644
--- a/code/modules/materials/_materials.dm
+++ b/code/modules/materials/_materials.dm
@@ -134,6 +134,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay)
var/table_icon_base = "metal"
var/table_icon_reinforced = "reinf_metal"
+ var/bench_icon = 'icons/obj/structures/benches.dmi'
+ var/pew_icon = 'icons/obj/structures/pews.dmi'
+
var/list/stack_origin_tech = @'{"materials":1}' // Research level for stacks.
// Attributes
diff --git a/code/modules/materials/definitions/solids/materials_solid_ice.dm b/code/modules/materials/definitions/solids/materials_solid_ice.dm
index a3b037c4e5c..dd69df88531 100644
--- a/code/modules/materials/definitions/solids/materials_solid_ice.dm
+++ b/code/modules/materials/definitions/solids/materials_solid_ice.dm
@@ -34,12 +34,13 @@
liquid_name = "water"
solid_name = "snow"
gas_name = "steam"
+ color = COLOR_WHITE
codex_name = null
uid = "solid_snow"
hardness = MAT_VALUE_MALLEABLE
dug_drop_type = /obj/item/stack/material/ore/handful
default_solid_form = /obj/item/stack/material/ore/handful
- can_backfill_turf_type = /turf/floor/natural/snow
+ can_backfill_turf_type = /turf/floor/snow
/decl/material/solid/ice/aspium
name = "aspium"
diff --git a/code/modules/materials/definitions/solids/materials_solid_mineral.dm b/code/modules/materials/definitions/solids/materials_solid_mineral.dm
index eeb01b5f67a..2be84c6c5df 100644
--- a/code/modules/materials/definitions/solids/materials_solid_mineral.dm
+++ b/code/modules/materials/definitions/solids/materials_solid_mineral.dm
@@ -234,7 +234,7 @@
)
dug_drop_type = /obj/item/stack/material/ore/handful
default_solid_form = /obj/item/stack/material/ore/handful
- can_backfill_turf_type = /turf/floor/natural/sand
+ can_backfill_turf_type = /turf/floor/rock/sand
/decl/material/solid/clay
name = "clay"
@@ -257,7 +257,7 @@
melting_point = null // Clay is already almost a liquid...
// lower than the temperature expected from a kiln so that clay can be used to make bricks to make a high-temperature kiln.
bakes_into_at_temperature = 950 CELSIUS
- can_backfill_turf_type = /turf/floor/natural/clay
+ can_backfill_turf_type = /turf/floor/clay
/decl/material/solid/soil
name = "soil"
@@ -273,8 +273,8 @@
dug_drop_type = /obj/item/stack/material/lump/large
tillable = TRUE
can_backfill_turf_type = list(
- /turf/floor/natural/mud,
- /turf/floor/natural/dirt
+ /turf/floor/mud,
+ /turf/floor/dirt
)
/decl/material/solid/hematite
diff --git a/code/modules/materials/definitions/solids/materials_solid_wood.dm b/code/modules/materials/definitions/solids/materials_solid_wood.dm
index e57510127e3..9dea72c5cdd 100644
--- a/code/modules/materials/definitions/solids/materials_solid_wood.dm
+++ b/code/modules/materials/definitions/solids/materials_solid_wood.dm
@@ -1,9 +1,10 @@
/decl/material/solid/organic/wood
- name = "wood"
+ name = "oak"
uid = "solid_wood"
liquid_name = "wood pulp"
- lore_text = "A fibrous structural material harvested from an indeterminable plant. Don't get a splinter."
- adjective_name = "wooden"
+ adjective_name = "oaken"
+ lore_text = "Oak timber is strong yet simple to carve, making it a fine choice for wooden handicrafts."
+ adjective_name = "oaken"
color = WOOD_COLOR_GENERIC
integrity = 75
icon_base = 'icons/turf/walls/wood.dmi'
@@ -15,7 +16,8 @@
'icons/turf/walls/log.dmi' = TRUE,
'icons/turf/walls/metal.dmi' = TRUE
)
- table_icon_base = "wood"
+ bench_icon = 'icons/obj/structures/wood_benches.dmi'
+ pew_icon = 'icons/obj/structures/wood_pews.dmi'
explosion_resistance = 2
shard_type = SHARD_SPLINTER
shard_can_repair = 0 // you can't weld splinters back into planks
@@ -51,6 +53,7 @@
/decl/material/solid/organic/wood/fungal
name = "towercap"
+ adjective_name = "towercap"
uid = "solid_wood_fungal"
color = "#e6d8dd"
hardness = MAT_VALUE_FLEXIBLE + 10
@@ -59,6 +62,7 @@
name = "holographic wood"
uid = "solid_holographic_wood"
color = WOOD_COLOR_CHOCOLATE //the very concept of wood should be brown
+ adjective_name = "holowood"
holographic = TRUE
/decl/material/solid/organic/wood/mahogany
diff --git a/code/modules/materials/material_stack_misc.dm b/code/modules/materials/material_stack_misc.dm
index 6ac557a3969..cf8ddd36474 100644
--- a/code/modules/materials/material_stack_misc.dm
+++ b/code/modules/materials/material_stack_misc.dm
@@ -145,6 +145,12 @@
/obj/item/stack/material/bundle/special_crafting_check()
return !dried_type || drying_wetness <= 0
+/obj/item/stack/material/bundle/grass
+ material = /decl/material/solid/organic/plantmatter/grass
+
+/obj/item/stack/material/bundle/grass/dry
+ material = /decl/material/solid/organic/plantmatter/grass/dry
+
/obj/item/stack/material/strut
name = "struts"
singular_name = "strut"
diff --git a/code/modules/mob/examine.dm b/code/modules/mob/examine.dm
index e2c78710061..033c9499a24 100644
--- a/code/modules/mob/examine.dm
+++ b/code/modules/mob/examine.dm
@@ -53,8 +53,8 @@
// Show our equipment, held items, desc, etc.
var/decl/pronouns/pronouns = get_visible_pronouns(hideflags)
- to_chat(user, "")
+ // to_chat(user, "
")
+ // to_chat(user, "") // see above
diff --git a/code/modules/mob/living/bot/floorbot.dm b/code/modules/mob/living/bot/floorbot.dm
index 16a14aed1ba..d3dc81be5c3 100644
--- a/code/modules/mob/living/bot/floorbot.dm
+++ b/code/modules/mob/living/bot/floorbot.dm
@@ -130,7 +130,7 @@
if(emagged)
return 1
else
- return (amount && (T.is_floor_damaged() || (improvefloors && !T.flooring)))
+ return (amount && (T.is_floor_damaged() || (improvefloors && !T.has_flooring())))
/mob/living/bot/floorbot/UnarmedAttack(var/atom/A, var/proximity)
@@ -148,8 +148,8 @@
var/turf/floor/F = A
busy = 1
update_icon()
- if(F.flooring)
- visible_message("[src] begins to tear the floor tile from the floor.")
+ if(F.has_flooring())
+ visible_message("[src] begins to tear up \the [F].")
if(do_after(src, 50, F))
F.break_tile_to_plating()
addTiles(1)
@@ -169,18 +169,18 @@
anchored = TRUE
if(do_after(src, 50, F))
if(F.is_floor_damaged())
- F.make_plating()
+ F.set_flooring(null)
anchored = FALSE
target = null
busy = 0
update_icon()
- else if(!F.flooring && amount)
+ else if(!F.has_flooring() && amount)
busy = 1
update_icon()
visible_message("[src] begins to improve the floor.")
anchored = TRUE
if(do_after(src, 50, F))
- if(!F.flooring)
+ if(!F.has_flooring())
F.set_flooring(GET_DECL(floor_build_type))
addTiles(-1)
anchored = FALSE
diff --git a/code/modules/mob/living/living_attackhand.dm b/code/modules/mob/living/living_attackhand.dm
index 030b366fda1..af16a0e793b 100644
--- a/code/modules/mob/living/living_attackhand.dm
+++ b/code/modules/mob/living/living_attackhand.dm
@@ -46,7 +46,7 @@
/mob/living/proc/default_grab_interaction(var/mob/user)
SHOULD_CALL_PARENT(TRUE)
- return (scoop_check(user) && get_scooped(user, user)) || try_make_grab(user)
+ return scoop_check(user) ? get_scooped(user, user) : try_make_grab(user)
// This proc is where movable atoms handle being grabbed, but we handle it additionally in
// default_grab_interaction, so we override it here to return FALSE and avoid double-grabbing.
diff --git a/code/modules/mob/living/living_genetics.dm b/code/modules/mob/living/living_genetics.dm
index fd0c40638a0..c33da0160f9 100644
--- a/code/modules/mob/living/living_genetics.dm
+++ b/code/modules/mob/living/living_genetics.dm
@@ -16,7 +16,7 @@
return _genetic_conditions
/mob/living/can_have_genetic_conditions()
- return !(get_bodytype()?.body_flags & BODY_FLAG_NO_DNA)
+ return has_genetic_information()
/mob/living/has_genetic_condition(condition_type)
if(!LAZYLEN(_genetic_conditions))
diff --git a/code/modules/mob/living/living_throw.dm b/code/modules/mob/living/living_throw.dm
index db543f0543f..4c6e4d4ccba 100644
--- a/code/modules/mob/living/living_throw.dm
+++ b/code/modules/mob/living/living_throw.dm
@@ -65,10 +65,10 @@
item.forceMove(get_turf(target))
return TRUE
- else if(!try_unequip(item))
+ else if(!try_unequip(item, play_dropsound = place_item))
return FALSE
- if(!istype(item) || QDELETED(item) || !try_unequip(item, get_turf(target), play_dropsound = place_item) || !isturf(item.loc))
+ if(!istype(item) || QDELETED(item) || !isturf(item.loc))
return FALSE
if(place_item)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 519d5dc6817..64d68301772 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -243,7 +243,7 @@
italics = 1
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
- get_mobs_and_objs_in_view_fast(T, message_range, listening, listening_obj, /datum/client_preference/ghost_ears)
+ get_listeners_in_range(T, message_range, listening, listening_obj, /datum/client_preference/ghost_ears)
var/speech_bubble_state = check_speech_punctuation_state(message)
var/speech_state_modifier = get_speech_bubble_state_modifier()
@@ -273,7 +273,7 @@
var/eavesdroping_range = 5
var/list/eavesdroping = list()
var/list/eavesdroping_obj = list()
- get_mobs_and_objs_in_view_fast(T, eavesdroping_range, eavesdroping, eavesdroping_obj)
+ get_listeners_in_range(T, eavesdroping_range, eavesdroping, eavesdroping_obj)
eavesdroping -= listening
eavesdroping_obj -= listening_obj
for(var/mob/M in eavesdroping)
diff --git a/code/modules/mob/living/simple_animal/hostile/faithful_hound.dm b/code/modules/mob/living/simple_animal/hostile/faithful_hound.dm
index e10628527cd..ac15b145c00 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithful_hound.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithful_hound.dm
@@ -29,7 +29,7 @@
var/aggressiveness = 0 //The closer somebody is to us, the more aggressive we are
var/list/mobs = list()
var/list/objs = list()
- get_mobs_and_objs_in_view_fast(get_turf(body), 5, mobs, objs, 0)
+ get_listeners_in_range(get_turf(body), 5, mobs, objs, 0)
for(var/mob/living/mailman in mobs)
if((mailman == body) || is_friend(mailman) || mailman.faction == body.faction)
continue
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index f434d3b7259..f99ee59aaf4 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -118,7 +118,7 @@
var/turf/T = get_turf(src)
var/list/mobs = list()
var/list/objs = list()
- get_mobs_and_objs_in_view_fast(T, range, mobs, objs, check_ghosts)
+ get_listeners_in_range(T, range, mobs, objs, check_ghosts)
for(var/o in objs)
var/obj/O = o
@@ -158,7 +158,7 @@
var/turf/T = get_turf(src)
var/list/mobs = list()
var/list/objs = list()
- get_mobs_and_objs_in_view_fast(T, hearing_distance, mobs, objs, check_ghosts)
+ get_listeners_in_range(T, hearing_distance, mobs, objs, check_ghosts)
for(var/m in mobs)
var/mob/M = m
@@ -1392,4 +1392,3 @@
/mob/proc/can_twohand_item(obj/item/item)
return FALSE
-
diff --git a/code/modules/mob/mob_layering.dm b/code/modules/mob/mob_layering.dm
index 39998aeac88..d98e8923528 100644
--- a/code/modules/mob/mob_layering.dm
+++ b/code/modules/mob/mob_layering.dm
@@ -96,7 +96,7 @@
new_pixel_z += structure_offset
// Update offsets from loc.
- var/turf/floor/natural/ext = loc
+ var/turf/floor/ext = loc
if(istype(ext) && ext.height < 0)
new_pixel_z += ext.pixel_z
diff --git a/code/modules/mob/mob_snapshot.dm b/code/modules/mob/mob_snapshot.dm
index 8d9636d3f87..4f5441a8933 100644
--- a/code/modules/mob/mob_snapshot.dm
+++ b/code/modules/mob/mob_snapshot.dm
@@ -15,7 +15,7 @@
var/list/sprite_accessories
var/list/genetic_conditions
-/datum/mob_snapshot/New(mob/living/donor, force)
+/datum/mob_snapshot/New(mob/living/donor, genetic_info_only = FALSE)
real_name = donor?.real_name || "unknown"
eye_color = donor?.get_eye_colour() || COLOR_BLACK
@@ -29,7 +29,7 @@
for(var/obj/item/organ/external/limb in donor?.get_external_organs())
// Discard anything not relating to our core/original bodytype and species.
// Does this need to be reviewed for Outreach serde?
- if(limb.bodytype == root_bodytype && limb.species == root_species && (force || !BP_IS_PROSTHETIC(limb)))
+ if(limb.bodytype == root_bodytype && limb.species == root_species && (!genetic_info_only || !BP_IS_PROSTHETIC(limb)))
var/list/limb_sprite_acc = limb.get_sprite_accessories(copy = TRUE)
if(length(limb_sprite_acc))
LAZYSET(sprite_accessories, limb.organ_tag, limb_sprite_acc)
@@ -85,5 +85,5 @@
target.update_eyes()
return TRUE
-/mob/proc/get_mob_snapshot(force = FALSE)
- return (force || has_genetic_information()) ? new /datum/mob_snapshot(src, force) : null
+/mob/proc/get_mob_snapshot(check_dna = FALSE)
+ return (!check_dna || has_genetic_information()) ? new /datum/mob_snapshot(src, genetic_info_only = check_dna) : null
diff --git a/code/modules/mob_holder/holder_mobs.dm b/code/modules/mob_holder/holder_mobs.dm
index f2ba2cc988c..ec0527a41ed 100644
--- a/code/modules/mob_holder/holder_mobs.dm
+++ b/code/modules/mob_holder/holder_mobs.dm
@@ -28,13 +28,13 @@
to_chat(target, SPAN_NOTICE("\The [src] clambers onto you!"))
to_chat(initiator, SPAN_NOTICE("You climb up onto \the [target]!"))
else
+ if(!ai?.scooped_by(initiator))
+ return FALSE // The AI canceled the scooping.
+
if(!target.put_in_hands(H))
to_chat(initiator, SPAN_WARNING("Your hands are full!"))
return FALSE
- if(!ai?.scooped_by(initiator))
- return FALSE // The AI canceled the scooping.
-
to_chat(initiator, SPAN_NOTICE("You scoop up \the [src]!"))
to_chat(src, SPAN_NOTICE("\The [initiator] scoops you up!"))
diff --git a/code/modules/multiz/level_data.dm b/code/modules/multiz/level_data.dm
index 42575450860..96254e43b06 100644
--- a/code/modules/multiz/level_data.dm
+++ b/code/modules/multiz/level_data.dm
@@ -181,6 +181,8 @@
initialize_level_id()
SSmapping.register_level_data(src)
+ setup_ambient()
+ setup_exterior_atmosphere()
if(SSmapping.initialized && !defer_level_setup)
setup_level_data()
@@ -227,8 +229,6 @@
return //Since we can defer setup, make sure we only setup once
setup_level_bounds()
- setup_ambient()
- setup_exterior_atmosphere()
setup_strata()
if(!skip_gen)
generate_level()
@@ -556,7 +556,8 @@
// Accessors
//
/datum/level_data/proc/get_exterior_atmosphere()
- if(!exterior_atmosphere)
+ if(exterior_atmosphere && !istype(exterior_atmosphere))
+ PRINT_STACK_TRACE("Attempting to retrieve exterior atmosphere before it is set up!")
return
var/datum/gas_mixture/gas = new
gas.copy_from(exterior_atmosphere)
@@ -737,7 +738,7 @@ INITIALIZE_IMMEDIATE(/obj/abstract/level_data_spawner)
return ..()
/datum/level_data/mining_level/asteroid
- base_turf = /turf/floor/natural/barren
+ base_turf = /turf/floor
level_generators = list(
/datum/random_map/automata/cave_system,
/datum/random_map/noise/ore
diff --git a/code/modules/organs/external/_external.dm b/code/modules/organs/external/_external.dm
index d262957ed4c..4b7aea6abdf 100644
--- a/code/modules/organs/external/_external.dm
+++ b/code/modules/organs/external/_external.dm
@@ -550,7 +550,7 @@
//Helper proc used by various tools for repairing robot limbs
/obj/item/organ/external/proc/robo_repair(var/repair_amount, var/damage_type, var/damage_desc, obj/item/tool, mob/living/user)
- if((!BP_IS_PROSTHETIC(src)))
+ if(!BP_IS_PROSTHETIC(src))
return 0
var/damage_amount
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index a3dcc56f555..2d8f8ac2943 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -93,11 +93,10 @@
// this can be fine if appearance data with species is passed
log_debug("obj/item/organ/setup(): [src] had null bodytype, with an owner with null bodytype!")
bodytype = new_bodytype // used in later setup procs
- if((bodytype?.body_flags & BODY_FLAG_NO_DNA) || !supplied_appearance)
- // set_bodytype will unset invalid appearance data anyway, so set_dna(null) is unnecessary
- set_species(owner?.get_species() || global.using_map.default_species)
- else
+ if(supplied_appearance)
copy_from_mob_snapshot(supplied_appearance)
+ else
+ set_species(owner?.get_species() || global.using_map.default_species)
//Called on initialization to add the neccessary reagents
@@ -116,9 +115,6 @@
add_to_reagents(reagent_to_add, reagents.maximum_volume)
/obj/item/organ/proc/copy_from_mob_snapshot(var/datum/mob_snapshot/supplied_appearance)
- if(istype(bodytype) && (bodytype.body_flags & BODY_FLAG_NO_DNA))
- QDEL_NULL(organ_appearance)
- return
if(supplied_appearance != organ_appearance) // Hacky. Is this ever used? Do any organs ever have DNA set before setup_as_organic?
QDEL_NULL(organ_appearance)
organ_appearance = supplied_appearance.Clone()
@@ -152,8 +148,6 @@
if(reagents)
reagents.clear_reagents()
populate_reagents()
- if(bodytype.body_flags & BODY_FLAG_NO_DNA)
- QDEL_NULL(organ_appearance)
reset_status()
return TRUE
diff --git a/code/modules/organs/prosthetics/prosthetics_manufacturer.dm b/code/modules/organs/prosthetics/prosthetics_manufacturer.dm
index 74ca60e49c2..e687a696f63 100644
--- a/code/modules/organs/prosthetics/prosthetics_manufacturer.dm
+++ b/code/modules/organs/prosthetics/prosthetics_manufacturer.dm
@@ -7,6 +7,7 @@
is_robotic = TRUE
body_flags = BODY_FLAG_NO_DNA | BODY_FLAG_NO_DEFIB | BODY_FLAG_NO_STASIS | BODY_FLAG_NO_PAIN | BODY_FLAG_NO_EAT
material = /decl/material/solid/metal/steel
+ appearance_flags = HAS_EYE_COLOR
eye_flash_mod = 1
eye_darksight_range = 2
associated_gender = null
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index f1fb7081e41..28b6fbc3c98 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -552,17 +552,15 @@ By design, d1 is the smallest direction and d2 is the highest
//you can use wires to heal robotics
/obj/item/stack/cable_coil/use_on_mob(mob/living/target, mob/living/user, animate = TRUE)
- if(ishuman(target) && user.a_intent == I_HELP)
- var/mob/living/human/H = target
- var/obj/item/organ/external/S = GET_EXTERNAL_ORGAN(H, user.get_target_zone())
- if(!S || !BP_IS_PROSTHETIC(S) || user.a_intent != I_HELP)
- return ..()
- if(BP_IS_BRITTLE(S))
- to_chat(user, SPAN_WARNING("\The [H]'s [S.name] is hard and brittle - \the [src] cannot repair it."))
- return TRUE
- var/use_amt = min(src.amount, ceil(S.burn_dam/3), 5)
- if(can_use(use_amt))
- if(S.robo_repair(3*use_amt, BURN, "some damaged wiring", src, user))
+ var/obj/item/organ/external/affecting = istype(target) && GET_EXTERNAL_ORGAN(target, user?.get_target_zone())
+ if(affecting && user.a_intent == I_HELP)
+ if(!affecting.is_robotic())
+ to_chat(user, SPAN_WARNING("\The [target]'s [affecting.name] is not robotic. \The [src] cannot repair it."))
+ else if(BP_IS_BRITTLE(affecting))
+ to_chat(user, SPAN_WARNING("\The [target]'s [affecting.name] is hard and brittle. \The [src] cannot repair it."))
+ else
+ var/use_amt = min(src.amount, ceil(affecting.burn_dam/3), 5)
+ if(can_use(use_amt) && affecting.robo_repair(3*use_amt, BURN, "some damaged wiring", src, user))
use(use_amt)
return TRUE
return ..()
@@ -648,10 +646,10 @@ By design, d1 is the smallest direction and d2 is the highest
/obj/item/stack/cable_coil/cyborg/can_merge_stacks(var/obj/item/stack/other)
return TRUE
-/obj/item/stack/cable_coil/transfer_to(obj/item/stack/cable_coil/S)
- if(!istype(S))
+/obj/item/stack/cable_coil/transfer_to(obj/item/stack/cable_coil/coil)
+ if(!istype(coil))
return 0
- if(!(can_merge_stacks(S) || S.can_merge_stacks(src)))
+ if(!(can_merge_stacks(coil) || coil.can_merge_stacks(src)))
return 0
return ..()
diff --git a/code/modules/power/geothermal/_geothermal.dm b/code/modules/power/geothermal/_geothermal.dm
index 0c3e2216bf2..5f76fa6dd0f 100644
--- a/code/modules/power/geothermal/_geothermal.dm
+++ b/code/modules/power/geothermal/_geothermal.dm
@@ -83,13 +83,13 @@ var/global/const/MAX_GEOTHERMAL_PRESSURE = 12000
. = ..()
if(!loc)
return INITIALIZE_HINT_QDEL
- for(var/turf/floor/natural/seafloor/T in RANGE_TURFS(loc, 5))
+ for(var/turf/floor/seafloor/T in RANGE_TURFS(loc, 5))
var/dist = get_dist(loc, T)-1
if(prob(100 - (dist * 20)))
if(prob(25))
- T = T.ChangeTurf(/turf/floor/natural/clay)
+ T = T.ChangeTurf(/turf/floor/clay)
else
- T = T.ChangeTurf(/turf/floor/natural/mud)
+ T = T.ChangeTurf(/turf/floor/mud)
if(prob(50 - (dist * 10)))
new /obj/random/seaweed(T)
diff --git a/code/modules/projectiles/guns/energy/capacitor.dm b/code/modules/projectiles/guns/energy/capacitor.dm
index 100ba0b58b7..7cf1b85b66c 100644
--- a/code/modules/projectiles/guns/energy/capacitor.dm
+++ b/code/modules/projectiles/guns/energy/capacitor.dm
@@ -269,7 +269,7 @@ var/global/list/laser_wavelengths
/obj/item/gun/energy/capacitor/rifle/setup_power_supply(loaded_cell_type, accepted_cell_type, power_supply_extension_type, charge_value)
loaded_cell_type = loaded_cell_type || /obj/item/cell/super
- return ..(loaded_cell_type, accepted_cell_type, power_supply_extension_type, charge_value)
+ return ..(loaded_cell_type, accepted_cell_type, /datum/extension/loaded_cell, charge_value)
/obj/item/gun/energy/capacitor/rifle/linear_fusion
name = "linear fusion rifle"
diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm
index 8da6d6c6ea9..cf4b659eb7e 100644
--- a/code/modules/projectiles/guns/energy/laser.dm
+++ b/code/modules/projectiles/guns/energy/laser.dm
@@ -101,4 +101,4 @@
desc = "A G40E carbine, designed to kill with concentrated energy blasts. Uses removable energy cells."
/obj/item/gun/energy/laser/reloadable/setup_power_supply(loaded_cell_type, accepted_cell_type, power_supply_extension_type, charge_value)
- return ..(/obj/item/cell/gun, /obj/item/cell/gun, power_supply_extension_type, charge_value)
+ return ..(/obj/item/cell/gun, /obj/item/cell/gun, /datum/extension/loaded_cell, charge_value)
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index b043517b744..d69f9bdef70 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -134,6 +134,7 @@
/obj/item/gun/energy/plasmacutter/Initialize()
. = ..()
set_extension(src, /datum/extension/tool, list(TOOL_SAW = TOOL_QUALITY_BAD))
+ set_extension(src, /datum/extension/demolisher/energy)
/obj/item/gun/energy/plasmacutter/get_heat()
. = max(..(), 3800)
diff --git a/code/modules/random_map/automata/caves.dm b/code/modules/random_map/automata/caves.dm
index 8d6d4b523ac..d12f5a79204 100644
--- a/code/modules/random_map/automata/caves.dm
+++ b/code/modules/random_map/automata/caves.dm
@@ -2,7 +2,7 @@
iterations = 5
descriptor = "moon caves"
wall_type = /turf/wall/natural
- floor_type = /turf/floor/natural/barren
+ floor_type = /turf/floor
target_turf_type = /turf/unsimulated/mask
var/sparse_mineral_turf = /turf/wall/natural/random
diff --git a/code/modules/random_map/noise/desert.dm b/code/modules/random_map/noise/desert.dm
index 08605c01e97..05146ce50e2 100644
--- a/code/modules/random_map/noise/desert.dm
+++ b/code/modules/random_map/noise/desert.dm
@@ -14,9 +14,9 @@
if(isnull(val)) val = 0
switch(val)
if(0 to 1)
- return /turf/floor/natural/sand/water
+ return /turf/floor/rock/sand/water
else
- return /turf/floor/natural/sand
+ return /turf/floor/rock/sand
/datum/random_map/noise/desert/get_additional_spawns(var/value, var/turf/T)
var/val = min(9,max(0,round((value/cell_range)*10)))
diff --git a/code/modules/random_map/noise/forage.dm b/code/modules/random_map/noise/forage.dm
index 93ddba8a3e2..72dd620ec1b 100644
--- a/code/modules/random_map/noise/forage.dm
+++ b/code/modules/random_map/noise/forage.dm
@@ -122,12 +122,12 @@
var/place_type
if(T.is_outside())
- if(istype(T, /turf/floor/natural/rock))
+ if(istype(T, /turf/floor/rock))
if(prob(15)) // Static as current map has limited amount of rock turfs
var/rock_type = SAFEPICK(forage["rocks"])
new rock_type(T)
return
- else if(istype(T, /turf/floor/natural/grass))
+ else if(istype(T, /turf/floor/grass))
if(prob(parse_value * tree_weight))
if(length(trees))
var/tree_type = pickweight(trees)
@@ -135,17 +135,17 @@
return
place_prob = parse_value * forage_weight
place_type = SAFEPICK(forage["grass"])
- else if(istype(T, /turf/floor/natural/mud/water/deep))
+ else if(istype(T, /turf/floor/mud/water/deep))
place_prob = parse_value * forage_weight
place_type = SAFEPICK(forage["riverbed"])
- else if(istype(T, /turf/floor/natural/mud/water))
+ else if(istype(T, /turf/floor/mud/water))
place_prob = parse_value * forage_weight
place_type = SAFEPICK(forage["shallows"])
- else if(istype(T, /turf/floor/natural/mud))
+ else if(istype(T, /turf/floor/mud))
place_prob = parse_value * forage_weight
place_type = SAFEPICK(forage["riverbank"]) // no entries by default, expanded on subtypes
else
- if(istype(T, /turf/floor/natural/mud) && !istype(T, /turf/floor/natural/mud/water/deep))
+ if(istype(T, /turf/floor/mud) && !istype(T, /turf/floor/mud/water/deep))
if(prob(parse_value * cave_tree_weight))
if(length(cave_trees))
var/tree_type = pick(cave_trees)
@@ -153,10 +153,10 @@
return
place_prob = parse_value * cave_forage_weight * 2
place_type = SAFEPICK(forage["caves"])
- else if(istype(T, /turf/floor/natural/dirt))
+ else if(istype(T, /turf/floor/dirt))
place_prob = parse_value * cave_forage_weight
place_type = SAFEPICK(forage["caves"])
- else if(istype(T, /turf/floor/natural/mud/water))
+ else if(istype(T, /turf/floor/mud/water))
place_prob = parse_value * cave_forage_weight
place_type = SAFEPICK(forage["cave_shallows"])
diff --git a/code/modules/random_map/noise/magma.dm b/code/modules/random_map/noise/magma.dm
index c02084c48fc..f6130645dba 100644
--- a/code/modules/random_map/noise/magma.dm
+++ b/code/modules/random_map/noise/magma.dm
@@ -3,7 +3,7 @@
/datum/random_map/noise/volcanism
descriptor = "volcanism"
smoothing_iterations = 6
- target_turf_type = /turf/floor/natural
+ target_turf_type = /turf/floor
// Get rid of those dumb little single-tile volcanic areas.
/datum/random_map/noise/volcanism/cleanup()
@@ -38,8 +38,8 @@
/datum/random_map/noise/volcanism/get_additional_spawns(var/value, var/turf/T)
if(value>=178)
- if(istype(T,/turf/floor/natural/barren))
- T.ChangeTurf(/turf/floor/natural/lava)
+ if(istype(T,/turf/floor))
+ T.ChangeTurf(/turf/floor/lava)
else if(istype(T,/turf/wall/natural))
var/turf/wall/natural/M = T
- M.floor_type = /turf/floor/natural/lava
\ No newline at end of file
+ M.floor_type = /turf/floor/lava
\ No newline at end of file
diff --git a/code/modules/random_map/noise/seafloor.dm b/code/modules/random_map/noise/seafloor.dm
index 496f68a045e..a6d11088b08 100644
--- a/code/modules/random_map/noise/seafloor.dm
+++ b/code/modules/random_map/noise/seafloor.dm
@@ -1,22 +1,22 @@
/datum/random_map/noise/seafloor
descriptor = "seafloor (roundstart)"
smoothing_iterations = 3
- target_turf_type = /turf/floor/natural/seafloor/flooded
+ target_turf_type = /turf/floor/seafloor/flooded
/datum/random_map/noise/seafloor/replace_space
descriptor = "seafloor (replace)"
target_turf_type = TRUE
/datum/random_map/noise/seafloor/replace_space/get_appropriate_path(var/value)
- return /turf/floor/natural/seafloor/flooded
+ return /turf/floor/seafloor/flooded
/datum/random_map/noise/seafloor/get_appropriate_path(var/value)
var/val = min(9,max(0,round((value/cell_range)*10)))
switch(val)
if(6)
- return /turf/floor/natural/clay/flooded
+ return /turf/floor/clay/flooded
if(7 to 9)
- return /turf/floor/natural/mud/flooded
+ return /turf/floor/mud/flooded
/datum/random_map/noise/seafloor/get_additional_spawns(var/value, var/turf/T)
var/val = min(9,max(0,round((value/cell_range)*10)))
diff --git a/code/modules/random_map/noise/tundra.dm b/code/modules/random_map/noise/tundra.dm
index 8c4d39d4355..e8a05b43f39 100644
--- a/code/modules/random_map/noise/tundra.dm
+++ b/code/modules/random_map/noise/tundra.dm
@@ -36,9 +36,9 @@
if(isnull(val)) val = 0
switch(val)
if(0 to 4)
- return /turf/floor/natural/mud/water
+ return /turf/floor/mud/water
else
- return /turf/floor/natural/snow
+ return /turf/floor/snow
/datum/random_map/noise/tundra/get_additional_spawns(var/value, var/turf/T)
var/val = min(9,max(0,round((value/cell_range)*10)))
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index 13e9eb97816..ebf78f1f900 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -235,7 +235,7 @@
if(!name)
name = reagents.get_primary_reagent_name()
P.label_text = name
- P.update_container_name()
+ P.update_name()
P.lid_color = bottle_lid_color
P.label_color = bottle_label_color
reagents.trans_to_obj(P,60)
diff --git a/code/modules/reagents/chems/chems_compounds.dm b/code/modules/reagents/chems/chems_compounds.dm
index 3fa592487ec..04e6da8e7fb 100644
--- a/code/modules/reagents/chems/chems_compounds.dm
+++ b/code/modules/reagents/chems/chems_compounds.dm
@@ -246,20 +246,14 @@
/decl/material/liquid/mutagenics/affect_blood(var/mob/living/M, var/removed, var/datum/reagents/holder)
. = ..()
- if(M.isSynthetic())
+ if(!M.has_genetic_information())
return
- var/mob/living/human/H = M
- if(istype(H) && (H.get_bodytype()?.body_flags & BODY_FLAG_NO_DNA))
- return
-
if(prob(removed * 0.1)) // Approx. one mutation per 10 injected/20 ingested/30 touching units
- H.set_unique_enzymes(num2text(random_id(/mob, 1000000, 9999999)))
+ M.set_unique_enzymes(num2text(random_id(/mob, 1000000, 9999999)))
if(prob(98))
M.add_genetic_condition(pick(decls_repository.get_decls_of_type(/decl/genetic_condition/disability)))
else
M.add_genetic_condition(pick(decls_repository.get_decls_of_type(/decl/genetic_condition/superpower)))
-
-
M.apply_damage(10 * removed, IRRADIATE, armor_pen = 100)
/decl/material/liquid/lactate
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index e0911fc60ee..d3fee37783c 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -25,10 +25,6 @@
if(!possible_transfer_amounts)
src.verbs -= /obj/item/chems/verb/set_amount_per_transfer_from_this
-/obj/item/chems/set_custom_name(var/new_name)
- base_name = new_name
- update_container_name()
-
/obj/item/chems/set_custom_desc(var/new_desc)
base_desc = new_desc
update_container_desc()
@@ -42,24 +38,18 @@
return TRUE
return FALSE
-/obj/item/chems/proc/get_base_name()
- if(!base_name)
- base_name = initial(name)
- . = base_name
-
/obj/item/chems/on_update_icon()
. = ..()
if(detail_state)
add_overlay(overlay_image(icon, "[initial(icon_state)][detail_state]", detail_color || COLOR_WHITE, RESET_COLOR))
-/obj/item/chems/proc/update_container_name()
- var/newname = get_base_name()
- if(material_alteration & MAT_FLAG_ALTERATION_NAME)
- newname = "[material.solid_name] [newname]"
+/obj/item/chems/update_name()
+ . = ..() // handles material, etc
+ var/newname = name
if(presentation_flags & PRESENTATION_FLAG_NAME)
- var/decl/material/R = reagents?.get_primary_reagent_decl()
- if(R)
- newname += " of [R.get_presentation_name(src)]"
+ var/decl/material/primary = reagents?.get_primary_reagent_decl()
+ if(primary)
+ newname += " of [primary.get_presentation_name(src)]"
if(length(label_text))
newname += " ([label_text])"
if(newname != name)
@@ -80,7 +70,7 @@
/obj/item/chems/on_reagent_change()
if((. = ..()))
- update_container_name()
+ update_name()
update_container_desc()
update_icon()
@@ -106,7 +96,7 @@
else
to_chat(user, SPAN_NOTICE("You set the label to \"[tmp_label]\"."))
label_text = tmp_label
- update_container_name()
+ update_name()
return TRUE
return ..()
diff --git a/code/modules/reagents/reagent_containers/beaker.dm b/code/modules/reagents/reagent_containers/beaker.dm
index e40e1465a49..60affc293c2 100644
--- a/code/modules/reagents/reagent_containers/beaker.dm
+++ b/code/modules/reagents/reagent_containers/beaker.dm
@@ -65,7 +65,7 @@
take_damage(rand(4,8))
/obj/item/chems/glass/beaker/large
- name = "large beaker"
+ name = "beaker" // see update_name override below
desc = "A large beaker."
icon = 'icons/obj/items/chem/beakers/large.dmi'
center_of_mass = @'{"x":16,"y":10}'
@@ -74,6 +74,10 @@
possible_transfer_amounts = @"[5,10,15,25,30,60,120]"
w_class = ITEM_SIZE_LARGE
+/obj/item/chems/glass/beaker/large/update_name()
+ . = ..()
+ SetName("large [name]") // large glass beaker, not glass large beaker
+
/obj/item/chems/glass/beaker/bowl
name = "mixing bowl"
desc = "A large mixing bowl."
diff --git a/code/modules/reagents/reagent_containers/condiments/__condiment.dm b/code/modules/reagents/reagent_containers/condiments/__condiment.dm
index 34b3835902c..255ffef4b7c 100644
--- a/code/modules/reagents/reagent_containers/condiments/__condiment.dm
+++ b/code/modules/reagents/reagent_containers/condiments/__condiment.dm
@@ -10,6 +10,7 @@
volume = 50
var/condiment_key
var/morphic_container = TRUE
+ var/use_condiment_name = TRUE
var/initial_condiment_type
/obj/item/chems/condiment/populate_reagents()
@@ -32,7 +33,7 @@
else
to_chat(user, SPAN_NOTICE("You remove the label."))
label_text = null
- update_container_name()
+ update_name()
update_container_desc()
update_icon()
return
@@ -65,15 +66,18 @@
var/decl/condiment_appearance/condiment = get_current_condiment_appearance()
center_of_mass = condiment?.condiment_center_of_mass || initial(center_of_mass)
-/obj/item/chems/condiment/update_container_name()
+/obj/item/chems/condiment/update_name()
var/decl/condiment_appearance/condiment = get_current_condiment_appearance()
- name = condiment?.condiment_name || initial(name)
+ if(use_condiment_name && condiment?.condiment_name)
+ SetName(condiment.condiment_name)
+ else
+ ..()
if(label_text)
- name = addtext(name," ([label_text])")
+ SetName(addtext(name," ([label_text])"))
/obj/item/chems/condiment/update_container_desc()
var/decl/condiment_appearance/condiment = get_current_condiment_appearance()
- desc = condiment?.condiment_desc || initial(desc)
+ desc = condiment?.condiment_desc || get_base_desc()
/obj/item/chems/condiment/on_update_icon()
. = ..()
diff --git a/code/modules/reagents/reagent_containers/condiments/_condiment_large.dm b/code/modules/reagents/reagent_containers/condiments/_condiment_large.dm
index a8cd75d64ec..453aebbcc9a 100644
--- a/code/modules/reagents/reagent_containers/condiments/_condiment_large.dm
+++ b/code/modules/reagents/reagent_containers/condiments/_condiment_large.dm
@@ -3,9 +3,7 @@
possible_transfer_amounts = @"[1,5,10,20,50,100]"
volume = 500
w_class = ITEM_SIZE_LARGE
-
-/obj/item/chems/condiment/large/salt/update_container_name()
- return
+ use_condiment_name = FALSE
/obj/item/chems/condiment/large/salt/update_container_desc()
return
diff --git a/code/modules/reagents/reagent_containers/condiments/_condiment_small.dm b/code/modules/reagents/reagent_containers/condiments/_condiment_small.dm
index e119e720d73..0ad0fd5fc49 100644
--- a/code/modules/reagents/reagent_containers/condiments/_condiment_small.dm
+++ b/code/modules/reagents/reagent_containers/condiments/_condiment_small.dm
@@ -4,13 +4,11 @@
possible_transfer_amounts = @"[1,2,5,8,10,20]"
amount_per_transfer_from_this = 1
volume = 20
+ use_condiment_name = FALSE
/obj/item/chems/condiment/small/update_center_of_mass()
return
-/obj/item/chems/condiment/small/update_container_name()
- return
-
/obj/item/chems/condiment/small/update_container_desc()
return
diff --git a/code/modules/reagents/reagent_containers/drinkingglass/drinkingglass.dm b/code/modules/reagents/reagent_containers/drinkingglass/drinkingglass.dm
index 228d9d8d49b..0a4dd77dabe 100644
--- a/code/modules/reagents/reagent_containers/drinkingglass/drinkingglass.dm
+++ b/code/modules/reagents/reagent_containers/drinkingglass/drinkingglass.dm
@@ -7,7 +7,6 @@ var/global/const/DRINK_ICON_NOISY = "noise"
/obj/item/chems/drinks/glass2
name = "glass" // Name when empty
- base_name = "glass"
desc = "A generic drinking glass." // Description when empty
icon = 'icons/obj/drink_glasses/square.dmi'
icon_state = null
@@ -102,9 +101,6 @@ var/global/const/DRINK_ICON_NOISY = "noise"
if(!overlay_base_icon)
overlay_base_icon = base_icon
-/obj/item/chems/drinks/glass2/get_base_name()
- . = base_name
-
/obj/item/chems/drinks/glass2/get_base_desc()
. = custom_desc || ..()
diff --git a/code/modules/reagents/reagent_containers/drinkingglass/glass_types.dm b/code/modules/reagents/reagent_containers/drinkingglass/glass_types.dm
index 73c3ca3fce8..ccff0201716 100644
--- a/code/modules/reagents/reagent_containers/drinkingglass/glass_types.dm
+++ b/code/modules/reagents/reagent_containers/drinkingglass/glass_types.dm
@@ -1,6 +1,5 @@
/obj/item/chems/drinks/glass2/square
name = "half-pint glass"
- base_name = "glass"
base_icon = "square"
icon_state = "square"
icon = 'icons/obj/drink_glasses/square.dmi'
@@ -13,7 +12,6 @@
/obj/item/chems/drinks/glass2/rocks
name = "rocks glass"
desc = "A robust tumbler with a thick, weighted bottom."
- base_name = "glass"
base_icon = "rocks"
icon_state = "rocks"
icon = 'icons/obj/drink_glasses/rocks.dmi'
@@ -25,7 +23,6 @@
/obj/item/chems/drinks/glass2/shake
name = "sherry glass"
desc = "Stemware with an untapered conical bowl."
- base_name = "glass"
base_icon = "shake"
icon_state = "shake"
icon = 'icons/obj/drink_glasses/shake.dmi'
@@ -37,7 +34,6 @@
/obj/item/chems/drinks/glass2/cocktail
name = "cocktail glass"
desc = "Fragile stemware with a stout conical bowl. Don't spill."
- base_name = "glass"
base_icon = "cocktail"
icon_state = "cocktail"
icon = 'icons/obj/drink_glasses/cocktail.dmi'
@@ -49,7 +45,6 @@
/obj/item/chems/drinks/glass2/shot
name = "shot glass"
desc = "A small glass, designed so that its contents can be consumed in one gulp."
- base_name = "shot"
base_icon = "shot"
icon_state = "shot"
icon = 'icons/obj/drink_glasses/shot.dmi'
@@ -61,7 +56,6 @@
/obj/item/chems/drinks/glass2/pint
name = "pint glass"
- base_name = "pint"
base_icon = "pint"
icon_state = "pint"
icon = 'icons/obj/drink_glasses/pint.dmi'
@@ -74,7 +68,6 @@
/obj/item/chems/drinks/glass2/mug
name = "glass mug"
desc = "A heavy mug with thick walls."
- base_name = "mug"
base_icon = "mug"
icon_state = "mug"
icon = 'icons/obj/drink_glasses/mug.dmi'
@@ -86,7 +79,6 @@
/obj/item/chems/drinks/glass2/wine
name = "wine glass"
desc = "A piece of elegant stemware."
- base_name = "glass"
base_icon = "wine"
icon_state = "wine"
icon = 'icons/obj/drink_glasses/wine.dmi'
@@ -98,7 +90,6 @@
/obj/item/chems/drinks/glass2/flute
name = "flute glass"
desc = "A piece of very elegant stemware."
- base_name = "glass"
base_icon = "flute"
icon_state = "flute"
icon = 'icons/obj/drink_glasses/flute.dmi'
@@ -110,7 +101,6 @@
/obj/item/chems/drinks/glass2/carafe
name = "pitcher"
desc = "A handled glass pitcher."
- base_name = "pitcher"
base_icon = "carafe"
icon_state = "carafe"
icon = 'icons/obj/drink_glasses/carafe.dmi'
diff --git a/code/modules/reagents/reagent_containers/drinks.dm b/code/modules/reagents/reagent_containers/drinks.dm
index 3634d48e74c..b4f4ab51dfe 100644
--- a/code/modules/reagents/reagent_containers/drinks.dm
+++ b/code/modules/reagents/reagent_containers/drinks.dm
@@ -84,9 +84,6 @@
if(percent <= k)
return k
-/obj/item/chems/drinks/get_base_name()
- . = base_name
-
/obj/item/chems/drinks/on_update_icon()
. = ..()
if(LAZYLEN(reagents?.reagent_volumes) && filling_states)
diff --git a/code/modules/reagents/reagent_containers/drinks/bottle.dm b/code/modules/reagents/reagent_containers/drinks/bottle.dm
index 84e39aa1c86..44a0aea2f51 100644
--- a/code/modules/reagents/reagent_containers/drinks/bottle.dm
+++ b/code/modules/reagents/reagent_containers/drinks/bottle.dm
@@ -28,9 +28,6 @@
rag = null
return ..()
-/obj/item/chems/drinks/bottle/update_container_name()
- return
-
/obj/item/chems/drinks/bottle/update_container_desc()
return
diff --git a/code/modules/reagents/reagent_containers/drinks/cans.dm b/code/modules/reagents/reagent_containers/drinks/cans.dm
index bebbdb9f24e..ac6d82e688d 100644
--- a/code/modules/reagents/reagent_containers/drinks/cans.dm
+++ b/code/modules/reagents/reagent_containers/drinks/cans.dm
@@ -4,9 +4,6 @@
atom_flags = 0 //starts closed
material = /decl/material/solid/metal/aluminium
-/obj/item/chems/drinks/cans/update_container_name()
- return
-
/obj/item/chems/drinks/cans/update_container_desc()
return
diff --git a/code/modules/reagents/reagent_containers/drinks/jar.dm b/code/modules/reagents/reagent_containers/drinks/jar.dm
deleted file mode 100644
index aedbbade98d..00000000000
--- a/code/modules/reagents/reagent_containers/drinks/jar.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-///jar
-
-/obj/item/chems/drinks/jar
- name = "empty jar"
- desc = "A jar. You're not sure what it's supposed to hold."
- icon_state = "jar"
- item_state = "beaker"
- center_of_mass = @'{"x":15,"y":8}'
- material = /decl/material/solid/glass
- drop_sound = 'sound/foley/bottledrop1.ogg'
- pickup_sound = 'sound/foley/bottlepickup1.ogg'
-
-/obj/item/chems/drinks/jar/update_container_name()
- if(LAZYLEN(reagents?.reagent_volumes))
- SetName("jar of something")
- else
- SetName(initial(name))
-
-/obj/item/chems/drinks/jar/update_container_desc()
- if(LAZYLEN(reagents?.reagent_volumes))
- desc = "You can't really tell what this is."
- else
- desc = "A jar. You're not sure what it's supposed to hold."
-
-/obj/item/chems/drinks/jar/on_update_icon()
- if(LAZYLEN(reagents?.reagent_volumes))
- icon_state = "jar_what"
- else
- icon_state = initial(icon_state)
diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm
index d8244f8b045..c8412e988a5 100644
--- a/code/modules/reagents/reagent_containers/dropper.dm
+++ b/code/modules/reagents/reagent_containers/dropper.dm
@@ -78,7 +78,7 @@
to_chat(user, SPAN_NOTICE("You fill the dropper with [trans] unit\s of the solution."))
-/obj/item/chems/dropper/update_container_name()
+/obj/item/chems/dropper/update_name()
return
/obj/item/chems/dropper/update_container_desc()
diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm
index cd34a4cf679..12f89307eb5 100644
--- a/code/modules/reagents/reagent_containers/glass/bottle.dm
+++ b/code/modules/reagents/reagent_containers/glass/bottle.dm
@@ -68,7 +68,7 @@
. = ..()
if(reagents?.total_volume > 0 && autolabel && !label_text) // don't override preset labels
label_text = reagents.get_primary_reagent_name()
- update_container_name()
+ update_name()
/obj/item/chems/glass/bottle/stabilizer
desc = "A small bottle. Contains stabilizer - used to stabilize patients."
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 5269b0a440d..ade65a7a020 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -184,7 +184,7 @@
/obj/item/chems/hypospray/autoinjector/Initialize()
. = ..()
if(label_text)
- update_container_name()
+ update_name()
/obj/item/chems/hypospray/autoinjector/populate_reagents()
SHOULD_CALL_PARENT(TRUE)
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 203fb2d5382..3d33d1ad367 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -20,7 +20,7 @@
// Pill subtype that does not use a reagent name.
/obj/item/chems/pill/dispensed
autolabel = FALSE
-/obj/item/chems/pill/dispensed/update_container_name()
+/obj/item/chems/pill/dispensed/update_name()
return
/obj/item/chems/pill/dispensed/update_container_desc()
return
@@ -31,7 +31,7 @@
icon_state = pick(colorizable_icon_states) //preset pills only use colour changing or unique icons
update_icon()
if(label_text)
- update_container_name()
+ update_name()
/obj/item/chems/pill/populate_reagents()
SHOULD_CALL_PARENT(TRUE)
@@ -254,7 +254,7 @@
autolabel = FALSE
// Don't overwrite the custom name.
-/obj/item/chems/pill/detergent/update_container_name()
+/obj/item/chems/pill/detergent/update_name()
return
/obj/item/chems/pill/detergent/populate_reagents()
@@ -268,7 +268,7 @@
autolabel = FALSE
// Don't overwrite the custom names.
-/obj/item/chems/pill/pod/update_container_name()
+/obj/item/chems/pill/pod/update_name()
return
/obj/item/chems/pill/pod/cream
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index fd422e1fdd5..485edbccdb3 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -35,7 +35,7 @@
. = ..()
if(reagents.total_volume > 0 && autolabel && !label_text) // don't override preset labels
label_text = reagents.get_primary_reagent_name()
- update_container_name()
+ update_name()
/obj/item/chems/syringe/on_reagent_change()
diff --git a/code/modules/species/species_bodytype.dm b/code/modules/species/species_bodytype.dm
index 33ea2bc8c78..87ae9a45f47 100644
--- a/code/modules/species/species_bodytype.dm
+++ b/code/modules/species/species_bodytype.dm
@@ -13,7 +13,7 @@ var/global/list/bodytypes_by_category = list()
var/icon_deformed
var/cosmetics_icon
var/bandages_icon
- var/bodytype_flag = BODY_FLAG_HUMANOID
+ var/bodytype_flag = BODY_EQUIP_FLAG_HUMANOID
var/bodytype_category = BODYTYPE_OTHER
var/limb_icon_intensity = 1.5
var/blood_overlays
@@ -595,7 +595,7 @@ var/global/list/bodytypes_by_category = list()
qdel(O)
//Create missing limbs
- var/datum/mob_snapshot/supplied_data = H.get_mob_snapshot(force = TRUE)
+ var/datum/mob_snapshot/supplied_data = H.get_mob_snapshot()
supplied_data.root_bodytype = src // This may not have been set on the target mob torso yet.
for(var/limb_type in has_limbs)
@@ -722,7 +722,7 @@ var/global/list/bodytypes_by_category = list()
qdel(innard)
// Install any necessary new organs.
- var/datum/mob_snapshot/supplied_data = limb.owner.get_mob_snapshot(force = TRUE)
+ var/datum/mob_snapshot/supplied_data = limb.owner.get_mob_snapshot()
supplied_data.root_bodytype = src
for(var/organ_tag in replacing_organs)
var/organ_type = replacing_organs[organ_tag]
diff --git a/code/modules/species/species_bodytype_quadruped.dm b/code/modules/species/species_bodytype_quadruped.dm
index 93f1693fc34..ab5bbdd75e6 100644
--- a/code/modules/species/species_bodytype_quadruped.dm
+++ b/code/modules/species/species_bodytype_quadruped.dm
@@ -2,7 +2,7 @@
abstract_type = /decl/bodytype/quadruped
rotate_on_prone = FALSE
bodytype_category = BODYTYPE_QUADRUPED
- bodytype_flag = BODY_FLAG_QUADRUPED
+ bodytype_flag = BODY_EQUIP_FLAG_QUADRUPED
has_limbs = list(
BP_CHEST = list("path" = /obj/item/organ/external/chest),
BP_GROIN = list("path" = /obj/item/organ/external/groin),
diff --git a/code/modules/species/station/monkey_bodytypes.dm b/code/modules/species/station/monkey_bodytypes.dm
index 1ea804f5534..804d6d0add1 100644
--- a/code/modules/species/station/monkey_bodytypes.dm
+++ b/code/modules/species/station/monkey_bodytypes.dm
@@ -4,7 +4,7 @@
icon_base = 'icons/mob/human_races/species/monkey/monkey_body.dmi'
blood_overlays = 'icons/mob/human_races/species/monkey/blood_overlays.dmi'
health_hud_intensity = 1.75
- bodytype_flag = BODY_FLAG_MONKEY
+ bodytype_flag = BODY_EQUIP_FLAG_MONKEY
eye_icon = null
override_limb_types = list(
BP_TAIL = /obj/item/organ/external/tail/monkey
@@ -30,3 +30,4 @@
/obj/item/organ/external/tail/monkey
tail_icon = 'icons/mob/human_races/species/monkey/monkey_body.dmi'
+ tail_blend = null // The monkey tail is already colored.
diff --git a/code/modules/surgery/_surgery.dm b/code/modules/surgery/_surgery.dm
index 9df3477ae93..11b61a35b24 100644
--- a/code/modules/surgery/_surgery.dm
+++ b/code/modules/surgery/_surgery.dm
@@ -1,16 +1,22 @@
var/global/list/surgeries_in_progress = list()
-// A list of types that will not attempt to perform surgery if the user is on help intent.
+// A list of types that will continue to call use_on_mob() if they fail to find an appropriate surgical procedure.
var/global/list/surgery_tool_exceptions = list(
+ // Organic repair:
/obj/item/auto_cpr,
/obj/item/scanner/health,
/obj/item/scanner/breath,
/obj/item/shockpaddles,
/obj/item/chems/hypospray,
/obj/item/chems/inhaler,
- /obj/item/modular_computer,
/obj/item/chems/syringe,
- /obj/item/chems/borghypo
+ /obj/item/chems/borghypo,
+ // Cyborg repair:
+ /obj/item/robotanalyzer,
+ /obj/item/weldingtool,
+ /obj/item/stack/cable_coil,
+ // Modular computer functions like scanners:
+ /obj/item/modular_computer,
)
var/global/list/surgery_tool_exception_cache = list()
@@ -264,6 +270,7 @@ var/global/list/surgery_tool_exception_cache = list()
LAZYSET(possible_surgeries, S, radial_button)
// Which surgery, if any, do we actually want to do?
+ var/cancelled_surgery = FALSE
var/decl/surgery_step/S
if(LAZYLEN(possible_surgeries) == 1)
S = possible_surgeries[1]
@@ -272,11 +279,18 @@ var/global/list/surgery_tool_exception_cache = list()
S = possible_surgeries[1]
else
S = show_radial_menu(user, M, possible_surgeries, radius = 42, use_labels = RADIAL_LABELS_OFFSET, require_near = TRUE, check_locs = list(src))
+ if(isnull(S))
+ cancelled_surgery = TRUE
if(S && !user.skill_check_multiple(S.get_skill_reqs(user, M, src, zone)))
S = pick(possible_surgeries)
// We didn't find a surgery, or decided not to perform one.
if(!istype(S))
+
+ // If they cancelled, do not continue at all!
+ if(cancelled_surgery)
+ return TRUE
+
// If we're on an optable, we are protected from some surgery fails. Bypass this for some items (like health analyzers).
if((locate(/obj/machinery/optable) in get_turf(M)) && user.a_intent == I_HELP)
// Keep track of which tools we know aren't appropriate for surgery on help intent.
diff --git a/code/modules/tools/subtypes/drills.dm b/code/modules/tools/subtypes/drills.dm
index c57da41762f..e3f2cf4f2bb 100644
--- a/code/modules/tools/subtypes/drills.dm
+++ b/code/modules/tools/subtypes/drills.dm
@@ -4,6 +4,10 @@
icon = 'icons/obj/items/tool/drills/drill.dmi'
material_alteration = 0
+/obj/item/tool/drill/Initialize(ml, material_key, _handle_material, _binding_material, override_tool_qualities, override_tool_properties)
+ . = ..()
+ set_extension(src, /datum/extension/demolisher/pick)
+
/obj/item/tool/drill/get_handle_color()
return null
diff --git a/code/modules/tools/subtypes/hammers.dm b/code/modules/tools/subtypes/hammers.dm
index 81ec81beae9..ffeec48f00c 100644
--- a/code/modules/tools/subtypes/hammers.dm
+++ b/code/modules/tools/subtypes/hammers.dm
@@ -12,6 +12,12 @@
"bashes",
"hammers"
)
+ var/demolisher_type = /datum/extension/demolisher/delicate
+
+/obj/item/tool/hammer/Initialize(ml, material_key, _handle_material, _binding_material, override_tool_qualities, override_tool_properties)
+ . = ..()
+ if(demolisher_type)
+ set_extension(src, demolisher_type, null, "demolishing", 'sound/effects/bang.ogg')
/obj/item/tool/hammer/get_initial_tool_properties()
var/static/list/tool_properties = list(
@@ -41,6 +47,7 @@
"bashes",
"hammers"
)
+ demolisher_type = /datum/extension/demolisher
/obj/item/tool/hammer/sledge/get_initial_tool_qualities()
var/static/list/tool_qualities = list(
diff --git a/code/modules/tools/subtypes/hoes.dm b/code/modules/tools/subtypes/hoes.dm
index 3e787f0ac43..ca283a3edb7 100644
--- a/code/modules/tools/subtypes/hoes.dm
+++ b/code/modules/tools/subtypes/hoes.dm
@@ -2,6 +2,7 @@
name = "hoe"
desc = "It's used for removing weeds or scratching your back."
icon = 'icons/obj/items/tool/hoes/hoe.dmi'
+ icon_state = "preview"
sharp = TRUE
edge = TRUE
attack_verb = list("slashed", "sliced", "cut", "clawed")
@@ -9,8 +10,13 @@
material_alteration = MAT_FLAG_ALTERATION_COLOR | MAT_FLAG_ALTERATION_NAME
/obj/item/tool/hoe/wood
+ color = /decl/material/solid/organic/wood::color
material = /decl/material/solid/organic/wood
+/obj/item/tool/hoe/wood/walnut
+ color = /decl/material/solid/organic/wood/walnut::color
+ material = /decl/material/solid/organic/wood/walnut
+
/obj/item/tool/hoe/get_initial_tool_qualities()
var/static/list/tool_qualities = list(TOOL_HOE = TOOL_QUALITY_DEFAULT)
return tool_qualities
diff --git a/code/modules/tools/subtypes/pickaxes.dm b/code/modules/tools/subtypes/pickaxes.dm
index 410354acc0c..3a6a2747b21 100644
--- a/code/modules/tools/subtypes/pickaxes.dm
+++ b/code/modules/tools/subtypes/pickaxes.dm
@@ -8,6 +8,10 @@
handle_material = /decl/material/solid/organic/wood
_base_attack_force = 15
+/obj/item/tool/pickaxe/Initialize(ml, material_key, _handle_material, _binding_material, override_tool_qualities, override_tool_properties)
+ . = ..()
+ set_extension(src, /datum/extension/demolisher/pick)
+
/obj/item/tool/pickaxe/get_initial_tool_qualities()
var/static/list/tool_qualities = list(
TOOL_PICK = TOOL_QUALITY_DEFAULT,
diff --git a/code/modules/tools/subtypes/shovel.dm b/code/modules/tools/subtypes/shovel.dm
index 4355000545d..20ef6053ab0 100644
--- a/code/modules/tools/subtypes/shovel.dm
+++ b/code/modules/tools/subtypes/shovel.dm
@@ -2,7 +2,7 @@
name = "shovel"
desc = "A large tool for digging and moving dirt."
icon = 'icons/obj/items/tool/shovels/shovel.dmi'
- icon_state = ICON_STATE_WORLD
+ icon_state = "preview" // mapping preview icon
slot_flags = SLOT_LOWER_BODY
w_class = ITEM_SIZE_HUGE
edge = TRUE
@@ -19,8 +19,14 @@
return tool_qualities
/obj/item/tool/shovel/wood
+ color = /decl/material/solid/organic/wood::color
material = /decl/material/solid/organic/wood
+/obj/item/tool/shovel/wood/walnut
+ color = /decl/material/solid/organic/wood/walnut::color
+ handle_material = /decl/material/solid/organic/wood/walnut
+ material = /decl/material/solid/organic/wood/walnut
+
/obj/item/tool/shovel/one_material/Initialize(ml, material_key, _handle_material, _binding_material, override_tool_qualities, override_tool_properties)
return ..(ml, material_key, material_key, _binding_material, override_tool_qualities, override_tool_properties)
@@ -28,7 +34,7 @@
name = "spade"
desc = "A small tool for digging and moving dirt."
icon = 'icons/obj/items/tool/shovels/spade.dmi'
- icon_state = ICON_STATE_WORLD
+ icon_state = "preview" // mapping preview icon
w_class = ITEM_SIZE_SMALL
edge = FALSE
sharp = FALSE
diff --git a/code/modules/tools/subtypes/xenoarchaeology_picks.dm b/code/modules/tools/subtypes/xenoarchaeology_picks.dm
index a47f1f7119c..5effa74d311 100644
--- a/code/modules/tools/subtypes/xenoarchaeology_picks.dm
+++ b/code/modules/tools/subtypes/xenoarchaeology_picks.dm
@@ -46,7 +46,7 @@
material = /decl/material/solid/organic/wood
matter = list(/decl/material/solid/metal/steel = MATTER_AMOUNT_REINFORCEMENT)
excavation_amount = 1
- excavation_sound = 'sound/weapons/thudswoosh.ogg'
+ excavation_sound = "sweeping"
excavation_verb = "brushing"
/obj/item/tool/xeno/one_pick
diff --git a/code/modules/weather/weather_wind.dm b/code/modules/weather/weather_wind.dm
index 0161034069c..c363f20e36e 100644
--- a/code/modules/weather/weather_wind.dm
+++ b/code/modules/weather/weather_wind.dm
@@ -17,7 +17,10 @@
mob_shown_wind.Cut()
if(prob(10))
var/old_strength = wind_strength
- wind_strength = clamp(wind_strength + rand(-1, 1), 5, -5)
+ wind_strength = clamp(wind_strength + rand(-1, 1), -1, 5)
+ if(wind_strength < 0)
+ wind_strength = abs(wind_strength)
+ wind_direction = turn(wind_direction, 180)
if(old_strength != wind_strength)
mob_shown_wind.Cut()
diff --git a/code/unit_tests/clothing.dm b/code/unit_tests/clothing.dm
index 94f961984c9..b66ce1ed1b5 100644
--- a/code/unit_tests/clothing.dm
+++ b/code/unit_tests/clothing.dm
@@ -73,7 +73,7 @@
// We don't currently validate clothes specifically for nonhumans.
// TODO: make this a loop over all relevant bodytype categories instead.
var/check_flags = initial(clothes.bodytype_equip_flags)
- if((check_flags && !(check_flags & BODY_FLAG_HUMANOID)) || ((check_flags & BODY_FLAG_EXCLUDE) && (check_flags & BODY_FLAG_HUMANOID)))
+ if((check_flags && !(check_flags & BODY_EQUIP_FLAG_HUMANOID)) || ((check_flags & BODY_EQUIP_FLAG_EXCLUDE) && (check_flags & BODY_EQUIP_FLAG_HUMANOID)))
if(length(clothing_fails))
failures += "[clothing_type]:\n- [jointext(clothing_fails, "\n- ")]"
continue
diff --git a/code/unit_tests/food_tests.dm b/code/unit_tests/food_tests.dm
index 0adf2ad4e20..c1a682a5e0d 100644
--- a/code/unit_tests/food_tests.dm
+++ b/code/unit_tests/food_tests.dm
@@ -41,3 +41,120 @@
pass("All slice types defined correctly.")
return 1
+
+/datum/unit_test/recipes_should_produce_result
+ name = "FOOD: Each recipe should produce the correct result"
+
+/datum/unit_test/recipes_should_produce_result/start_test()
+ var/list/processed_growns_by_tag = list()
+ for(var/processed_type in subtypesof(/obj/item/food/processed_grown))
+ var/obj/item/food/processed_grown/processed = processed_type
+ if(processed::seed)
+ continue
+ if(processed::processed_grown_tag)
+ processed_growns_by_tag[processed::processed_grown_tag] = processed
+ var/list/seeds_by_tag = list()
+ for(var/seed_name in SSplants.seeds)
+ var/datum/seed/seed = SSplants.seeds[seed_name]
+ if(!seed.roundstart) // roundstart seeds ONLY
+ continue
+ if(!seed.grown_tag)
+ continue
+ seeds_by_tag[seed.grown_tag] = seed_name
+
+ var/failures = list()
+ var/obj/container = new // dummy container for holding ingredients
+ container.create_reagents(1000)
+ for (var/decl/recipe/recipe in decls_repository.get_decls_of_subtype_unassociated(/decl/recipe))
+ // assume all recipes are valid because /decl/recipe/validate() handles other things
+ for(var/item_path in recipe.items)
+ var/count = recipe.items[item_path] || 1
+ if(ispath(item_path, /obj/item/stack))
+ if(ispath(item_path, /obj/item/stack/material))
+ new item_path(container, count, /decl/material/solid/organic/bone) // placeholder
+ else
+ new item_path(container, count)
+ else
+ for(var/i in 1 to count)
+ if(ispath(item_path, /obj/item/food/grown))
+ new item_path(container, null, null, "carrot") // placeholder
+ else if(ispath(item_path, /obj/item/food/processed_grown))
+ new item_path(container, null, null, "carrot") // placeholder
+ else if(ispath(item_path, /obj/item/paper))
+ new item_path(container, null, "This is so that fortune cookies work properly. TODO: Make this generic somehow?")
+ else
+ new item_path(container)
+ var/recipe_is_valid = TRUE
+ for(var/fruit_key in recipe.fruit)
+ var/list/key_components = splittext(fruit_key, " ")
+ var/fruit_index = 1
+ var/dry = FALSE
+ if(key_components[1] == "dried")
+ fruit_index = 2
+ dry = TRUE
+ var/seed = seeds_by_tag[key_components[fruit_index]]
+ if(!seed)
+ failures += "Unable to find seed with grown_tag [key_components[fruit_index]] from recipe [recipe.type]"
+ recipe_is_valid = FALSE
+ continue
+ if(length(key_components) > fruit_index) // processed grown!
+ var/processed_type = processed_growns_by_tag[key_components[fruit_index + 1]]
+ if(!processed_type)
+ failures += "Unable to find processed grown type with tag [key_components[fruit_index + 1]] from recipe [recipe.type]"
+ recipe_is_valid = FALSE
+ continue
+ for(var/i in 1 to recipe.fruit[fruit_key])
+ var/obj/item/food/processed_grown/processed = new processed_type(container, null, null, seed)
+ if(dry)
+ processed = processed.dry_out(null, processed.get_max_drying_wetness() + 1)
+ processed.forceMove(container)
+ else
+ for(var/i in 1 to recipe.fruit[fruit_key])
+ var/obj/item/food/grown/grown = new /obj/item/food/grown(container, null, null, seed)
+ if(dry)
+ grown = grown.dry_out(null, grown.get_max_drying_wetness() + 1)
+ grown.forceMove(container)
+
+ for(var/material_key in recipe.reagents)
+ container.add_to_reagents(material_key, recipe.reagents[material_key])
+
+ if(!recipe_is_valid)
+ QDEL_LIST(container.contents) // clean up prematurely
+ container.reagents.clear_reagents()
+ continue
+
+ // continue with validation
+ var/container_category = RECIPE_CATEGORY_MICROWAVE
+ if(recipe.container_categories)
+ container_category = recipe.container_categories[recipe.container_categories.len]
+ if(!container_category)
+ failures += "Invalid container categories [json_encode(recipe.container_categories)] on [recipe.type]"
+ QDEL_LIST(container.contents) // clean up prematurely
+ container.reagents.clear_reagents()
+ continue
+ var/cooking_temperature = T20C
+ if(recipe.minimum_temperature > 0)
+ cooking_temperature = max(cooking_temperature, recipe.minimum_temperature)
+ if(recipe.maximum_temperature < INFINITY)
+ cooking_temperature = min(cooking_temperature, recipe.maximum_temperature)
+ var/decl/recipe/new_recipe = select_recipe(container_category, container, cooking_temperature)
+ if(new_recipe && new_recipe != recipe)
+ failures += "Recipe [recipe.type]'s ingredients selected [new_recipe.type] instead!"
+ else if(!new_recipe)
+ failures += "Recipe [recipe.type]'s ingredients selected NULL instead!"
+ else
+ recipe.produce_result(container)
+ if(ispath(recipe.result, /decl/material) && !container.reagents.has_reagent(recipe.result))
+ failures += "Recipe [recipe.type] did not produce the expected output [recipe.result]"
+ if(ispath(recipe.result, /atom/movable) && !locate(recipe.result) in container)
+ failures += "Recipe [recipe.type] did not produce the expected output [recipe.result]"
+
+ QDEL_LIST(container.contents) // clean up
+ container.reagents.clear_reagents()
+
+ if(length(failures))
+ fail("Some recipes failed to produce the right result:\n\t-[jointext(failures, "\n\t-")]")
+ else
+ pass("All recipes produced the right result.")
+
+ return TRUE
\ No newline at end of file
diff --git a/code/unit_tests/turf_icons.dm b/code/unit_tests/turf_icons.dm
index 47a9c52548b..4baaafd593e 100644
--- a/code/unit_tests/turf_icons.dm
+++ b/code/unit_tests/turf_icons.dm
@@ -80,33 +80,8 @@
if(!istext(icon_state))
. += "null or invalid icon_state '[icon_state]'"
if(icon && icon_state && !check_state_in_icon(icon_state, icon))
- . += "missing initial icon_state '[icon_state]' from '[icon]"
- if(base_icon)
- if(!istext(base_icon_state))
- . += "base_icon set, but null or invalid base_icon_state set: '[base_icon_state]'"
- else if(!check_state_in_icon(base_icon_state, base_icon))
- . += "base_icon_state '[base_icon_state]' not found in base_icon '[base_icon]'"
- else if(base_icon_state)
- . += "null base_icon but base_icon_state set"
-
-/turf/floor/natural/validate_turf()
- . = ..()
- if(icon_edge_layer != -1 && !isnum(icon_edge_layer))
- . += "invalid icon_edge_layer '[icon_edge_layer]'"
-
- if(icon && icon_state)
- if(possible_states)
- for(var/i = 0 to possible_states)
- if(!check_state_in_icon(num2text(i), icon))
- . += "missing icon_state [i] from icon '[icon]'"
-
- if(icon_edge_layer >= 0)
- for(var/checkdir in (icon_has_corners ? global.alldirs : global.cardinal))
- if(icon_edge_states)
- for(var/i = 0 to icon_edge_states)
- var/check_state = "edge[checkdir][i]"
- if(!check_state_in_icon(check_state, icon))
- . += "missing edge state '[check_state]' in icon '[icon]'"
- var/check_state = "edge[checkdir]"
- if(!check_state_in_icon(check_state, icon))
- . += "missing edge state '[check_state]' in icon '[icon]'"
+ . += "missing initial icon_state '[icon_state]' from '[icon]'"
+ if(!istype(_base_flooring))
+ . += "null or invalid _base_flooring ([_base_flooring || "NULL"])"
+ if(_flooring && !istype(_flooring))
+ . += "invalid post-init type for _flooring ([_flooring || "NULL"])"
diff --git a/html/changelog.html b/html/changelog.html
index 9c08468f154..51c853c8ceb 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -52,6 +52,31 @@
-->
") // these don't work in BYOND's native output panel. If we switch to browser output instead, you can readd this
show_examined_short_description(user, distance, infix, suffix, hideflags, pronouns)
show_examined_worn_held_items(user, distance, infix, suffix, hideflags, pronouns)
show_other_examine_strings(user, distance, infix, suffix, hideflags, pronouns)
- to_chat(user, "