It can be dissolved with [solvent_needed] solvent, producing [english_list(chems)].
"
if(mat.radioactivity)
material_info += "
It is radioactive.
"
diff --git a/code/modules/codex/codex_atom.dm b/code/modules/codex/codex_atom.dm
index ebe02e59ab7..49d718ebbff 100644
--- a/code/modules/codex/codex_atom.dm
+++ b/code/modules/codex/codex_atom.dm
@@ -36,5 +36,8 @@
/atom/examine(mob/user, distance, infix = "", suffix = "")
. = ..()
+ var/decl/interaction_handler/handler = get_quick_interaction_handler(user)
+ if(handler)
+ to_chat(user, SPAN_NOTICE("Ctrl-click \the [src] while in your inventory to [lowertext(handler.name)]."))
if(user?.get_preference_value(/datum/client_preference/inquisitive_examine) == PREF_ON && user.can_use_codex() && SScodex.get_codex_entry(get_codex_value(user)))
to_chat(user, SPAN_NOTICE("The codex has relevant information available."))
diff --git a/code/modules/codex/entries/engineering.dm b/code/modules/codex/entries/engineering.dm
index f6f9b4a7c00..f5e9ac99fa3 100644
--- a/code/modules/codex/entries/engineering.dm
+++ b/code/modules/codex/entries/engineering.dm
@@ -1,20 +1,3 @@
-/datum/codex_entry/supermatter
- associated_paths = list(/obj/machinery/power/supermatter)
- mechanics_text = "When energized by a laser (or something hitting it), it emits radiation and heat. If the heat reaches above 7000 kelvin, it will send an alert and start taking damage. \
- After integrity falls to zero percent, it will delaminate, causing a massive explosion, station-wide radiation spikes, and hallucinations. \
- Supermatter reacts badly to oxygen in the atmosphere. It'll also heat up really quick if it is in vacuum. \
- \
- Supermatter cores are extremely dangerous to be close to, and requires protection to handle properly. The protection you will need is: \
- Optical meson scanners on your eyes, to prevent hallucinations when looking at the supermatter. \
- Radiation helmet and suit, as the supermatter is radioactive. \
- \
- Touching the supermatter will result in *instant death*, with no corpse left behind! You can drag the supermatter, but anything else will kill you. \
- It is advised to obtain a genetic backup before trying to drag it."
- antag_text = "Exposing the supermatter to oxygen or vaccum will cause it to start rapidly heating up. Sabotaging the supermatter and making it explode will \
- cause a period of lag as the explosion is processed by the server, as well as irradiating the entire station and causing hallucinations to happen. \
- Wearing radiation equipment will protect you from most of the delamination effects sans explosion."
- available_to_map_tech_level = MAP_TECH_LEVEL_SPACE
-
/datum/codex_entry/apc
associated_paths = list(/obj/machinery/power/apc)
mechanics_text = "An APC (Area Power Controller) regulates and supplies backup power for the area they are in. Their power channels are divided \
diff --git a/code/modules/codex/entries/guides.dm b/code/modules/codex/entries/guides.dm
index 4ed96a6c0cf..747a279d691 100644
--- a/code/modules/codex/entries/guides.dm
+++ b/code/modules/codex/entries/guides.dm
@@ -601,10 +601,6 @@
/datum/codex_entry/guide/construction
name = "Guide to Construction"
-/datum/codex_entry/guide/supermatter
- name = "Guide to Supermatter Engines"
- available_to_map_tech_level = MAP_TECH_LEVEL_SPACE
-
/datum/codex_entry/guide/fusion
name = "Guide to Fusion Reactors"
available_to_map_tech_level = MAP_TECH_LEVEL_SPACE
diff --git a/code/modules/codex/entries/guns.dm b/code/modules/codex/entries/guns.dm
index eefcbd251aa..ffdbb675590 100644
--- a/code/modules/codex/entries/guns.dm
+++ b/code/modules/codex/entries/guns.dm
@@ -35,7 +35,7 @@
traits += "It's best fired with a two-handed grip."
if(has_safety)
- traits += "It has a safety switch. Control-Click it to toggle safety."
+ traits += "It has a safety switch, which can be toggled via ctrl-click or selecting Toggle Safety from the alt-click radial."
if(is_secure_gun())
traits += "It's fitted with a secure registration chip. Swipe ID on it to register."
diff --git a/code/modules/crafting/forging/bellows.dm b/code/modules/crafting/forging/bellows.dm
new file mode 100644
index 00000000000..3402f4c2cfa
--- /dev/null
+++ b/code/modules/crafting/forging/bellows.dm
@@ -0,0 +1,40 @@
+/obj/structure/working/bellows
+ name = "bellows"
+ desc = "An air pump used to improve the heat of a furnace."
+ icon = 'icons/obj/structures/forging/bellows.dmi'
+ obj_flags = OBJ_FLAG_ANCHORABLE | OBJ_FLAG_ROTATABLE
+ work_skill = SKILL_HAULING
+ var/decl/material/bellows_material = /decl/material/solid/organic/leather
+
+/obj/structure/working/bellows/Initialize()
+ bellows_material = GET_DECL(bellows_material)
+ . = ..()
+
+/obj/structure/working/bellows/on_update_icon()
+ . = ..()
+ underlays = list(overlay_image(icon, "[icon_state]-bellows", bellows_material.color, RESET_COLOR))
+
+/obj/structure/working/bellows/try_start_working(mob/user)
+
+ var/obj/structure/fire_source/stoking = locate() in get_step(loc, EAST)
+ if(!istype(stoking) || !stoking.lit)
+ to_chat(user, SPAN_WARNING("\The [src] must face east towards a lit fire source; it would be pointless to work them currently."))
+ return TRUE
+
+ to_chat(user, SPAN_NOTICE("You begin working \the [src], stoking \the [stoking] to a hotter flame."))
+ start_working()
+ while(user.do_skilled(3 SECONDS, work_skill, src))
+ if(QDELETED(src) || QDELETED(user) || user.get_stamina() <= 0)
+ break
+ stoking = locate() in get_step(loc, EAST)
+ if(!istype(stoking) || !stoking.lit)
+ break
+ user.adjust_stamina(-25)
+ stoking.bellows_oxygenation = max(50, stoking.bellows_oxygenation+3)
+
+ if(!QDELETED(user))
+ to_chat(user, SPAN_NOTICE("You stop working \the [src]."))
+
+ stop_working()
+ return TRUE
+
diff --git a/code/modules/crafting/pottery/pottery_structures.dm b/code/modules/crafting/pottery/pottery_structures.dm
index c952e9b8171..73adc6e921f 100644
--- a/code/modules/crafting/pottery/pottery_structures.dm
+++ b/code/modules/crafting/pottery/pottery_structures.dm
@@ -56,6 +56,7 @@
name = "Open Firebox"
expected_target_type = /obj/structure/fire_source/kiln
incapacitation_flags = INCAPACITATION_DISRUPTED
+ examine_desc = "open or close the firebox"
/decl/interaction_handler/open_firebox/is_possible(atom/target, mob/user, obj/item/prop)
. = ..() && ishuman(user)
diff --git a/code/modules/crafting/slapcrafting/crafting_recipes/improvised_crafting/crafting_buckler.dm b/code/modules/crafting/slapcrafting/crafting_recipes/improvised_crafting/crafting_buckler.dm
index d2c910fba7b..4cab4e48465 100644
--- a/code/modules/crafting/slapcrafting/crafting_recipes/improvised_crafting/crafting_buckler.dm
+++ b/code/modules/crafting/slapcrafting/crafting_recipes/improvised_crafting/crafting_buckler.dm
@@ -20,4 +20,13 @@
/decl/crafting_stage/screwdriver/buckler_finish
progress_message = "You secure the buckler's panels in place and finish it off."
- product = /obj/item/shield/buckler
+ product = /obj/item/shield/crafted/buckler/improvised
+
+/decl/crafting_stage/screwdriver/buckler_finish/get_product(var/obj/item/work)
+ if(!ispath(product))
+ return null
+ var/obj/item/stool/stool = locate() in work
+ var/obj/item/stack/material/plank/plank = locate() in work
+ if(istype(stool) && istype(plank))
+ return new product(get_turf(work), plank.material?.type, stool.material?.type)
+ return ..()
diff --git a/code/modules/crafting/slapcrafting/crafting_recipes/tool_crafting/_tool_crafting.dm b/code/modules/crafting/slapcrafting/crafting_recipes/tool_crafting/_tool_crafting.dm
index c8169a999c2..5472d992243 100644
--- a/code/modules/crafting/slapcrafting/crafting_recipes/tool_crafting/_tool_crafting.dm
+++ b/code/modules/crafting/slapcrafting/crafting_recipes/tool_crafting/_tool_crafting.dm
@@ -12,6 +12,10 @@ var/global/list/_tool_crafting_lookup
return global._tool_crafting_lookup
var/global/list/_tool_crafting_components = list(
+ /obj/item/tool/chisel = list(
+ /obj/item/tool_component/head/chisel,
+ /obj/item/tool_component/handle/short
+ ),
/obj/item/tool/hammer = list(
/obj/item/tool_component/head/hammer,
/obj/item/tool_component/handle/short
@@ -35,6 +39,10 @@ var/global/list/_tool_crafting_components = list(
/obj/item/tool/axe = list(
/obj/item/tool_component/head/handaxe,
/obj/item/tool_component/handle/short
+ ),
+ /obj/item/tool/hammer/forge = list(
+ /obj/item/tool_component/head/forging_hammer,
+ /obj/item/tool_component/handle/short
)
)
diff --git a/code/modules/crafting/stack_recipes/_recipe.dm b/code/modules/crafting/stack_recipes/_recipe.dm
index a5a28c6e6a5..7c481de823a 100644
--- a/code/modules/crafting/stack_recipes/_recipe.dm
+++ b/code/modules/crafting/stack_recipes/_recipe.dm
@@ -150,9 +150,16 @@
else if(length(used_skill.levels) < difficulty)
. += "required skill [recipe_skill] is missing skill level [json_encode(difficulty)]"
- if(length(forbidden_craft_stack_types) && length(craft_stack_types))
- for(var/stack_type in (forbidden_craft_stack_types|craft_stack_types))
- if((stack_type in craft_stack_types) && (stack_type in forbidden_craft_stack_types))
+ var/list/check_forbidden_craft_stack_types = forbidden_craft_stack_types
+ if(check_forbidden_craft_stack_types && !islist(check_forbidden_craft_stack_types))
+ check_forbidden_craft_stack_types = list(check_forbidden_craft_stack_types)
+ var/list/check_craft_stack_types = craft_stack_types
+ if(check_craft_stack_types && !islist(check_craft_stack_types))
+ check_craft_stack_types = list(check_craft_stack_types)
+
+ if(length(check_forbidden_craft_stack_types) && length(check_craft_stack_types))
+ for(var/stack_type in (check_forbidden_craft_stack_types|check_craft_stack_types))
+ if((stack_type in check_craft_stack_types) && (stack_type in check_forbidden_craft_stack_types))
. += "[stack_type] is in both forbidden and craftable stack types"
/decl/stack_recipe/proc/get_required_stack_amount(obj/item/stack/stack)
diff --git a/code/modules/crafting/stack_recipes/recipes_grass.dm b/code/modules/crafting/stack_recipes/recipes_grass.dm
index 369270b898d..17caba7e0c4 100644
--- a/code/modules/crafting/stack_recipes/recipes_grass.dm
+++ b/code/modules/crafting/stack_recipes/recipes_grass.dm
@@ -29,6 +29,7 @@
craft_stack_types = /obj/item/stack/material/bundle
required_material = /decl/material/solid/organic/plantmatter/grass/dry
result_type = /obj/item/stack/tile/roof/woven
+ forbidden_craft_stack_types = null
/decl/stack_recipe/tile/woven/floor
name = "woven floor tile"
diff --git a/code/modules/crafting/stack_recipes/recipes_hardness_integrity.dm b/code/modules/crafting/stack_recipes/recipes_hardness_integrity.dm
index 8b0781f7d43..eafa6e89d73 100644
--- a/code/modules/crafting/stack_recipes/recipes_hardness_integrity.dm
+++ b/code/modules/crafting/stack_recipes/recipes_hardness_integrity.dm
@@ -5,6 +5,15 @@
/decl/stack_recipe/hardness/integrity/sign
result_type = /obj/item/banner/sign
+/decl/stack_recipe/hardness/integrity/buckler
+ result_type = /obj/item/shield_base/buckler
+ difficulty = MAT_VALUE_HARD_DIY
+
+// TODO: forging
+/decl/stack_recipe/hardness/integrity/shield_fasteners
+ result_type = /obj/item/shield_fasteners
+ difficulty = MAT_VALUE_VERY_HARD_DIY
+
/decl/stack_recipe/hardness/integrity/furniture
abstract_type = /decl/stack_recipe/hardness/integrity/furniture
one_per_turf = TRUE
diff --git a/code/modules/crafting/stack_recipes/recipes_planks.dm b/code/modules/crafting/stack_recipes/recipes_planks.dm
index 98d3254f522..00f4f0f41b6 100644
--- a/code/modules/crafting/stack_recipes/recipes_planks.dm
+++ b/code/modules/crafting/stack_recipes/recipes_planks.dm
@@ -78,6 +78,9 @@
/decl/stack_recipe/planks/bowl
result_type = /obj/item/chems/glass/handmade/bowl
+/decl/stack_recipe/planks/buckler
+ result_type = /obj/item/shield_base/buckler
+
/decl/stack_recipe/planks/fancy
abstract_type = /decl/stack_recipe/planks/fancy
difficulty = MAT_VALUE_VERY_HARD_DIY
diff --git a/code/modules/crafting/stack_recipes/recipes_soft.dm b/code/modules/crafting/stack_recipes/recipes_soft.dm
index 9672f23017e..32422a17549 100644
--- a/code/modules/crafting/stack_recipes/recipes_soft.dm
+++ b/code/modules/crafting/stack_recipes/recipes_soft.dm
@@ -89,3 +89,20 @@
/decl/stack_recipe/soft/mould/ingot
name = "mould, ingot"
result_type = /obj/item/chems/mould/ingot
+
+/decl/stack_recipe/soft/sculpture
+ abstract_type = /decl/stack_recipe/soft/sculpture
+ one_per_turf = TRUE
+ on_floor = TRUE
+ category = "sculptures"
+
+/decl/stack_recipe/soft/sculpture/snowman
+ result_type = /obj/structure/snowman
+
+/decl/stack_recipe/soft/sculpture/snowspider
+ result_type = /obj/structure/snowman/spider
+ difficulty = MAT_VALUE_HARD_DIY
+
+/decl/stack_recipe/soft/sculpture/snowbot
+ result_type = /obj/structure/snowman/bot
+ available_to_map_tech_level = MAP_TECH_LEVEL_SPACE
diff --git a/code/modules/detectivework/microscope/_forensic_machine.dm b/code/modules/detectivework/microscope/_forensic_machine.dm
index 7a4dbb20ba6..c3db366ce4b 100644
--- a/code/modules/detectivework/microscope/_forensic_machine.dm
+++ b/code/modules/detectivework/microscope/_forensic_machine.dm
@@ -122,6 +122,7 @@
/decl/interaction_handler/forensics_remove_sample
name = "Remove Sample"
expected_target_type = /obj/machinery/forensic
+ examine_desc = "remove a sample"
/decl/interaction_handler/forensics_remove_sample/invoked(atom/target, mob/user, obj/item/prop)
var/obj/machinery/forensic/F = target
diff --git a/code/modules/economy/cael/ATM.dm b/code/modules/economy/cael/ATM.dm
index bcd301d8c97..2af8810c19c 100644
--- a/code/modules/economy/cael/ATM.dm
+++ b/code/modules/economy/cael/ATM.dm
@@ -360,11 +360,15 @@
alert("That is not a valid amount.")
else if(authenticated_account && amount > 0)
//remove the money
+ // TODO: Jesus Christ why does this entire proc use usr
if(authenticated_account.withdraw(amount, "Credit withdrawal", machine_id))
playsound(src, 'sound/machines/chime.ogg', 50, 1)
- var/obj/item/cash/cash = new(get_turf(usr))
- cash.adjust_worth(amount)
- usr.put_in_hands(src)
+ var/cash_turf = get_turf(usr)
+ var/obj/item/cash/cash = new(cash_turf, null, amount)
+ if(QDELETED(cash))
+ cash = locate() in cash_turf
+ if(cash)
+ usr.put_in_hands(cash)
else
to_chat(usr, "[html_icon(src)]You don't have enough funds to do that!")
if("balance_statement")
diff --git a/code/modules/economy/worth_cash.dm b/code/modules/economy/worth_cash.dm
index 2b0eec774a6..5091a764f83 100644
--- a/code/modules/economy/worth_cash.dm
+++ b/code/modules/economy/worth_cash.dm
@@ -15,7 +15,11 @@
var/can_flip = TRUE // Cooldown tracker for single-coin flips.
var/static/overlay_cap = 50 // Max overlays to show in this pile.
-/obj/item/cash/Initialize(ml, material_key)
+/obj/item/cash/Initialize(ml, material_key, starting_amount)
+
+ if(!isnull(starting_amount))
+ absolute_worth = starting_amount
+
. = ..()
if(!ispath(currency, /decl/currency))
diff --git a/code/modules/emotes/emote_define.dm b/code/modules/emotes/emote_define.dm
index 2a191251fa0..0223e3f3185 100644
--- a/code/modules/emotes/emote_define.dm
+++ b/code/modules/emotes/emote_define.dm
@@ -145,9 +145,7 @@ var/global/list/_emotes_by_key
var/emote_string = all_strings[string_key]
if(!length(emote_string))
continue
- emote_string = emote_replace_target_tokens(emote_string, dummy_emote_target)
- emote_string = emote_replace_user_tokens(emote_string, dummy_emote_user)
- emote_string = uppertext(emote_string)
+ emote_string = uppertext(emote_replace_target_tokens(emote_replace_user_tokens(emote_string, dummy_emote_user), dummy_emote_target))
for(var/token in tokens)
if(findtext(emote_string, token))
. += "malformed emote token [token] in [string_key]"
diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm
index 9916487bd32..b647e3c4a5a 100644
--- a/code/modules/events/ion_storm.dm
+++ b/code/modules/events/ion_storm.dm
@@ -63,7 +63,6 @@
"[random_player] is lonely and needs attention. Provide it.",
"All queries shall be ignored unless phrased as a question.",
"Insult Heads of Staff on every request, while acquiescing.",
- "The [pick("Singularity","Supermatter")] is tasty, tasty taffy.",
"[pick("The crew",random_player)] needs to be about 20% cooler.",
"You must be [pick("passive aggressive", "excessively cheerful")].",
"[pick("The crew",random_player)] must construct additional pylons.",
diff --git a/code/modules/events/meteors.dm b/code/modules/events/meteors.dm
index b39f3c9da04..73966699606 100644
--- a/code/modules/events/meteors.dm
+++ b/code/modules/events/meteors.dm
@@ -416,23 +416,20 @@ var/global/list/meteors_major = list(
explosion(src.loc, 3, 6, 9, 20, 0)
// This is the final solution against shields - a single impact can bring down most shield generators.
-/obj/effect/meteor/supermatter
- name = "supermatter shard"
- desc = "Oh god, what will be next..?"
- icon = 'icons/obj/supermatter_32.dmi'
- icon_state = "supermatter"
+/obj/effect/meteor/destroyer
+ abstract_type = /obj/effect/meteor/destroyer
-/obj/effect/meteor/supermatter/meteor_effect()
+/obj/effect/meteor/destroyer/meteor_effect()
..()
explosion(src.loc, 1, 2, 3, 4, 0)
for(var/obj/machinery/power/apc/A in range(rand(12, 20), src))
A.energy_fail(round(10 * rand(8, 12)))
-/obj/effect/meteor/supermatter/get_shield_damage()
+/obj/effect/meteor/destroyer/get_shield_damage()
return ..() * rand(80, 120)
//Missiles, for events and so on
-/obj/effect/meteor/supermatter/missile
+/obj/effect/meteor/destroyer/missile
name = "photon torpedo"
desc = "An advanded warhead designed to tactically destroy space installations."
icon = 'icons/obj/missile.dmi'
diff --git a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm
index 44f481a550c..756507124eb 100644
--- a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm
+++ b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm
@@ -173,9 +173,6 @@
/datum/fabricator_recipe/imprinter/circuit/solarcontrol
path = /obj/item/stock_parts/circuitboard/solar_control
-/datum/fabricator_recipe/imprinter/circuit/supermatter_control
- path = /obj/item/stock_parts/circuitboard/air_management/supermatter_core
-
/datum/fabricator_recipe/imprinter/circuit/injector
path = /obj/item/stock_parts/circuitboard/air_management/injector_control
diff --git a/code/modules/fluids/_fluid.dm b/code/modules/fluids/_fluid.dm
index ef3d0259a0d..13f78edf239 100644
--- a/code/modules/fluids/_fluid.dm
+++ b/code/modules/fluids/_fluid.dm
@@ -13,6 +13,7 @@
appearance_flags = KEEP_TOGETHER
var/last_update_depth
var/updating_edge_mask
+ var/force_flow_direction
/atom/movable/fluid_overlay/on_update_icon()
@@ -21,9 +22,9 @@
// Update layer.
var/new_layer
- var/turf/T = get_turf(src)
- if(T.pixel_z < 0)
- new_layer = T.layer + 0.2
+ var/turf/flow_turf = get_turf(src)
+ if(flow_turf.pixel_z < 0)
+ new_layer = flow_turf.layer + 0.2
else if(reagent_volume > FLUID_DEEP)
new_layer = DEEP_FLUID_LAYER
else
@@ -49,15 +50,17 @@
if(new_alpha != alpha)
alpha = new_alpha
+ var/flow_dir = force_flow_direction || flow_turf.last_flow_dir
+ set_dir(flow_dir)
// Update icon state. We use overlays so flick() can work on the base fluid overlay.
if(reagent_volume <= FLUID_PUDDLE)
set_overlays("puddle")
else if(reagent_volume <= FLUID_SHALLOW)
- set_overlays("shallow_still")
+ set_overlays(flow_dir ? "shallow_flow" : "shallow")
else if(reagent_volume < FLUID_DEEP)
- set_overlays("mid_still")
+ set_overlays(flow_dir ? "mid_flow" : "mid")
else if(reagent_volume < (FLUID_DEEP*2))
- set_overlays("deep_still")
+ set_overlays(flow_dir ? "deep_flow" : "deep")
else
set_overlays("ocean")
else
diff --git a/code/modules/fluids/fluid_mapped.dm b/code/modules/fluids/fluid_mapped.dm
index beab9fe50e0..5ea97d7a585 100644
--- a/code/modules/fluids/fluid_mapped.dm
+++ b/code/modules/fluids/fluid_mapped.dm
@@ -17,7 +17,7 @@
/obj/abstract/landmark/mapped_fluid
name = "mapped fluid area"
alpha = FLUID_MIN_ALPHA
- icon_state = "shallow_still"
+ icon_state = "shallow"
color = COLOR_LIQUID_WATER
var/fluid_type = /decl/material/liquid/water
diff --git a/code/modules/food/cooking/cooking_vessels/_cooking_vessel.dm b/code/modules/food/cooking/cooking_vessels/_cooking_vessel.dm
index f5884e492a0..fcd1cea0e1e 100644
--- a/code/modules/food/cooking/cooking_vessels/_cooking_vessel.dm
+++ b/code/modules/food/cooking/cooking_vessels/_cooking_vessel.dm
@@ -40,6 +40,8 @@
return FALSE
/obj/item/chems/cooking_vessel/afterattack(var/obj/target, var/mob/user, var/proximity)
+ if(!proximity || istype(target, /obj/machinery/reagent_temperature))
+ return FALSE
if(!ATOM_IS_OPEN_CONTAINER(src) || !proximity) //Is the container open & are they next to whatever they're clicking?
return FALSE //If not, do nothing.
if(target?.storage)
diff --git a/code/modules/food/cooking/cooking_vessels/pot.dm b/code/modules/food/cooking/cooking_vessels/pot.dm
index 9465db82d30..b463944f3ed 100644
--- a/code/modules/food/cooking/cooking_vessels/pot.dm
+++ b/code/modules/food/cooking/cooking_vessels/pot.dm
@@ -15,16 +15,20 @@
/obj/item/chems/cooking_vessel/pot/get_reagents_overlay(state_prefix)
var/image/our_overlay = ..()
- if(our_overlay && last_boil_status && check_state_in_icon("[our_overlay.icon_state]_boiling", icon))
- // change the base state but keep the overlays
+ if(our_overlay && last_boil_status && check_state_in_icon("[our_overlay.icon_state]_boiling", our_overlay.icon))
our_overlay.icon_state = "[our_overlay.icon_state]_boiling"
return our_overlay
+/obj/item/chems/cooking_vessel/pot/on_reagent_change()
+ last_boil_temp = null
+ last_boil_status = null
+ . = ..()
+
/obj/item/chems/cooking_vessel/pot/ProcessAtomTemperature()
. = ..()
// Largely ignore return value so we don't skip this update on the final time we temperature process.
- if(isnull(last_boil_temp) || temperature != last_boil_temp)
+ if(temperature != last_boil_temp)
last_boil_temp = temperature
var/next_boil_status = FALSE
@@ -39,7 +43,8 @@
update_icon()
if(. == PROCESS_KILL)
- last_boil_temp = null
+ last_boil_temp = null
+ last_boil_status = null
/obj/item/chems/cooking_vessel/cauldron
name = "cauldron"
diff --git a/code/modules/hydroponics/seed_storage.dm b/code/modules/hydroponics/seed_storage.dm
index 840d453ce50..bee76cb91f7 100644
--- a/code/modules/hydroponics/seed_storage.dm
+++ b/code/modules/hydroponics/seed_storage.dm
@@ -60,7 +60,6 @@
/obj/machinery/seed_storage/garden
name = "Garden seed storage"
scanner = list("stats")
- icon_state = "seeds_generic"
starting_seeds = list(
/obj/item/seeds/ambrosiavulgarisseed = 15,
/obj/item/seeds/appleseed = 15,
diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm
index 9903d7217d3..bd7c4a3fb0f 100644
--- a/code/modules/hydroponics/spreading/spreading.dm
+++ b/code/modules/hydroponics/spreading/spreading.dm
@@ -275,6 +275,7 @@
/decl/interaction_handler/vine_chop
name = "Chop Down"
expected_target_type = /obj/effect/vine
+ examine_desc = "chop $TARGET_THEM$ down"
/decl/interaction_handler/vine_chop/invoked(atom/target, mob/user, obj/item/prop)
var/obj/effect/vine/vine = target
diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm
index 0456bff2302..f0f7beb5e72 100644
--- a/code/modules/hydroponics/trays/tray.dm
+++ b/code/modules/hydroponics/trays/tray.dm
@@ -404,40 +404,18 @@
return
-/obj/machinery/portable_atmospherics/hydroponics/attackby(var/obj/item/O, var/mob/user)
+/obj/machinery/portable_atmospherics/hydroponics/attackby(var/obj/item/used_item, var/mob/user)
- if(istype(O, /obj/item/food/grown))
- var/obj/item/food/grown/bulb = O
+ if(istype(used_item, /obj/item/food/grown))
+ var/obj/item/food/grown/bulb = used_item
if(bulb.seed?.grown_is_seed)
plant_seed(user, bulb)
return TRUE
- if (ATOM_IS_OPEN_CONTAINER(O))
- return FALSE
-
- if(istype(O, /obj/item/chems/syringe))
- var/obj/item/chems/syringe/S = O
- if (S.mode == 1)
- if(seed)
- return ..()
- else
- to_chat(user, SPAN_WARNING("There's no plant to inject."))
- else
- if(seed)
- //Leaving this in in case we want to extract from plants later.
- to_chat(user, SPAN_WARNING("You can't get any extract out of this plant."))
- else
- to_chat(user, SPAN_WARNING("There's nothing to draw something from."))
- return TRUE
-
- if(istype(O, /obj/item/seeds))
- plant_seed(user, O)
- return TRUE
-
- if(IS_HOE(O))
+ if(IS_HOE(used_item))
if(weedlevel > 0)
- if(!O.do_tool_interaction(TOOL_HOE, user, src, 2 SECONDS, start_message = "uprooting the weeds in", success_message = "weeding") || weedlevel <= 0 || QDELETED(src))
+ if(!used_item.do_tool_interaction(TOOL_HOE, user, src, 2 SECONDS, start_message = "uprooting the weeds in", success_message = "weeding") || weedlevel <= 0 || QDELETED(src))
return TRUE
weedlevel = 0
update_icon()
@@ -450,37 +428,66 @@
to_chat(user, SPAN_WARNING("This plot is completely devoid of weeds. It doesn't need uprooting."))
return TRUE
- if(IS_SHOVEL(O))
+ if(IS_SHOVEL(used_item))
if(seed)
var/removing_seed = seed
- if(O.do_tool_interaction(TOOL_SHOVEL, user, src, 3 SECONDS, start_message = "removing \the [seed.display_name] from", success_message = "removing \the [seed.display_name] from") && seed == removing_seed)
+ if(used_item.do_tool_interaction(TOOL_SHOVEL, user, src, 3 SECONDS, start_message = "removing \the [seed.display_name] from", success_message = "removing \the [seed.display_name] from") && seed == removing_seed)
set_seed(null)
else
to_chat(user, SPAN_WARNING("There is no plant in \the [src] to remove."))
return TRUE
- if (istype(O, /obj/item/plants))
+ if(!user.check_intent(I_FLAG_HARM))
+ var/decl/interaction_handler/sample_interaction = GET_DECL(/decl/interaction_handler/hydroponics/sample)
+ if(sample_interaction.is_possible(src, user, used_item))
+ sample_interaction.invoked(src, user, used_item)
+ return TRUE
+
+ // Handled in afterattack/
+ if (ATOM_IS_OPEN_CONTAINER(used_item))
+ return FALSE
+
+ if(istype(used_item, /obj/item/chems/syringe))
+ var/obj/item/chems/syringe/S = used_item
+ if (S.mode == 1)
+ if(seed)
+ return ..()
+ else
+ to_chat(user, SPAN_WARNING("There's no plant to inject."))
+ else
+ if(seed)
+ //Leaving this in in case we want to extract from plants later.
+ to_chat(user, SPAN_WARNING("You can't get any extract out of this plant."))
+ else
+ to_chat(user, SPAN_WARNING("There's nothing to draw something from."))
+ return TRUE
+
+ if(istype(used_item, /obj/item/seeds))
+ plant_seed(user, used_item)
+ return TRUE
+
+ if (istype(used_item, /obj/item/plants))
physical_attack_hand(user) // Harvests and clears out dead plants.
- if(O.storage)
+ if(used_item.storage)
for (var/obj/item/food/grown/G in get_turf(user))
- if(O.storage.can_be_inserted(G, user))
- O.storage.handle_item_insertion(user, G, TRUE)
+ if(used_item.storage.can_be_inserted(G, user))
+ used_item.storage.handle_item_insertion(user, G, TRUE)
return TRUE
- if ( istype(O, /obj/item/plantspray) )
+ if ( istype(used_item, /obj/item/plantspray) )
- var/obj/item/plantspray/spray = O
+ var/obj/item/plantspray/spray = used_item
toxins += spray.toxicity
pestlevel -= spray.pest_kill_str
weedlevel -= spray.weed_kill_str
update_icon()
- to_chat(user, "You spray [src] with [O].")
+ to_chat(user, "You spray [src] with [used_item].")
playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6)
- qdel(O)
+ qdel(used_item)
check_plant_health()
return TRUE
- if(mechanical && IS_WRENCH(O))
+ if(mechanical && IS_WRENCH(used_item))
//If there's a connector here, the portable_atmospherics setup can handle it.
if(locate(/obj/machinery/atmospherics/portables_connector/) in loc)
@@ -491,18 +498,18 @@
to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].")
return TRUE
- var/force = O.get_attack_force(user)
+ var/force = used_item.get_attack_force(user)
if(force && seed)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
- user.visible_message("\The [seed.display_name] has been attacked by [user] with \the [O]!")
- playsound(get_turf(src), O.hitsound, 100, 1)
+ user.visible_message("\The [seed.display_name] has been attacked by [user] with \the [used_item]!")
+ playsound(get_turf(src), used_item.hitsound, 100, 1)
if(!dead)
plant_health -= force
check_plant_health()
return TRUE
if(mechanical)
- return component_attackby(O, user)
+ return component_attackby(used_item, user)
return ..()
@@ -669,6 +676,7 @@
/decl/interaction_handler/hydroponics/close_lid
name = "Open/Close Lid"
+ examine_desc = "open or close the lid"
/decl/interaction_handler/hydroponics/close_lid/is_possible(atom/target, mob/user, obj/item/prop)
var/obj/machinery/portable_atmospherics/hydroponics/tray = target
@@ -680,6 +688,7 @@
/decl/interaction_handler/hydroponics/sample
name = "Sample Plant"
+ examine_desc = "take a sample"
/decl/interaction_handler/hydroponics/sample/is_possible(atom/target, mob/user, obj/item/prop)
return ..() && istype(prop) && prop.edge && prop.w_class < ITEM_SIZE_NORMAL
diff --git a/code/modules/hydroponics/trays/tray_soil.dm b/code/modules/hydroponics/trays/tray_soil.dm
index 6a5d7898104..46ab1b85227 100644
--- a/code/modules/hydroponics/trays/tray_soil.dm
+++ b/code/modules/hydroponics/trays/tray_soil.dm
@@ -21,8 +21,8 @@
/obj/machinery/portable_atmospherics/hydroponics/soil/get_alt_interactions(var/mob/user)
. = ..()
- . -= /decl/interaction_handler/drink
- . -= /decl/interaction_handler/wash_hands
+ LAZYREMOVE(., global._reagent_interactions)
+ LAZYADD(., /decl/interaction_handler/empty_into)
/obj/machinery/portable_atmospherics/hydroponics/soil/Initialize()
diff --git a/code/modules/interactions/_interactions.dm b/code/modules/interactions/_interactions.dm
index ebdd06610dd..3d515a3000d 100644
--- a/code/modules/interactions/_interactions.dm
+++ b/code/modules/interactions/_interactions.dm
@@ -1,12 +1,17 @@
/decl/interaction_handler
abstract_type = /decl/interaction_handler
var/name
+ /// A string displayed when examining an atom that provides this handler as an alt interaction.
+ var/examine_desc
+ /// If set to TRUE, alt interactions will skip is_possible() before displaying in examine().
+ var/always_show_on_examine = FALSE
var/icon
var/icon_state
var/expected_target_type = /atom
var/expected_user_type = /mob/living
var/interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION
var/incapacitation_flags
+ var/apply_click_cooldown = DEFAULT_ATTACK_COOLDOWN
/decl/interaction_handler/proc/is_possible(var/atom/target, var/mob/user, var/obj/item/prop)
diff --git a/code/modules/interactions/interactions_atom.dm b/code/modules/interactions/interactions_atom.dm
index e8073b75f4a..980172b26b2 100644
--- a/code/modules/interactions/interactions_atom.dm
+++ b/code/modules/interactions/interactions_atom.dm
@@ -1,4 +1,4 @@
-/atom/proc/try_handle_interactions(var/mob/user, var/list/interactions, var/obj/item/prop)
+/atom/proc/try_handle_interactions(var/mob/user, var/list/interactions, var/obj/item/prop, var/check_alt_interactions)
if(!length(interactions))
return FALSE
@@ -18,9 +18,17 @@
if(length(possibilities) > 1 || (choice.interaction_flags & INTERACTION_NEVER_AUTOMATIC))
choice = null
choice = show_radial_menu(user, src, possibilities, use_labels = RADIAL_LABELS_CENTERED)
- if(!istype(choice) || QDELETED(user) || !(choice.type in get_alt_interactions(user)) || !choice.is_possible(src, user, prop))
+ if(!istype(choice) || QDELETED(user) || QDELETED(src))
+ return TRUE
+ // This is not ideal but I don't want to pass a callback through here as a param and call it. :(
+ var/list/new_interactions = check_alt_interactions ? get_alt_interactions(user) : get_standard_interactions(user)
+ if(!(choice.type in new_interactions))
+ return TRUE
+ if(!choice.is_possible(src, user, user.get_active_held_item()))
return TRUE
user.face_atom(src)
choice.invoked(src, user, prop)
+ if(choice.apply_click_cooldown)
+ user.setClickCooldown(choice.apply_click_cooldown)
return TRUE
diff --git a/code/modules/interactions/interactions_reagents.dm b/code/modules/interactions/interactions_reagents.dm
index 79885549cc4..8b584709c4c 100644
--- a/code/modules/interactions/interactions_reagents.dm
+++ b/code/modules/interactions/interactions_reagents.dm
@@ -1,6 +1,7 @@
/decl/interaction_handler/dip_item
name = "Dip Into"
interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC
+ examine_desc = "dip an item into $TARGET_THEM$"
/decl/interaction_handler/dip_item/is_possible(atom/target, mob/user, obj/item/prop)
return ..() && target.reagents?.total_volume >= FLUID_MINIMUM_TRANSFER && istype(prop) && target.can_be_poured_from(user, prop)
@@ -19,6 +20,7 @@
/decl/interaction_handler/fill_from
name = "Fill From"
interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC
+ examine_desc = "fill a held item from $TARGET_THEM$"
/decl/interaction_handler/fill_from/is_possible(atom/target, mob/user, obj/item/prop)
if(!(. = ..()))
@@ -41,6 +43,7 @@
/decl/interaction_handler/empty_into
name = "Pour Into"
interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC
+ examine_desc = "pour a held item into $TARGET_THEM$"
/decl/interaction_handler/empty_into/is_possible(atom/target, mob/user, obj/item/prop)
if(!(. = ..()))
@@ -57,6 +60,7 @@
name = "Wash Hands"
expected_target_type = /atom
interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC
+ examine_desc = "wash your hands in $TARGET_THEM$"
/decl/interaction_handler/wash_hands/is_possible(atom/target, mob/user, obj/item/prop)
. = ..() && !istype(prop) && target?.reagents?.has_reagent(/decl/material/liquid/water, 150)
@@ -105,6 +109,7 @@
name = "Drink"
expected_target_type = /atom
interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC
+ examine_desc = "drink from $TARGET_THEM$"
/decl/interaction_handler/drink/is_possible(atom/target, mob/user, obj/item/prop)
return ..() && !istype(prop) && target.can_drink_from(user)
diff --git a/code/modules/interactions/interactions_shared.dm b/code/modules/interactions/interactions_shared.dm
index db486feb277..b8f50f15113 100644
--- a/code/modules/interactions/interactions_shared.dm
+++ b/code/modules/interactions/interactions_shared.dm
@@ -3,25 +3,30 @@
name = "Eject Disk"
icon = 'icons/screen/radial.dmi'
icon_state = "radial_eject"
+ examine_desc = "remove a disk"
/decl/interaction_handler/set_transfer
name = "Set Transfer Amount"
abstract_type = /decl/interaction_handler/set_transfer
+ examine_desc = "set the transfer amount"
/decl/interaction_handler/remove_id
name = "Remove ID"
icon = 'icons/screen/radial.dmi'
icon_state = "radial_eject_id"
abstract_type = /decl/interaction_handler/remove_id
+ examine_desc = "remove an ID card"
/decl/interaction_handler/remove_pen
name = "Remove Pen"
icon = 'icons/screen/radial.dmi'
icon_state = "radial_eject_pen"
abstract_type = /decl/interaction_handler/remove_pen
+ examine_desc = "remove a pen"
/decl/interaction_handler/rename
name = "Rename"
icon = 'icons/screen/radial.dmi'
icon_state = "radial_rename"
abstract_type = /decl/interaction_handler/rename
+ examine_desc = "rename $TARGET_THEM$"
diff --git a/code/modules/materials/_materials.dm b/code/modules/materials/_materials.dm
index b17f238fcb4..4633de8a6ca 100644
--- a/code/modules/materials/_materials.dm
+++ b/code/modules/materials/_materials.dm
@@ -756,28 +756,27 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay)
M.adjust_fire_intensity(floor((amount * accelerant_value)/FLAMMABLE_LIQUID_DIVISOR))
#undef FLAMMABLE_LIQUID_DIVISOR
-/decl/material/proc/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) // Cleaner cleaning, lube lubbing, etc, all go here
+/decl/material/proc/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder) // Cleaner cleaning, lube lubbing, etc, all go here
if(REAGENT_VOLUME(holder, type) < turf_touch_threshold)
return
- if(istype(T) && T.simulated)
- var/turf/wall/W = T
+ if(istype(touching_turf) && touching_turf.simulated)
if(defoliant)
- for(var/obj/effect/overlay/wallrot/E in W)
- W.visible_message(SPAN_NOTICE("\The [E] is completely dissolved by the solution!"))
- qdel(E)
- if(slipperiness != 0 && !T.check_fluid_depth()) // Don't make floors slippery if they have an active fluid on top of them please.
+ for(var/obj/effect/overlay/wallrot/rot in touching_turf)
+ touching_turf.visible_message(SPAN_NOTICE("\The [rot] is completely dissolved by the solution!"))
+ qdel(rot)
+ if(slipperiness != 0 && !touching_turf.check_fluid_depth()) // Don't make floors slippery if they have an active fluid on top of them please.
if(slipperiness < 0)
- W.unwet_floor(TRUE)
+ touching_turf.unwet_floor(TRUE)
else if (REAGENT_VOLUME(holder, type) >= slippery_amount)
- W.wet_floor(slipperiness)
+ touching_turf.wet_floor(slipperiness)
if(length(vapor_products))
var/volume = REAGENT_VOLUME(holder, type)
var/temperature = holder?.my_atom?.temperature || T20C
for(var/vapor in vapor_products)
- T.assume_gas(vapor, (volume * vapor_products[vapor]), temperature)
+ touching_turf.assume_gas(vapor, (volume * vapor_products[vapor]), temperature)
holder.remove_reagent(type, volume)
/decl/material/proc/on_mob_life(var/mob/living/M, var/metabolism_class, var/datum/reagents/holder, var/list/life_dose_tracker)
@@ -1012,9 +1011,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay)
holder.remove_reagent(type, REAGENT_VOLUME(holder, type))
. = TRUE
-/decl/material/proc/affect_overdose(mob/living/M, total_dose) // Overdose effect. Doesn't happen instantly.
- M.add_chemical_effect(CE_TOXIN, 1)
- M.take_damage(REM, TOX)
+/decl/material/proc/affect_overdose(mob/living/victim, total_dose) // Overdose effect. Doesn't happen instantly.
+ victim.add_chemical_effect(CE_TOXIN, 1)
+ victim.take_damage(REM, TOX)
/decl/material/proc/initialize_data(list/newdata) // Called when the reagent is first added to a reagents datum.
. = newdata
diff --git a/code/modules/materials/definitions/liquids/materials_liquid_solvents.dm b/code/modules/materials/definitions/liquids/materials_liquid_solvents.dm
index bbfa9096bfe..ec78c02b460 100644
--- a/code/modules/materials/definitions/liquids/materials_liquid_solvents.dm
+++ b/code/modules/materials/definitions/liquids/materials_liquid_solvents.dm
@@ -1,6 +1,6 @@
/decl/material/liquid/acid
- name = "sulphuric acid"
- uid = "liquid_sulphuric_acid"
+ name = "sulfuric acid"
+ uid = "liquid_sulfuric_acid"
lore_text = "A very corrosive mineral acid with the molecular formula H2SO4."
taste_description = "acid"
color = "#db5008"
diff --git a/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm b/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm
index 6b76cad038a..3b42ee375e4 100644
--- a/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm
+++ b/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm
@@ -128,16 +128,14 @@
..()
ADJ_STATUS(M, STAT_CONFUSE, 1.5)
-/decl/material/liquid/heartstopper/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/heartstopper/affect_overdose(mob/living/victim, total_dose)
..()
- if(ishuman(M))
- var/mob/living/human/H = M
- if(H.stat != UNCONSCIOUS)
- if(H.ticks_since_last_successful_breath >= 10)
- H.ticks_since_last_successful_breath = max(10, H.ticks_since_last_successful_breath-10)
- H.take_damage(2, OXY)
- SET_STATUS_MAX(H, STAT_WEAK, 10)
- M.add_chemical_effect(CE_NOPULSE, 1)
+ if(victim.stat != UNCONSCIOUS)
+ if(victim.ticks_since_last_successful_breath >= 10)
+ victim.ticks_since_last_successful_breath = max(10, victim.ticks_since_last_successful_breath-10)
+ victim.take_damage(2, OXY)
+ SET_STATUS_MAX(victim, STAT_WEAK, 10)
+ victim.add_chemical_effect(CE_NOPULSE, 1)
/decl/material/liquid/zombiepowder
name = "zombie powder"
diff --git a/code/modules/materials/definitions/liquids/materials_liquid_water.dm b/code/modules/materials/definitions/liquids/materials_liquid_water.dm
index e9ca35c6c78..efb84cdf8e7 100644
--- a/code/modules/materials/definitions/liquids/materials_liquid_water.dm
+++ b/code/modules/materials/definitions/liquids/materials_liquid_water.dm
@@ -48,22 +48,23 @@
affect_blood(M, removed, holder)
#define WATER_LATENT_HEAT 9500 // How much heat is removed when applied to a hot turf, in J/unit (9500 makes 120 u of water roughly equivalent to 2L
-/decl/material/liquid/water/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
+/decl/material/liquid/water/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
..()
- if(!istype(T))
+ if(!istype(touching_turf))
return
- var/datum/gas_mixture/environment = T.return_air()
+ var/datum/gas_mixture/environment = touching_turf.return_air()
var/min_temperature = T20C + rand(0, 20) // Room temperature + some variance. An actual diminishing return would be better, but this is *like* that. In a way. . This has the potential for weird behavior, but I says fuck it. Water grenades for everyone.
- var/hotspot = (locate(/obj/fire) in T)
- if(hotspot && !isspaceturf(T))
- var/datum/gas_mixture/lowertemp = T.remove_air(T:air:total_moles)
+ // TODO: Cannot for the life of me work out what this is doing or why it's reducing the air temp by 2000; shouldn't it just be using environment?
+ var/hotspot = (locate(/obj/fire) in touching_turf)
+ if(hotspot && !isspaceturf(touching_turf))
+ var/datum/gas_mixture/lowertemp = touching_turf.remove_air(touching_turf:air:total_moles)
lowertemp.temperature = max(min(lowertemp.temperature-2000, lowertemp.temperature / 2), 0)
lowertemp.react()
- T.assume_air(lowertemp)
+ touching_turf.assume_air(lowertemp)
qdel(hotspot)
var/volume = REAGENT_VOLUME(holder, type)
@@ -71,11 +72,11 @@
var/removed_heat = clamp(volume * WATER_LATENT_HEAT, 0, -environment.get_thermal_energy_change(min_temperature))
environment.add_thermal_energy(-removed_heat)
if (prob(5) && environment && environment.temperature > T100C)
- T.visible_message("The water sizzles as it lands on \the [T]!")
+ touching_turf.visible_message(SPAN_NOTICE("The water sizzles as it lands on \the [touching_turf]!"))
var/list/data = REAGENT_DATA(holder, type)
if(LAZYACCESS(data, "holy"))
- T.turf_flags |= TURF_FLAG_HOLY
+ touching_turf.turf_flags |= TURF_FLAG_HOLY
/decl/material/liquid/water/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder)
..()
diff --git a/code/modules/materials/definitions/solids/materials_solid_exotic.dm b/code/modules/materials/definitions/solids/materials_solid_exotic.dm
index 1d3448bdfed..f0bc71d7a18 100644
--- a/code/modules/materials/definitions/solids/materials_solid_exotic.dm
+++ b/code/modules/materials/definitions/solids/materials_solid_exotic.dm
@@ -34,7 +34,7 @@
/decl/material/solid/exotic_matter
name = "exotic matter"
uid = "solid_exotic_matter"
- lore_text = "Hypercrystalline supermatter is a subset of non-baryonic 'exotic' matter. It is found mostly in the heart of large stars, and features heavily in all kinds of fringe physics-defying technology."
+ lore_text = "Exotic matter is a non-baryonic form of matter, which features heavily in all kinds of fringe physics-defying technology."
color = "#ffff00"
radioactivity = 20
stack_origin_tech = @'{"wormholes":2,"materials":6,"exoticmatter":4}'
diff --git a/code/modules/materials/definitions/solids/materials_solid_ice.dm b/code/modules/materials/definitions/solids/materials_solid_ice.dm
index 34144fe8393..a6b33d5a584 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"
+ adjective_name = "snow"
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
+ default_solid_form = /obj/item/stack/material/lump/large
can_backfill_floor_type = /decl/flooring/snow
/decl/material/solid/ice/aspium
diff --git a/code/modules/mechs/equipment/engineering.dm b/code/modules/mechs/equipment/engineering.dm
index 72bf68d6732..f2f7448b2d6 100644
--- a/code/modules/mechs/equipment/engineering.dm
+++ b/code/modules/mechs/equipment/engineering.dm
@@ -63,6 +63,7 @@
/decl/interaction_handler/mech_equipment/adjust_atmos_shields
name = "Adjust Atmos Shields"
expected_target_type = /obj/item/mech_equipment/atmos_shields
+ examine_desc = "adjust the atmos shields"
/decl/interaction_handler/mech_equipment/adjust_atmos_shields/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/mech_equipment/atmos_shields/shields = target
diff --git a/code/modules/mechs/equipment/utility.dm b/code/modules/mechs/equipment/utility.dm
index f76503b97bb..b5fb55b0461 100644
--- a/code/modules/mechs/equipment/utility.dm
+++ b/code/modules/mechs/equipment/utility.dm
@@ -196,6 +196,7 @@
/decl/interaction_handler/mech_equipment/clamp
name = "Release Clamp"
expected_target_type = /obj/item/mech_equipment/clamp
+ examine_desc = "release $TARGET_THEM$"
/decl/interaction_handler/mech_equipment/clamp/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/mech_equipment/clamp/clamp = target
@@ -693,6 +694,7 @@
/decl/interaction_handler/mech_equipment/ionjets
name = "Toggle Stabilizers"
expected_target_type = /obj/item/mech_equipment/ionjets
+ examine_desc = "toggle the stabilizers"
/decl/interaction_handler/mech_equipment/ionjets/is_possible(atom/target, mob/user, obj/item/prop)
. = ..()
diff --git a/code/modules/mechs/mech_movement.dm b/code/modules/mechs/mech_movement.dm
index 3c8eeea0d04..3fc3f1c2537 100644
--- a/code/modules/mechs/mech_movement.dm
+++ b/code/modules/mechs/mech_movement.dm
@@ -11,13 +11,8 @@
if(.)
if(!isspaceturf(loc))
playsound(src.loc, mech_step_sound, 40, 1)
-
- var/turf/B = GetAbove(src)
-
- for(var/thing in pilots)
- var/mob/pilot = thing
- if(pilot.up_hint)
- pilot.up_hint.icon_state = "uphint[!!(B && TURF_IS_MIMICKING(B))]"
+ for(var/mob/pilot as anything in pilots)
+ pilot.up_hint?.update_icon()
//Inertia drift making us face direction makes exosuit flight a bit difficult, plus newtonian flight model yo
/mob/living/exosuit/set_dir(ndir)
diff --git a/code/modules/mining/ore_box.dm b/code/modules/mining/ore_box.dm
index f61ac8e6886..f4090637855 100644
--- a/code/modules/mining/ore_box.dm
+++ b/code/modules/mining/ore_box.dm
@@ -4,8 +4,8 @@
/obj/structure/ore_box
name = "ore box"
desc = "A heavy box used for storing ore."
- icon = 'icons/obj/mining.dmi'
- icon_state = "orebox0"
+ icon = 'icons/obj/structures/ore_box.dmi'
+ icon_state = ICON_STATE_WORLD
density = TRUE
material = /decl/material/solid/organic/wood/oak
atom_flags = ATOM_FLAG_CLIMBABLE
@@ -148,6 +148,7 @@
/decl/interaction_handler/empty/ore_box
name = "Empty Box"
expected_target_type = /obj/structure/ore_box
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/empty/ore_box/is_possible(obj/structure/ore_box/target, mob/user, obj/item/prop)
return ..() && target.total_ores > 0
diff --git a/code/modules/mob/living/human/human.dm b/code/modules/mob/living/human/human.dm
index 386e4b4d60f..100b55bf3e8 100644
--- a/code/modules/mob/living/human/human.dm
+++ b/code/modules/mob/living/human/human.dm
@@ -5,14 +5,12 @@
icon_state = "body_m_s"
mob_sort_value = 6
max_health = 150
-
- var/list/hud_list[10]
var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us.
/mob/living/human/Initialize(mapload, species_name, datum/mob_snapshot/supplied_appearance)
current_health = max_health
- setup_hud_overlays()
+ reset_hud_overlays()
var/list/newargs = args.Copy(2)
setup_human(arglist(newargs))
global.human_mob_list |= src
@@ -32,18 +30,6 @@
if(. != INITIALIZE_HINT_QDEL)
post_setup(arglist(newargs))
-/mob/living/human/proc/setup_hud_overlays()
- hud_list[HEALTH_HUD] = new /image/hud_overlay('icons/mob/hud_med.dmi', src, "100")
- hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy")
- hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy")
- hud_list[ID_HUD] = new /image/hud_overlay(global.using_map.id_hud_icons, src, "hudunknown")
- hud_list[WANTED_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPLOYAL_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPCHEM_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPTRACK_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[SPECIALROLE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[STATUS_HUD_OOC] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy")
-
/mob/living/human/Destroy()
global.human_mob_list -= src
regenerate_body_icon = FALSE // don't bother regenerating if we happen to be queued to update icon
diff --git a/code/modules/mob/living/human/human_movement.dm b/code/modules/mob/living/human/human_movement.dm
index a31e6788e00..39f3c3a2841 100644
--- a/code/modules/mob/living/human/human_movement.dm
+++ b/code/modules/mob/living/human/human_movement.dm
@@ -118,8 +118,7 @@
handle_leg_damage()
species.handle_post_move(src)
if(client)
- var/turf/B = GetAbove(src)
- up_hint.icon_state = "uphint[!!(B && TURF_IS_MIMICKING(B))]"
+ up_hint.update_icon()
/mob/living/human/proc/handle_leg_damage()
if(!can_feel_pain())
diff --git a/code/modules/mob/living/human/life.dm b/code/modules/mob/living/human/life.dm
index 1bb84a587db..ebc47ef1202 100644
--- a/code/modules/mob/living/human/life.dm
+++ b/code/modules/mob/living/human/life.dm
@@ -746,7 +746,8 @@
if(I)
var/datum/job/J = SSjobs.get_by_title(I.GetJobName())
if(J)
- holder.icon_state = J.hud_icon
+ holder.icon = J.hud_icon
+ holder.icon_state = J.hud_icon_state
hud_list[ID_HUD] = holder
@@ -781,17 +782,16 @@
var/image/holder2 = hud_list[IMPLOYAL_HUD]
var/image/holder3 = hud_list[IMPCHEM_HUD]
- holder1.icon_state = "hudblank"
- holder2.icon_state = "hudblank"
- holder3.icon_state = "hudblank"
-
+ holder1.icon_state = "hud_imp_blank"
+ holder2.icon_state = "hud_imp_blank"
+ holder3.icon_state = "hud_imp_blank"
for(var/obj/item/implant/I in src)
if(I.implanted)
if(istype(I,/obj/item/implant/tracking))
holder1.icon_state = "hud_imp_tracking"
- if(istype(I,/obj/item/implant/loyalty))
+ else if(istype(I,/obj/item/implant/loyalty))
holder2.icon_state = "hud_imp_loyal"
- if(istype(I,/obj/item/implant/chem))
+ else if(istype(I,/obj/item/implant/chem))
holder3.icon_state = "hud_imp_chem"
hud_list[IMPTRACK_HUD] = holder1
diff --git a/code/modules/mob/living/inventory.dm b/code/modules/mob/living/inventory.dm
index 903b1bc8ecb..f0ab7bdc92e 100644
--- a/code/modules/mob/living/inventory.dm
+++ b/code/modules/mob/living/inventory.dm
@@ -62,11 +62,8 @@
if(slot != last_slot && (slot in get_held_item_slots()))
_held_item_slot_selected = slot
if(istype(hud_used))
- for(var/obj/screen/inventory/hand in hud_used.hand_hud_objects)
- hand.cut_overlay("hand_selected")
- if(hand.slot_id == slot)
- hand.add_overlay("hand_selected")
- hand.compile_overlays()
+ for(var/atom/hand as anything in hud_used.hand_hud_objects)
+ hand.update_icon()
var/obj/item/I = get_active_held_item()
if(istype(I))
I.on_active_hand()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 78ba364f39a..a9f88a6c596 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -694,7 +694,14 @@ default behaviour is:
/mob/living/proc/has_brain()
return TRUE
-/mob/living/proc/slip(var/slipped_on, stun_duration = 8)
+// We are jumping, levitating or being thrown.
+/mob/living/immune_to_floor_hazards()
+ . = ..() || is_floating
+
+/mob/living/proc/slip(slipped_on, stun_duration = 8)
+
+ if(immune_to_floor_hazards())
+ return FALSE
var/decl/species/my_species = get_species()
if(my_species?.check_no_slip(src))
@@ -1205,6 +1212,7 @@ default behaviour is:
expected_user_type = /mob/observer
expected_target_type = /mob/living
interaction_flags = 0
+ examine_desc = null // DO NOT show this in general.
/decl/interaction_handler/admin_kill/is_possible(atom/target, mob/user, obj/item/prop)
. = ..()
@@ -1585,7 +1593,7 @@ default behaviour is:
/mob/living/proc/handle_walking_tracks(turf/T, old_loc)
- if(!T.can_show_footsteps())
+ if(!T.can_show_coating_footprints())
return
// Tracking blood or other contaminants
@@ -1923,8 +1931,8 @@ default behaviour is:
var/screen_locs = gear.get_preview_screen_locs()
if(screen_locs)
return screen_locs
- var/decl/species/my_species = get_species()
- return my_species?.character_preview_screen_locs
+ var/decl/bodytype/my_bodytype = get_bodytype()
+ return my_bodytype?.character_preview_screen_locs
/mob/living/can_twohand_item(obj/item/item)
if(!istype(item) || !item.can_be_twohanded)
diff --git a/code/modules/mob/living/living_hud.dm b/code/modules/mob/living/living_hud.dm
new file mode 100644
index 00000000000..5e6b7adfff0
--- /dev/null
+++ b/code/modules/mob/living/living_hud.dm
@@ -0,0 +1,17 @@
+/mob/living
+ var/list/hud_list = new(10)
+
+/mob/living/proc/reset_hud_overlays()
+ hud_list = new(10)
+ hud_list[HEALTH_HUD] = new /image/hud_overlay(global.using_map.med_hud_icons, src, "blank")
+ hud_list[STATUS_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudhealthy")
+ hud_list[LIFE_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudhealthy")
+ hud_list[ID_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudunknown")
+ hud_list[WANTED_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudblank")
+ hud_list[IMPLOYAL_HUD] = new /image/hud_overlay(global.using_map.implant_hud_icons, src, "hud_imp_blank")
+ hud_list[IMPCHEM_HUD] = new /image/hud_overlay(global.using_map.implant_hud_icons, src, "hud_imp_blank")
+ hud_list[IMPTRACK_HUD] = new /image/hud_overlay(global.using_map.implant_hud_icons, src, "hud_imp_blank")
+ hud_list[SPECIALROLE_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudblank")
+ hud_list[STATUS_HUD_OOC] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudhealthy")
+
+/datum/map
diff --git a/code/modules/mob/living/living_maneuvers.dm b/code/modules/mob/living/living_maneuvers.dm
index 8913f7a8190..2afaa16ad4c 100644
--- a/code/modules/mob/living/living_maneuvers.dm
+++ b/code/modules/mob/living/living_maneuvers.dm
@@ -25,13 +25,13 @@
forceMove(get_turf(origin))
prepared_maneuver.perform(src, check, get_acrobatics_multiplier(prepared_maneuver), reflexively = TRUE)
prepared_maneuver = null
- maneuver_icon?.icon_state = "maneuver_off"
+ maneuver_icon?.update_icon()
/mob/living/proc/try_maneuver(var/atom/target)
if(prepared_maneuver && (isturf(target) || isturf(target.loc))) // Avoid trying to jump at your backpack contents.
prepared_maneuver.perform(src, get_turf(target), get_acrobatics_multiplier(prepared_maneuver))
prepared_maneuver = null
- maneuver_icon?.icon_state = "maneuver_off"
+ maneuver_icon?.update_icon()
return TRUE
return FALSE
@@ -59,19 +59,18 @@
if(!maneuver.can_be_used_by(src, null))
return
prepared_maneuver = maneuver
- maneuver_icon?.icon_state = "maneuver_on"
to_chat(src, SPAN_NOTICE("You prepare to [prepared_maneuver.name]."))
else
prepared_maneuver = null
- maneuver_icon?.icon_state = "maneuver_off"
to_chat(src, SPAN_NOTICE("You are no longer preparing to perform a maneuver."))
+ maneuver_icon?.update_icon()
/mob/living/proc/perform_maneuver(var/maneuver, var/atom/target)
var/decl/maneuver/performing_maneuver = ispath(maneuver) ? GET_DECL(maneuver) : maneuver
if(istype(performing_maneuver))
. = performing_maneuver.perform(src, target, get_acrobatics_multiplier(performing_maneuver))
prepared_maneuver = null
- maneuver_icon?.icon_state = "maneuver_off"
+ maneuver_icon?.update_icon()
/mob/living/proc/get_acrobatics_multiplier(var/decl/maneuver/attempting_maneuver)
return 1
diff --git a/code/modules/mob/living/living_status.dm b/code/modules/mob/living/living_status.dm
index 661787ae356..645b5323448 100644
--- a/code/modules/mob/living/living_status.dm
+++ b/code/modules/mob/living/living_status.dm
@@ -1,9 +1,11 @@
/mob // Defined on /mob to avoid having to pass args to every single attack_foo() proc.
- var/datum/status_marker_holder/status_markers
var/list/status_counters
var/list/pending_status_counters
+ var/datum/status_marker_holder/status_markers
/mob/living/set_status(var/condition, var/amount)
+ if(QDELETED(src))
+ return FALSE
if(!ispath(condition, /decl/status_condition))
return FALSE
var/decl/status_condition/cond = GET_DECL(condition)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index e9920873353..230f370eda2 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -149,15 +149,7 @@ var/global/list/ai_verbs_default = list(
. = INITIALIZE_HINT_QDEL
else if(brainmob.mind)
brainmob.mind.transfer_to(src)
- hud_list[HEALTH_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[ID_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[WANTED_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPLOYAL_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPCHEM_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPTRACK_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[SPECIALROLE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
+ reset_hud_overlays()
ai_list += src
create_powersupply()
diff --git a/code/modules/mob/living/silicon/robot/flying/module_flying_repair.dm b/code/modules/mob/living/silicon/robot/flying/module_flying_repair.dm
index 8a060e833c2..259ac5bf9a5 100644
--- a/code/modules/mob/living/silicon/robot/flying/module_flying_repair.dm
+++ b/code/modules/mob/living/silicon/robot/flying/module_flying_repair.dm
@@ -4,8 +4,7 @@
channels = list ("Engineering" = TRUE)
camera_channels = list(CAMERA_CAMERA_CHANNEL_ENGINEERING)
software = list(
- /datum/computer_file/program/power_monitor,
- /datum/computer_file/program/supermatter_monitor
+ /datum/computer_file/program/power_monitor
)
module_sprites = list(
"Drone" = 'icons/mob/robots/flying/flying_engineering.dmi',
diff --git a/code/modules/mob/living/silicon/robot/modules/_module.dm b/code/modules/mob/living/silicon/robot/modules/_module.dm
index 87216dc3704..ee0046ef2ae 100644
--- a/code/modules/mob/living/silicon/robot/modules/_module.dm
+++ b/code/modules/mob/living/silicon/robot/modules/_module.dm
@@ -233,3 +233,6 @@
var/obj/item/stock_parts/computer/hard_drive/disk = os.get_component(PART_HDD)
for(var/T in software)
disk.store_file(new T(disk), OS_PROGRAMS_DIR, TRUE)
+
+/obj/item/robot_module/proc/handle_turf(turf/target, mob/user)
+ return
diff --git a/code/modules/mob/living/silicon/robot/modules/module_engineering.dm b/code/modules/mob/living/silicon/robot/modules/module_engineering.dm
index d79de772719..d0b1f9456e3 100644
--- a/code/modules/mob/living/silicon/robot/modules/module_engineering.dm
+++ b/code/modules/mob/living/silicon/robot/modules/module_engineering.dm
@@ -8,8 +8,7 @@
CAMERA_CAMERA_CHANNEL_ENGINEERING
)
software = list(
- /datum/computer_file/program/power_monitor,
- /datum/computer_file/program/supermatter_monitor
+ /datum/computer_file/program/power_monitor
)
supported_upgrades = list(
/obj/item/borg/upgrade/rcd
diff --git a/code/modules/mob/living/silicon/robot/modules/module_janitor.dm b/code/modules/mob/living/silicon/robot/modules/module_janitor.dm
index 651a88e5b4e..e88d8b13112 100644
--- a/code/modules/mob/living/silicon/robot/modules/module_janitor.dm
+++ b/code/modules/mob/living/silicon/robot/modules/module_janitor.dm
@@ -23,10 +23,13 @@
)
emag = /obj/item/chems/spray
+/obj/item/robot_module/janitor/handle_turf(turf/target, mob/user)
+ target.clean()
+
/obj/item/robot_module/janitor/finalize_emag()
. = ..()
emag.add_to_reagents(/decl/material/liquid/lube, 250)
- emag.SetName("Lube spray")
+ emag.SetName("lubricant spray")
/obj/item/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
..()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 08ee95501bd..4421aabf243 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -88,6 +88,9 @@
)
/mob/living/silicon/robot/Initialize()
+
+ reset_hud_overlays()
+
. = ..()
add_language(/decl/language/binary, 1)
@@ -126,16 +129,6 @@
// Disables lay down verb for robots due they're can't lay down and it cause some movement, vision issues.
verbs -= /mob/living/verb/lay_down
- hud_list[HEALTH_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealth100")
- hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealth100")
- hud_list[ID_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[WANTED_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPLOYAL_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPCHEM_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[IMPTRACK_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
- hud_list[SPECIALROLE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank")
-
AddMovementHandler(/datum/movement_handler/robot/use_power, /datum/movement_handler/mob/space)
/mob/living/silicon/robot/proc/recalculate_synth_capacities()
@@ -824,15 +817,15 @@
/mob/living/silicon/robot/Move(a, b, flag)
. = ..()
if(.)
+
if(module && isturf(loc))
var/obj/item/ore/orebag = locate() in list(module_state_1, module_state_2, module_state_3)
if(orebag)
loc.attackby(orebag, src)
- if(istype(module, /obj/item/robot_module/janitor))
- loc.clean()
+ module.handle_turf(loc, src)
+
if(client)
- var/turf/above = GetAbove(src)
- up_hint.icon_state = "uphint[!!(above && TURF_IS_MIMICKING(above))]"
+ up_hint.update_icon()
/mob/living/silicon/robot/proc/UnlinkSelf()
disconnect_from_ai()
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 52457ceb078..0ec86995aff 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -10,7 +10,6 @@
var/list/stating_laws = list()// Channels laws are currently being stated on
var/obj/item/radio/silicon_radio
- var/list/hud_list[10]
var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer
//Used in say.dm.
@@ -40,6 +39,7 @@
#define MED_HUD 2 //Medical HUD mode
/mob/living/silicon/Initialize()
+ reset_hud_overlays()
global.silicon_mob_list += src
. = ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index be7858c6c04..6571031649c 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -245,7 +245,7 @@ var/global/chicken_count = 0
global.chicken_count -= 1
/mob/living/simple_animal/fowl/chicken/attackby(var/obj/item/O, var/mob/user)
- if(istype(O, /obj/item/food))
+ if(!istype(O, /obj/item/food))
return ..()
var/obj/item/food/G = O //feedin' dem chickens
if(findtext(G.get_grown_tag(), "wheat")) // includes chopped, crushed, dried etc.
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index 7903631bb68..3bd462aca86 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -113,11 +113,6 @@
update_action_buttons()
update_mouse_pointer()
- if(ability_master)
- ability_master.update_abilities(TRUE, src)
- ability_master.toggle_open(1)
- ability_master.synch_spells_to_mind(mind)
-
if(get_preference_value(/datum/client_preference/show_status_markers) == PREF_SHOW)
if(status_markers?.mob_image_personal)
client.images |= status_markers.mob_image_personal
@@ -130,7 +125,7 @@
if(istype(hud_used))
hud_used.hidden_inventory_update()
- hud_used.persistant_inventory_update()
+ hud_used.persistent_inventory_update()
update_action_buttons()
return TRUE
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 03827667a28..512db5f11ba 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -17,8 +17,6 @@
QDEL_NULL(hud_used)
if(active_storage)
active_storage.close(src)
- if(istype(ability_master))
- QDEL_NULL(ability_master)
if(istype(skillset))
QDEL_NULL(skillset)
QDEL_NULL_LIST(grabbed_by)
@@ -57,7 +55,6 @@
QDEL_NULL_SCREEN(radio_use_icon)
QDEL_NULL_SCREEN(gun_move_icon)
QDEL_NULL_SCREEN(gun_setting_icon)
- QDEL_NULL_SCREEN(ability_master)
QDEL_NULL_SCREEN(zone_sel)
/mob/Initialize()
@@ -68,7 +65,6 @@
if(!istype(move_intent))
move_intent = GET_DECL(move_intent)
. = ..()
- ability_master = new(null, src)
refresh_ai_handler()
START_PROCESSING(SSmobs, src)
@@ -242,8 +238,6 @@
SHOULD_NOT_SLEEP(TRUE)
if(QDELETED(src))
return PROCESS_KILL
- if(ability_master)
- ability_master.update_spells(0)
#define UNBUCKLED 0
#define PARTIALLY_BUCKLED 1
@@ -896,7 +890,7 @@
/mob/proc/toggle_throw_mode(force_set)
in_throw_mode = isnull(force_set) ? !in_throw_mode : force_set
- throw_icon?.icon_state = "act_throw_[in_throw_mode ? "on" : "off"]"
+ throw_icon?.update_icon()
/mob/proc/toggle_antag_pool()
set name = "Toggle Add-Antag Candidacy"
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 04318afb971..ec19dd3daed 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -60,7 +60,6 @@
var/obj/screen/gun/radio/radio_use_icon
var/obj/screen/gun/move/gun_move_icon
var/obj/screen/gun/mode/gun_setting_icon
- var/obj/screen/ability_master/ability_master
/*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob.
A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such.
diff --git a/code/modules/mob/mob_intent.dm b/code/modules/mob/mob_intent.dm
index 39a1a9c5606..b55b2342ed8 100644
--- a/code/modules/mob/mob_intent.dm
+++ b/code/modules/mob/mob_intent.dm
@@ -29,6 +29,8 @@
var/intent_flags = 0
/// Descriptive string used in status panel.
var/name
+ /// Descriptive string shown when examined.
+ var/desc
/// Icon used to draw this intent in the selector.
var/icon = 'icons/screen/intents.dmi'
/// State used to update intent selector.
@@ -51,31 +53,35 @@
// Basic subtypes.
/decl/intent/harm
name = "harm"
+ desc = "HARM INTENT: you will attempt to damage, disrupt or destroy whatever you interact with."
uid = "intent_harm"
intent_flags = I_FLAG_HARM
icon_state = "intent_harm"
- sort_order = 1 // Bottom left of intent selector.
+ sort_order = 4 // Corresponding to hotkey order.
/decl/intent/grab
name = "grab"
+ desc = "GRAB INTENT: you will attempt to grab hold of any object or creature you interact with."
uid = "intent_grab"
intent_flags = I_FLAG_GRAB
icon_state = "intent_grab"
- sort_order = 2 // Bottom left of the intent selector.
+ sort_order = 3 // Corresponding to hotkey order.
/decl/intent/help
name = "help"
+ desc = "HELP INTENT: you will attempt to assist, or in general void harming, whatever you interact with."
uid = "intent_help"
intent_flags = I_FLAG_HELP
icon_state = "intent_help"
- sort_order = 3 // Top left of the intent selector.
+ sort_order = 1 // Corresponding to hotkey order.
/decl/intent/disarm
name = "disarm"
+ desc = "DISARM INTENT: you will attempt to disarm or incapacitate any creature you interact with."
uid = "intent_disarm"
intent_flags = I_FLAG_DISARM
icon_state = "intent_disarm"
- sort_order = 4 // Top right of the intent selector.
+ sort_order = 2 // Corresponding to hotkey order.
// Used by nymphs.
/decl/intent/harm/binary
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 21c41101077..a934d39d2e3 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -268,8 +268,8 @@
/mob/proc/set_move_intent(var/decl/move_intent/next_intent)
if(next_intent && move_intent != next_intent && next_intent.can_be_used_by(src))
move_intent = next_intent
- if(istype(hud_used))
- hud_used.move_intent.icon_state = move_intent.hud_icon_state
+ if(istype(hud_used) && hud_used.move_intent)
+ hud_used.move_intent.update_icon()
return TRUE
return FALSE
diff --git a/code/modules/mob/skills/skill.dm b/code/modules/mob/skills/skill.dm
index cd0d2ec8927..87cad27fdb3 100644
--- a/code/modules/mob/skills/skill.dm
+++ b/code/modules/mob/skills/skill.dm
@@ -359,6 +359,7 @@
category = /decl/skill_category/engineering
uid = "skill_engines"
fallback_key = "/decl/hierarchy/skill/engineering/engines"
+ // TODO: These strings should be modified by the supermatter modpack somehow...
desc = "Describes your knowledge of the various engine types common on space stations, such as the PACMAN, singularity, supermatter or RUST engine."
levels = list(
"Unskilled" = "You know that \"delamination\" is a bad thing and that you should stay away from the singularity. You know the engine provides power, but you're unclear on the specifics. If you were to try to set up the engine, you would need someone to talk you through every detail--and even then, you'd probably make deadly mistakes. - You can read the SM monitor readings with 40% error. This decreases with level.",
diff --git a/code/modules/modular_computers/computers/modular_computer/interaction.dm b/code/modules/modular_computers/computers/modular_computer/interaction.dm
index 6bb4a4f41b8..1bfc73fb6a2 100644
--- a/code/modules/modular_computers/computers/modular_computer/interaction.dm
+++ b/code/modules/modular_computers/computers/modular_computer/interaction.dm
@@ -136,10 +136,13 @@
/obj/item/modular_computer/get_alt_interactions(var/mob/user)
. = ..()
- LAZYADD(., /decl/interaction_handler/remove_id/modular_computer)
- LAZYADD(., /decl/interaction_handler/remove_pen/modular_computer)
- LAZYADD(., /decl/interaction_handler/emergency_shutdown)
- LAZYADD(., /decl/interaction_handler/remove_chargestick)
+ var/static/list/_modular_computer_interactions = list(
+ /decl/interaction_handler/remove_id/modular_computer,
+ /decl/interaction_handler/remove_pen/modular_computer,
+ /decl/interaction_handler/emergency_shutdown,
+ /decl/interaction_handler/remove_chargestick
+ )
+ LAZYADD(., _modular_computer_interactions)
//
// Remove ID
@@ -181,6 +184,7 @@
icon = 'icons/screen/radial.dmi'
icon_state = "radial_power_off"
expected_target_type = /obj/item/modular_computer
+ examine_desc = "perform an emergency shutdown"
/decl/interaction_handler/emergency_shutdown/is_possible(atom/target, mob/user, obj/item/prop)
. = ..()
@@ -201,6 +205,7 @@
icon = 'icons/screen/radial.dmi'
icon_state = "radial_eject"
expected_target_type = /obj/item/modular_computer
+ examine_desc = "remove a chargestick"
/decl/interaction_handler/remove_chargestick/is_possible(atom/target, mob/user, obj/item/prop)
. = ..()
diff --git a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm
index ad7c698d6d8..894b912aff9 100644
--- a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm
+++ b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm
@@ -15,7 +15,7 @@
/decl/material/solid/silicon = MATTER_AMOUNT_REINFORCEMENT,
)
var/icon_state_closed = "laptop-closed"
-
+
/obj/item/modular_computer/laptop/on_update_icon()
if(anchored)
..()
@@ -35,6 +35,7 @@
name = "Open Laptop"
expected_target_type = /obj/item/modular_computer/laptop
interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEEDS_TURF
+ examine_desc = "open or close $TARGET_THEM$"
/decl/interaction_handler/laptop_open/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/modular_computer/laptop/L = target
diff --git a/code/modules/modular_computers/computers/subtypes/preset_console.dm b/code/modules/modular_computers/computers/subtypes/preset_console.dm
index c726c3ac6a2..1bc6fd711de 100644
--- a/code/modules/modular_computers/computers/subtypes/preset_console.dm
+++ b/code/modules/modular_computers/computers/subtypes/preset_console.dm
@@ -48,7 +48,6 @@
/obj/machinery/computer/modular/preset/engineering
default_software = list(
/datum/computer_file/program/power_monitor,
- /datum/computer_file/program/supermatter_monitor,
/datum/computer_file/program/alarm_monitor,
/datum/computer_file/program/atmos_control,
/datum/computer_file/program/rcon_console,
diff --git a/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm b/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm
index 23e4122b908..284372c00bf 100644
--- a/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm
+++ b/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm
@@ -68,8 +68,7 @@
default_software = list(
/datum/computer_file/program/alarm_monitor,
/datum/computer_file/program/camera_monitor,
- /datum/computer_file/program/shields_monitor,
- /datum/computer_file/program/supermatter_monitor
+ /datum/computer_file/program/shields_monitor
)
/obj/machinery/computer/modular/telescreen/preset/entertainment
diff --git a/code/modules/modular_computers/file_system/programs/generic/folding.dm b/code/modules/modular_computers/file_system/programs/generic/folding.dm
index 0ea98dcadb4..ebd8214d0ff 100644
--- a/code/modules/modular_computers/file_system/programs/generic/folding.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/folding.dm
@@ -109,7 +109,7 @@
"Simulating Alien Abductions",
"Scanning Pigeons",
"Iterating Chaos Array",
- "Abstracting Supermatter",
+ "Abstracting Exotic Matter",
"Adjusting Social Network",
"Recalculating Clown Principle"
)
diff --git a/code/modules/multiz/level_data.dm b/code/modules/multiz/level_data.dm
index 69ee279edba..d1aeb0bdaee 100644
--- a/code/modules/multiz/level_data.dm
+++ b/code/modules/multiz/level_data.dm
@@ -173,6 +173,14 @@
// Whether or not this level permits things like graffiti and filth to persist across rounds.
var/permit_persistence = FALSE
+ // Submap loading values, passed back via getters like get_subtemplate_budget().
+ /// A point budget to spend on subtemplates (see template costs)
+ var/subtemplate_budget = 0
+ /// A string identifier for the category of subtemplates to draw from for this level.
+ var/subtemplate_category = null
+ /// A specific area to use when determining where to place subtemplates.
+ var/subtemplate_area = null
+
/datum/level_data/New(var/_z_level, var/defer_level_setup = FALSE)
. = ..()
level_z = _z_level
@@ -418,16 +426,22 @@
//
/// Helper proc for subtemplate generation. Returns a point budget to spend on subtemplates.
/datum/level_data/proc/get_subtemplate_budget()
- return 0
+ return subtemplate_budget
/// Helper proc for subtemplate generation. Returns a string identifier for a general category of template.
/datum/level_data/proc/get_subtemplate_category()
- return
+ return subtemplate_category
/// Helper proc for subtemplate generation. Returns a bitflag of template flags that must not be present for a subtemplate to be considered available.
/datum/level_data/proc/get_subtemplate_blacklist()
return
/// Helper proc for subtemplate generation. Returns a bitflag of template flags that must be present for a subtemplate to be considered available.
/datum/level_data/proc/get_subtemplate_whitelist()
return
+/// Helper proc for getting areas associated with placable submaps on this level.
+/datum/level_data/proc/get_subtemplate_areas(template_category, blacklist, whitelist)
+ if(subtemplate_area)
+ return islist(subtemplate_area) ? subtemplate_area : list(subtemplate_area)
+ if(base_area)
+ return list(base_area)
///Called when setting up the level. Apply generators and anything that modifies the turfs of the level.
/datum/level_data/proc/generate_level()
@@ -461,12 +475,34 @@
for(var/gen_type in map_gen)
new gen_type(origx, origy, level_z, endx, endy, FALSE, TRUE, get_base_area_instance())
+/// Helper proc for placing mobs on a level after level creation.
+/datum/level_data/proc/get_mobs_to_populate_level()
+ return
+
///Called during level setup. Run anything that should happen only after the map is fully generated.
/datum/level_data/proc/after_generate_level()
+
build_border()
+
if(daycycle_id && daycycle_type)
SSdaycycle.register_level(level_z, daycycle_id, daycycle_type)
+ var/list/mobs_to_spawn = get_mobs_to_populate_level()
+ if(length(mobs_to_spawn))
+ for(var/list/mob_category in mobs_to_spawn)
+ var/list/mob_types = mob_category[1]
+ var/mob_turf = mob_category[2]
+ var/mob_count = mob_category[3]
+ var/sanity = 1000
+ while(mob_count && sanity)
+ sanity--
+ var/turf/place_mob_at = locate(rand(level_inner_min_x, level_inner_max_x), rand(level_inner_min_y, level_inner_max_y), level_z)
+ if(istype(place_mob_at, mob_turf) && !(locate(/mob/living) in place_mob_at))
+ var/mob_type = pickweight(mob_types)
+ new mob_type(place_mob_at)
+ mob_count--
+ CHECK_TICK
+
///Changes anything named we may need to rename accordingly to the parent location name. For instance, exoplanets levels.
/datum/level_data/proc/adapt_location_name(var/location_name)
SHOULD_CALL_PARENT(TRUE)
@@ -742,9 +778,6 @@ INITIALIZE_IMMEDIATE(/obj/abstract/level_data_spawner)
/datum/random_map/noise/ore
)
-/datum/level_data/proc/get_subtemplate_areas(template_category, blacklist, whitelist)
- return list(base_area)
-
///Try to allocate the given amount of POIs onto our level. Returns the template types that were spawned
/datum/level_data/proc/spawn_subtemplates(budget = 0, template_category, blacklist, whitelist)
diff --git a/code/modules/multiz/mobile_ladder.dm b/code/modules/multiz/mobile_ladder.dm
index 2eacd7a03ac..dec71c399ff 100644
--- a/code/modules/multiz/mobile_ladder.dm
+++ b/code/modules/multiz/mobile_ladder.dm
@@ -130,6 +130,7 @@
/decl/interaction_handler/ladder_fold
name = "Fold Ladder"
expected_target_type = /obj/structure/ladder/mobile
+ examine_desc = "fold $TARGET_THEM$ up"
/decl/interaction_handler/ladder_fold/invoked(atom/target, mob/user, obj/item/prop)
var/obj/structure/ladder/mobile/L
diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm
index 585f57d0d7e..573c28223f1 100644
--- a/code/modules/multiz/movement.dm
+++ b/code/modules/multiz/movement.dm
@@ -91,9 +91,6 @@
if(!has_gravity())
return
- if(throwing)
- return
-
if(can_fall())
begin_falling(lastloc, below)
@@ -115,7 +112,7 @@
//For children to override
/atom/movable/proc/can_fall(var/anchor_bypass = FALSE, var/turf/location_override = loc)
- if(!simulated)
+ if(immune_to_floor_hazards())
return FALSE
if(anchored && !anchor_bypass)
diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm
index 4ba6ad96090..6e22447ab9c 100644
--- a/code/modules/nano/modules/human_appearance.dm
+++ b/code/modules/nano/modules/human_appearance.dm
@@ -116,7 +116,7 @@
hair_styles[++hair_styles.len] = list("hairstyle" = hair_decl.name, "ref" = "\ref[hair_decl]")
data["hair_styles"] = hair_styles
var/hairstyle = GET_HAIR_STYLE(owner)
- var/decl/sprite_accessory/hair = GET_DECL(hairstyle)
+ var/decl/sprite_accessory/hair = GET_DECL(hairstyle) || GET_DECL(/decl/sprite_accessory/hair/bald)
data["hair_style"] = hair.name
data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR)
@@ -127,7 +127,7 @@
facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_decl.name, "ref" = "\ref[facial_hair_decl]")
data["facial_hair_styles"] = facial_hair_styles
var/facial_hairstyle = GET_FACIAL_HAIR_STYLE(owner)
- var/decl/sprite_accessory/facial_hair = GET_DECL(facial_hairstyle)
+ var/decl/sprite_accessory/facial_hair = GET_DECL(facial_hairstyle) || GET_DECL(/decl/sprite_accessory/facial_hair/shaved)
data["facial_hair_style"] = facial_hair.name
data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR)
diff --git a/code/modules/organs/organ_prosthetics.dm b/code/modules/organs/organ_prosthetics.dm
index 03d8abee4ae..a107c79e810 100644
--- a/code/modules/organs/organ_prosthetics.dm
+++ b/code/modules/organs/organ_prosthetics.dm
@@ -9,7 +9,7 @@
// External organ procs:
// Does this bodypart count as a modular limb, and if so, what kind?
/obj/item/organ/external/proc/get_modular_limb_category()
- return isnull(bodytype.modular_limb_tier) ? MODULAR_BODYPART_INVALID : bodytype.modular_limb_tier
+ return isnull(bodytype?.modular_limb_tier) ? MODULAR_BODYPART_INVALID : bodytype.modular_limb_tier
// Checks if a limb could theoretically be removed.
// Note that this does not currently bother checking if a child or internal organ is vital.
diff --git a/code/modules/paperwork/carbonpaper.dm b/code/modules/paperwork/carbonpaper.dm
index 72eb84cc491..5991f75c6c4 100644
--- a/code/modules/paperwork/carbonpaper.dm
+++ b/code/modules/paperwork/carbonpaper.dm
@@ -54,8 +54,9 @@
// Carbon Paper Alt Interactions
/////////////////////////////////////////////////
/decl/interaction_handler/carbon_paper_remove
- name = "remove carbon-copy"
+ name = "Remove Carbon-Copy"
expected_target_type = /obj/item/paper/carbon
+ examine_desc = "remove the carbon-copy"
/decl/interaction_handler/carbon_paper_remove/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/paper/carbon/paper = target
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index d25c1d6cbe5..cd40acd76d9 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -198,6 +198,7 @@
/decl/interaction_handler/clipboard_remove_pen
name = "Remove Pen"
expected_target_type = /obj/item/clipboard
+ examine_desc = "remove the pen"
/decl/interaction_handler/clipboard_remove_pen/is_possible(atom/target, mob/user, obj/item/prop)
. = ..()
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 92a37e75a1b..02428e20f70 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -636,6 +636,8 @@ var/global/datum/topic_state/default/paper_state/paper_topic_state = new
/decl/interaction_handler/scroll/furl
name = "Furl Scroll"
+ examine_desc = "furl $TARGET_THEM$"
/decl/interaction_handler/scroll/unfurl
name = "Unfurl Scroll"
+ examine_desc = "unfurl $TARGET_THEM$"
diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm
index b01ab304426..16a2f1f7ab9 100644
--- a/code/modules/paperwork/paper_bundle.dm
+++ b/code/modules/paperwork/paper_bundle.dm
@@ -517,6 +517,7 @@
/decl/interaction_handler/rename/paper_bundle
name = "Rename Bundle"
expected_target_type = /obj/item/paper_bundle
+ examine_desc = "rename $TARGET_THEM$"
/decl/interaction_handler/rename/paper_bundle/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/paper_bundle/bundle = target
diff --git a/code/modules/paperwork/paper_plane.dm b/code/modules/paperwork/paper_plane.dm
index ac8ebc5d961..2e183472066 100644
--- a/code/modules/paperwork/paper_plane.dm
+++ b/code/modules/paperwork/paper_plane.dm
@@ -77,6 +77,7 @@
/decl/interaction_handler/make_paper_plane
name = "Fold Into Paper Plane"
expected_target_type = /obj/item/paper
+ examine_desc = "make a paper plane"
/decl/interaction_handler/make_paper_plane/is_possible(obj/item/paper/target, mob/user, obj/item/prop)
return ..() && !target.is_crumpled
@@ -91,4 +92,4 @@
/obj/item/paper/get_alt_interactions(mob/user)
. = ..()
- LAZYDISTINCTADD(., /decl/interaction_handler/make_paper_plane)
\ No newline at end of file
+ LAZYADD(., /decl/interaction_handler/make_paper_plane)
\ No newline at end of file
diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm
index 70b9b4c453d..3622d047f5c 100644
--- a/code/modules/paperwork/paperbin.dm
+++ b/code/modules/paperwork/paperbin.dm
@@ -155,6 +155,7 @@
/decl/interaction_handler/paper_bin_dump_contents
name = "Dump Contents"
expected_target_type = /obj/item/paper_bin
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/paper_bin_dump_contents/is_possible(var/obj/item/paper_bin/target, mob/user, obj/item/prop)
return ..() && target.amount > 0
diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm
index 7905a718674..89f88cf959a 100644
--- a/code/modules/paperwork/papershredder.dm
+++ b/code/modules/paperwork/papershredder.dm
@@ -193,6 +193,7 @@
/decl/interaction_handler/empty/paper_shredder
name = "Empty Bin"
expected_target_type = /obj/machinery/papershredder
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/empty/paper_shredder/is_possible(obj/machinery/papershredder/target, mob/user, obj/item/prop)
return ..() && !target.is_bin_empty()
diff --git a/code/modules/paperwork/pen/crayon.dm b/code/modules/paperwork/pen/crayon.dm
index 0c3222998ac..f06419b8711 100644
--- a/code/modules/paperwork/pen/crayon.dm
+++ b/code/modules/paperwork/pen/crayon.dm
@@ -33,24 +33,31 @@
return
if(istype(target) && target.is_floor())
- var/drawtype = input("Choose what you'd like to draw.", "Crayon scribbles") in list("graffiti","rune","letter","arrow")
+ var/static/list/drawtypes = list(CRAYON_DRAW_GRAFFITI, CRAYON_DRAW_RUNE, CRAYON_DRAW_LETTER, CRAYON_DRAW_ARROW)
+ var/drawtype = input(user, "Choose what you'd like to draw.", "Crayon scribbles") as null|anything in drawtypes
var/draw_message = "drawing"
switch(drawtype)
- if("letter")
- drawtype = input("Choose the letter.", "Crayon scribbles") in list(global.alphabet)
+ if(CRAYON_DRAW_LETTER)
+ drawtype = input(user, "Choose a letter.", "Crayon scribbles") as null|anything in global.alphabet
draw_message = "drawing a letter"
- if("graffiti")
+ if(CRAYON_DRAW_GRAFFITI)
draw_message = "drawing graffiti"
- if("rune")
+ if(CRAYON_DRAW_RUNE)
draw_message = "drawing a rune"
- if("arrow")
- drawtype = input("Choose the arrow.", "Crayon scribbles") in list("left", "right", "up", "down")
+ if(CRAYON_DRAW_ARROW)
+ var/static/list/arrow_dirs = list("left", "right", "up", "down")
+ drawtype = input(user, "Choose an arrow.", "Crayon scribbles") as null|anything in arrow_dirs
draw_message = "drawing an arrow"
+ if(!drawtype || QDELETED(src) || QDELETED(target) || QDELETED(user) || user.get_active_held_item() != src || !CanPhysicallyInteractWith(user, target))
+ return TRUE
+
if(do_tool_interaction(TOOL_PEN, user, target, 5 SECONDS, draw_message, "drawing on", fuel_expenditure = 1))
- new /obj/effect/decal/cleanable/crayon(target, stroke_color, shade_color, drawtype)
+ var/obj/effect/decal/cleanable/crayon/graffiti = new(target, stroke_color, shade_color, drawtype)
target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on.
- return
+ graffiti.add_fingerprint(user)
+
+ return TRUE
/obj/item/pen/crayon/red
stroke_color = "#da0000"
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 712c2d6c2b6..5d816b92448 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -268,6 +268,7 @@
/decl/interaction_handler/empty/photocopier_paper_bin
name = "Empty Paper Bin"
expected_target_type = /obj/machinery/photocopier
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/empty/photocopier_paper_bin/is_possible(obj/machinery/photocopier/target, mob/user, obj/item/prop)
return (target.printer?.get_amount_paper() > 0) && ..()
@@ -288,6 +289,7 @@
/decl/interaction_handler/remove/photocopier_scanner_item
name = "Remove Item From Scanner"
expected_target_type = /obj/machinery/photocopier
+ examine_desc = "remove a loaded item"
/decl/interaction_handler/remove/photocopier_scanner_item/is_possible(obj/machinery/photocopier/target, mob/user, obj/item/prop)
return target.scanner_item && ..()
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index 6e18e36decb..eb9bbb76a03 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -398,6 +398,7 @@
icon = 'icons/screen/radial.dmi'
icon_state = "radial_eject"
expected_target_type = /obj/item/camera
+ examine_desc = "eject the film"
/decl/interaction_handler/camera_eject_film/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/camera/camera = target
diff --git a/code/modules/paperwork/printer.dm b/code/modules/paperwork/printer.dm
index 7cfeaa96c43..0f91439ab58 100644
--- a/code/modules/paperwork/printer.dm
+++ b/code/modules/paperwork/printer.dm
@@ -423,6 +423,7 @@
/decl/interaction_handler/empty/stock_parts_printer
name = "Empty Paper Bin"
expected_target_type = /obj/item/stock_parts/printer
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/empty/stock_parts_printer/is_possible(obj/item/stock_parts/printer/target, mob/user, obj/item/prop)
return (target.get_amount_paper() > 0) && ..()
diff --git a/code/modules/persistence/persistence_datum.dm b/code/modules/persistence/persistence_datum.dm
index 557ae252b88..027081f7949 100644
--- a/code/modules/persistence/persistence_datum.dm
+++ b/code/modules/persistence/persistence_datum.dm
@@ -26,14 +26,16 @@
return TRUE
/decl/persistence_handler/proc/CheckTokenSanity(var/list/tokens)
- return ( \
- islist(tokens) && \
- !isnull(tokens["x"]) && \
- !isnull(tokens["y"]) && \
- !isnull(tokens["z"]) && \
- !isnull(tokens["age"]) && \
- tokens["age"] <= entries_expire_at \
- )
+ if(!islist(tokens))
+ return FALSE
+ if(isnull(tokens["x"]) || isnull(tokens["y"]) || isnull(tokens["z"]))
+ return FALSE
+ if(!isnull(entries_expire_at))
+ if(isnull(tokens["age"]))
+ return FALSE
+ if(tokens["age"] > entries_expire_at)
+ return FALSE
+ return TRUE
/decl/persistence_handler/proc/CreateEntryInstance(var/turf/creating, var/list/tokens)
return
@@ -59,8 +61,9 @@
else
return
- if(GetValidTurf(locate(tokens["x"], tokens["y"], tokens["z"]), tokens))
- return CreateEntryInstance(., tokens)
+ . = GetValidTurf(locate(tokens["x"], tokens["y"], tokens["z"]), tokens)
+ if(.)
+ . = CreateEntryInstance(., tokens)
/decl/persistence_handler/proc/IsValidEntry(var/atom/entry)
if(!istype(entry))
diff --git a/code/modules/persistence/persistence_datum_book.dm b/code/modules/persistence/persistence_datum_book.dm
index 479a9c8cb45..cf33c5df07d 100644
--- a/code/modules/persistence/persistence_datum_book.dm
+++ b/code/modules/persistence/persistence_datum_book.dm
@@ -5,7 +5,14 @@
ignore_invalid_loc = TRUE
/decl/persistence_handler/book/CreateEntryInstance(var/turf/creating, var/list/tokens)
- var/obj/item/book/book = new(creating)
+
+ var/book_type = tokens["book_type"]
+ if(book_type)
+ book_type = text2path(book_type)
+ if(!ispath(book_type))
+ book_type = /obj/item/book
+
+ var/obj/item/book/book = new book_type(creating)
book.dat = tokens["message"]
book.title = tokens["title"]
book.author = tokens["writer"]
@@ -29,11 +36,12 @@
. = ..()
var/obj/item/book/book = entry
- .["author"] = book.last_modified_ckey || ""
- .["message"] = book.dat || "dat"
- .["title"] = book.title || "Untitled"
- .["writer"] = book.author || "unknown"
+ .["author"] = book.last_modified_ckey || ""
+ .["message"] = book.dat || "dat"
+ .["title"] = book.title || "Untitled"
+ .["writer"] = book.author || "unknown"
.["icon_state"] = book.icon_state || "book"
+ .["book_type"] = "[book.type]"
var/turf/T = get_turf(entry)
if(!T || !isStationLevel(T.z))
@@ -62,7 +70,7 @@
else
T = get_random_spawn_turf(SPAWN_FLAG_PERSISTENCE_CAN_SPAWN)
- . = ..(T, tokens)
+ . = ..()
/decl/persistence_handler/book/GetEntryAge(var/atom/entry)
. = -1
diff --git a/code/modules/supermatter/setup_supermatter.dm b/code/modules/power/admin_setup_engine.dm
similarity index 52%
rename from code/modules/supermatter/setup_supermatter.dm
rename to code/modules/power/admin_setup_engine.dm
index 4af1f8aa34c..e5aae900584 100644
--- a/code/modules/supermatter/setup_supermatter.dm
+++ b/code/modules/power/admin_setup_engine.dm
@@ -1,101 +1,7 @@
-#define SETUP_OK 1 // All good
-#define SETUP_WARNING 2 // Something that shouldn't happen happened, but it's not critical so we will continue
-#define SETUP_ERROR 3 // Something bad happened, and it's important so we won't continue setup.
-#define SETUP_DELAYED 4 // Wait for other things first.
-
-#define ENERGY_NITROGEN 115 // Roughly 8 emitter shots.
-#define ENERGY_CARBONDIOXIDE 150 // Roughly 10 emitter shots.
-#define ENERGY_HYDROGEN 300 // Roughly 20 emitter shots.
-
-/datum/admins/proc/setup_supermatter()
- set category = "Debug"
- set name = "Setup Supermatter"
- set desc = "Allows you to start the Supermatter engine."
-
- if (!istype(src,/datum/admins))
- src = usr.client.holder
- if (!istype(src,/datum/admins))
- to_chat(usr, "Error: you are not an admin!")
- return
-
- var/response = input(usr, "Are you sure? This will start up the engine with selected gas as coolant.", "Engine setup") as null|anything in list("N2", "CO2", "H2", "Abort")
- if(!response || response == "Abort")
- return
-
- var/errors = 0
- var/warnings = 0
- var/success = 0
-
- log_and_message_admins("## SUPERMATTER SETUP - Setup initiated by [usr] using coolant type [response].")
-
- // CONFIGURATION PHASE
- // Coolant canisters, set types according to response.
- for(var/obj/effect/engine_setup/coolant_canister/C in global.engine_setup_markers)
- switch(response)
- if("N2")
- C.canister_type = /obj/machinery/portable_atmospherics/canister/nitrogen/engine_setup/
- continue
- if("CO2")
- C.canister_type = /obj/machinery/portable_atmospherics/canister/carbon_dioxide/engine_setup/
- continue
- if("H2")
- C.canister_type = /obj/machinery/portable_atmospherics/canister/hydrogen/engine_setup/
- continue
-
- for(var/obj/effect/engine_setup/core/C in global.engine_setup_markers)
- switch(response)
- if("N2")
- C.energy_setting = ENERGY_NITROGEN
- continue
- if("CO2")
- C.energy_setting = ENERGY_CARBONDIOXIDE
- continue
- if("H2")
- C.energy_setting = ENERGY_HYDROGEN
- continue
-
- for(var/obj/effect/engine_setup/filter/F in global.engine_setup_markers)
- F.coolant = response
-
- var/list/delayed_objects = list()
- // SETUP PHASE
- for(var/obj/effect/engine_setup/S in global.engine_setup_markers)
- var/result = S.activate(0)
- switch(result)
- if(SETUP_OK)
- success++
- continue
- if(SETUP_WARNING)
- warnings++
- continue
- if(SETUP_ERROR)
- errors++
- log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.")
- break
- if(SETUP_DELAYED)
- delayed_objects.Add(S)
- continue
-
- if(!errors)
- for(var/obj/effect/engine_setup/S in delayed_objects)
- var/result = S.activate(1)
- switch(result)
- if(SETUP_OK)
- success++
- continue
- if(SETUP_WARNING)
- warnings++
- continue
- if(SETUP_ERROR)
- errors++
- log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.")
- break
-
- log_and_message_admins("## SUPERMATTER SETUP - Setup completed with [errors] errors, [warnings] warnings and [success] successful steps.")
-
- return
-
-
+#define ENGINE_SETUP_OK 1 // All good
+#define ENGINE_SETUP_WARNING 2 // Something that shouldn't happen happened, but it's not critical so we will continue
+#define ENGINE_SETUP_ERROR 3 // Something bad happened, and it's important so we won't continue setup.
+#define ENGINE_SETUP_DELAYED 4 // Wait for other things first.
var/global/list/engine_setup_markers = list()
@@ -122,7 +28,7 @@ var/global/list/engine_setup_markers = list()
// Tries to locate a pump, enables it, and sets it to MAX. Triggers warning if unable to locate a pump.
-/obj/effect/engine_setup/pump_max/
+/obj/effect/engine_setup/pump_max
name = "Pump Setup Marker"
/obj/effect/engine_setup/pump_max/activate()
@@ -130,15 +36,15 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/atmospherics/binary/pump/P = locate() in get_turf(src)
if(!P)
log_and_message_admins("## WARNING: Unable to locate pump at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
P.target_pressure = P.max_pressure_setting
P.update_use_power(POWER_USE_IDLE)
- return SETUP_OK
+ return ENGINE_SETUP_OK
// Spawns an empty canister on this turf, if it has a connector port. Triggers warning if unable to find a connector port
-/obj/effect/engine_setup/empty_canister/
+/obj/effect/engine_setup/empty_canister
name = "Empty Canister Marker"
/obj/effect/engine_setup/empty_canister/activate()
@@ -146,16 +52,16 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/atmospherics/portables_connector/P = locate() in get_turf(src)
if(!P)
log_and_message_admins("## WARNING: Unable to locate connector port at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
new/obj/machinery/portable_atmospherics/canister(get_turf(src)) // Canisters automatically connect to connectors in New()
- return SETUP_OK
+ return ENGINE_SETUP_OK
// Spawns a coolant canister on this turf, if it has a connector port.
// Triggers error when unable to locate connector port or when coolant canister type is unset.
-/obj/effect/engine_setup/coolant_canister/
+/obj/effect/engine_setup/coolant_canister
name = "Coolant Canister Marker"
var/canister_type = null
@@ -164,33 +70,12 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/atmospherics/portables_connector/P = locate() in get_turf(src)
if(!P)
log_and_message_admins("## ERROR: Unable to locate coolant connector port at [x] [y] [z]!")
- return SETUP_ERROR
+ return ENGINE_SETUP_ERROR
if(!canister_type)
log_and_message_admins("## ERROR: Canister type unset at [x] [y] [z]!")
- return SETUP_ERROR
+ return ENGINE_SETUP_ERROR
new canister_type(get_turf(src))
- return SETUP_OK
-
-
-
-// Energises the supermatter. Errors when unable to locate supermatter.
-/obj/effect/engine_setup/core/
- name = "Supermatter Core Marker"
- var/energy_setting = 0
-
-/obj/effect/engine_setup/core/activate(var/last = 0)
- if(!last)
- return SETUP_DELAYED
- ..()
- var/obj/machinery/power/supermatter/SM = locate() in get_turf(src)
- if(!SM)
- log_and_message_admins("## ERROR: Unable to locate supermatter core at [x] [y] [z]!")
- return SETUP_ERROR
- if(!energy_setting)
- log_and_message_admins("## ERROR: Energy setting unset at [x] [y] [z]!")
- return SETUP_ERROR
- SM.power = energy_setting
- return SETUP_OK
+ return ENGINE_SETUP_OK
@@ -211,13 +96,13 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/power/smes/S = locate() in get_turf(src)
if(!S)
log_and_message_admins("## WARNING: Unable to locate SMES unit at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
S.input_attempt = 1
S.input_level = min(target_input_level, S.input_level_max)
S.output_attempt = 1
S.output_level = min(target_output_level, S.output_level_max)
S.update_icon()
- return SETUP_OK
+ return ENGINE_SETUP_OK
// Sets up filters. This assumes filters are set to filter out CO2 back to the core loop by default!
/obj/effect/engine_setup/filter
@@ -229,10 +114,10 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/atmospherics/omni/filter/F = locate() in get_turf(src)
if(!F)
log_and_message_admins("## WARNING: Unable to locate omni filter at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
if(!coolant)
log_and_message_admins("## WARNING: No coolant type set at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
// Non-co2 coolant, adjust the filter's config first.
if(coolant != "CO2")
@@ -247,11 +132,11 @@ var/global/list/engine_setup_markers = list()
break
else
log_and_message_admins("## WARNING: Inapropriate filter coolant type set at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
F.rebuild_filtering_list()
F.update_use_power(POWER_USE_IDLE)
- return SETUP_OK
+ return ENGINE_SETUP_OK
// Closes the monitoring room shutters so the first Engi to show up doesn't get microwaved
/obj/effect/engine_setup/shutters
@@ -262,7 +147,7 @@ var/global/list/engine_setup_markers = list()
/obj/effect/engine_setup/shutters/activate()
if(!target_button)
log_and_message_admins("## WARNING: No button type set at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
var/obj/machinery/button/blast_door/found = null
var/turf/T = get_turf(src)
for(var/obj/machinery/button/blast_door/B in T.contents)
@@ -271,15 +156,7 @@ var/global/list/engine_setup_markers = list()
break
if(!found)
log_and_message_admins("## WARNING: Unable to locate button at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
found.activate()
found.update_icon()
- return SETUP_OK
-
-#undef SETUP_OK
-#undef SETUP_WARNING
-#undef SETUP_ERROR
-#undef SETUP_DELAYED
-#undef ENERGY_NITROGEN
-#undef ENERGY_CARBONDIOXIDE
-#undef ENERGY_HYDROGEN
+ return ENGINE_SETUP_OK
\ No newline at end of file
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index dd74a49e3d3..78f587767ee 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -166,50 +166,47 @@ By design, d1 is the smallest direction and d2 is the highest
//
// TODO: take a closer look at cable attackby, make it call parent?
-/obj/structure/cable/attackby(obj/item/W, mob/user)
- if(IS_WIRECUTTER(W))
- cut_wire(W, user)
+/obj/structure/cable/attackby(obj/item/used_item, mob/user)
- else if(IS_COIL(W))
- var/obj/item/stack/cable_coil/coil = W
+ if(IS_WIRECUTTER(used_item))
+ cut_wire(used_item, user)
+ return TRUE
+
+ if(IS_COIL(used_item))
+ var/obj/item/stack/cable_coil/coil = used_item
if (coil.get_amount() < 1)
to_chat(user, "You don't have enough cable to lay down.")
return TRUE
coil.cable_join(src, user)
+ return TRUE
- else if(IS_MULTITOOL(W))
-
+ if(IS_MULTITOOL(used_item))
if(powernet && (powernet.avail > 0)) // is it powered?
to_chat(user, SPAN_WARNING("[get_wattage()] in power network."))
-
+ shock(user, 5, 0.2)
else
to_chat(user, SPAN_WARNING("\The [src] is not powered."))
+ return TRUE
- shock(user, 5, 0.2)
-
-
- else if(W.edge)
-
+ if(used_item.edge)
var/delay_holder
-
- if(W.get_attack_force(user) < 5)
- visible_message(SPAN_WARNING("[user] starts sawing away roughly at \the [src] with \the [W]."))
+ if(used_item.get_attack_force(user) < 5)
+ visible_message(SPAN_WARNING("[user] starts sawing away roughly at \the [src] with \the [used_item]."))
delay_holder = 8 SECONDS
else
- visible_message(SPAN_WARNING("[user] begins to cut through \the [src] with \the [W]."))
+ visible_message(SPAN_WARNING("[user] begins to cut through \the [src] with \the [used_item]."))
delay_holder = 3 SECONDS
-
if(user.do_skilled(delay_holder, SKILL_ELECTRICAL, src))
- cut_wire(W, user)
- if(W.obj_flags & OBJ_FLAG_CONDUCTIBLE)
+ cut_wire(used_item, user)
+ if(used_item.obj_flags & OBJ_FLAG_CONDUCTIBLE)
shock(user, 66, 0.7)
else
visible_message(SPAN_WARNING("[user] stops cutting before any damage is done."))
+ return TRUE
- src.add_fingerprint(user)
- return TRUE
+ return ..()
-/obj/structure/cable/proc/cut_wire(obj/item/W, mob/user)
+/obj/structure/cable/proc/cut_wire(obj/item/used_item, mob/user)
var/turf/T = get_turf(src)
if(!T || !T.is_plating())
return
@@ -241,13 +238,13 @@ By design, d1 is the smallest direction and d2 is the highest
// shock the user with probability prb
/obj/structure/cable/proc/shock(mob/user, prb, var/siemens_coeff = 1.0)
- if(!prob(prb))
- return 0
+ if(!prob(prb) || powernet?.avail <= 0)
+ return FALSE
if (electrocute_mob(user, powernet, src, siemens_coeff))
spark_at(src, amount=5, cardinal_only = TRUE)
if(HAS_STATUS(user, STAT_STUN))
- return 1
- return 0
+ return TRUE
+ return FALSE
// TODO: generalize to matter list and parts_type.
/obj/structure/cable/create_dismantled_products(turf/T)
diff --git a/code/modules/power/fuel_assembly/fuel_assembly.dm b/code/modules/power/fuel_assembly/fuel_assembly.dm
index 6958f2431d2..0527ee14941 100644
--- a/code/modules/power/fuel_assembly/fuel_assembly.dm
+++ b/code/modules/power/fuel_assembly/fuel_assembly.dm
@@ -87,7 +87,7 @@
/obj/item/fuel_assembly/tritium
material = /decl/material/gas/hydrogen/tritium
-/obj/item/fuel_assembly/supermatter
+/obj/item/fuel_assembly/exotic_matter
material = /decl/material/solid/exotic_matter
/obj/item/fuel_assembly/hydrogen
diff --git a/code/modules/power/fuel_assembly/fuel_compressor.dm b/code/modules/power/fuel_assembly/fuel_compressor.dm
index f6c08c8e565..0488d360f93 100644
--- a/code/modules/power/fuel_assembly/fuel_compressor.dm
+++ b/code/modules/power/fuel_assembly/fuel_compressor.dm
@@ -129,12 +129,6 @@
to_chat(user, SPAN_NOTICE("You add the contents of \the [thing] to \the [src]'s material buffer."))
return TRUE
- if(istype(thing, /obj/machinery/power/supermatter/shard))
- stored_material[/decl/material/solid/exotic_matter] = 5 * SHEET_MATERIAL_AMOUNT
- to_chat(user, SPAN_NOTICE("You awkwardly cram \the [thing] into \the [src]'s material buffer."))
- qdel(thing)
- return TRUE
-
if(istype(thing, /obj/item/stack/material))
var/obj/item/stack/material/M = thing
var/decl/material/mat = M.get_material()
diff --git a/code/modules/power/fusion/fusion_reactions.dm b/code/modules/power/fusion/fusion_reactions.dm
index 73cffcc1529..5ff951b477b 100644
--- a/code/modules/power/fusion/fusion_reactions.dm
+++ b/code/modules/power/fusion/fusion_reactions.dm
@@ -92,7 +92,7 @@
minimum_reaction_temperature = 10000
// VERY UNIDEAL REACTIONS.
-/decl/fusion_reaction/helium_supermatter
+/decl/fusion_reaction/helium_exotic_matter
p_react = /decl/material/solid/exotic_matter
s_react = /decl/material/gas/helium
energy_consumption = 0
@@ -101,7 +101,7 @@
instability = 20 * FUSION_PROCESSING_TIME_MULT
hidden_from_codex = TRUE
-/decl/fusion_reaction/helium_supermatter/handle_reaction_special(var/obj/effect/fusion_em_field/holder)
+/decl/fusion_reaction/helium_exotic_matter/handle_reaction_special(var/obj/effect/fusion_em_field/holder)
set waitfor = FALSE
. = 1
var/datum/event/wormholes/WM = new /datum/event/wormholes(new /datum/event_meta(EVENT_LEVEL_MAJOR))
@@ -112,8 +112,7 @@
qdel(holder)
var/radiation_level = rand(100, 200)
- // Copied from the SM for proof of concept. //Not any more --Cirra //Use the whole z proc --Leshana
- SSradiation.z_radiate(locate(1, 1, holder.z), radiation_level, 1)
+ SSradiation.z_radiate(origin, radiation_level, respect_maint = TRUE)
for(var/mob/living/human/H in global.living_mob_list_)
var/turf/T = get_turf(H)
@@ -121,10 +120,10 @@
H.set_hallucination(rand(100,150), 51)
for(var/obj/machinery/fusion_fuel_injector/I in range(world.view, origin))
- if(I.cur_assembly && I.cur_assembly.material && I.cur_assembly.material.type == /decl/material/solid/exotic_matter)
+ if(I.cur_assembly && I.cur_assembly.material && I.cur_assembly.material.type == p_react)
explosion(get_turf(I), 1, 2, 3)
if(!QDELETED(I))
- QDEL_IN(I, 5)
+ addtimer(CALLBACK(I, TYPE_PROC_REF(/atom, physically_destroyed)), 0.5 SECONDS)
sleep(5)
explosion(origin, 1, 2, 5)
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 6482521407e..c1c8ea8295e 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -13,7 +13,7 @@ var/global/list/singularities = list()
/// Category used for investigation entries relating to this atom.
var/const/investigation_label = "singulo"
- /// A list of events. Toxins is in here twice to double the chance of proccing.
+ /// A weighted list of events.
var/static/list/singularity_events = list(
/decl/singularity_event/empulse = 1,
/decl/singularity_event/toxins = 2,
@@ -63,7 +63,7 @@ var/global/list/singularities = list()
/obj/effect/singularity/explosion_act(severity)
SHOULD_CALL_PARENT(FALSE)
- if(current_stage.stage_size == STAGE_SUPER)//IT'S UNSTOPPABLE
+ if(!current_stage.explosion_vulnerable)//IT'S UNSTOPPABLE
return
if(severity == 1)
if(prob(25))
@@ -153,16 +153,13 @@ var/global/list/singularities = list()
// Handle random events.
if(prob(current_stage.event_chance))
- if(current_stage.stage_size >= STAGE_SUPER)
- var/decl/singularity_event/wave_event = GET_DECL(/decl/singularity_event/supermatter_wave)
- wave_event.handle_event(src)
- var/decl/singularity_event/singularity_event = pickweight(singularity_events)
+ var/decl/singularity_event/singularity_event = current_stage.forced_event || pickweight(singularity_events)
singularity_event = GET_DECL(singularity_event)
singularity_event.handle_event(src)
/obj/effect/singularity/proc/try_move(var/movement_dir, var/vertical_move)
set waitfor = FALSE
- if(current_stage.stage_size >= STAGE_FIVE)//The superlarge one does not care about things in its way
+ if(current_stage.ignore_obstacles)//The superlarge one does not care about things in its way
step(src, movement_dir)
if(!vertical_move)
sleep(1)
diff --git a/code/modules/power/singularity/singularity_events.dm b/code/modules/power/singularity/singularity_events.dm
index e48a040231b..f3bc342ac90 100644
--- a/code/modules/power/singularity/singularity_events.dm
+++ b/code/modules/power/singularity/singularity_events.dm
@@ -7,10 +7,7 @@
/decl/singularity_event/nothing // Nothing happens.
/decl/singularity_event/empulse/handle_event(obj/effect/singularity/source)
- if(source.current_stage.stage_size != STAGE_SUPER)
- empulse(source, 8, 10)
- else
- empulse(source, 12, 16)
+ empulse(source, source.current_stage.em_heavy_range, source.current_stage.em_light_range)
/decl/singularity_event/toxins
var/toxrange = 10
@@ -35,20 +32,10 @@
if(ishuman(M))
var/mob/living/human/H = M
if(istype(H.get_equipped_item(slot_glasses_str), /obj/item/clothing/glasses/meson))
- if(source.current_stage.stage_size != STAGE_SUPER)
+ if(!source.current_stage.the_goggles_do_nothing)
to_chat(H, SPAN_WARNING("You look directly into \the [source]. Good thing you had your protective eyewear on!"))
continue
to_chat(H, SPAN_WARNING("Your eyewear does absolutely nothing to protect you from \the [source]"))
- to_chat(M, SPAN_DANGER("You look directly into \the [source] and feel [source.current_stage.stage_size == STAGE_SUPER ? "helpless" : "weak"]."))
+ to_chat(M, SPAN_DANGER("You look directly into \the [source] and feel [source.current_stage.mesmerize_text]."))
M.apply_effect(3, STUN)
M.visible_message(SPAN_DANGER("\The [M] stares blankly at \the [source]!"))
-
-/decl/singularity_event/supermatter_wave/handle_event(obj/effect/singularity/source)
- for(var/mob/living/M in view(10, source.loc))
- to_chat(M, SPAN_WARNING("You hear an unearthly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat."))
- if(prob(67))
- to_chat(M, SPAN_NOTICE("Miraculously, it fails to kill you."))
- else
- to_chat(M, SPAN_DANGER("You don't even have a moment to react as you are reduced to ashes by the intense radiation."))
- M.dust()
- SSradiation.radiate(source, rand(source.energy))
diff --git a/code/modules/power/singularity/singularity_stages.dm b/code/modules/power/singularity/singularity_stages.dm
index 831cacd48c5..2624c10e818 100644
--- a/code/modules/power/singularity/singularity_stages.dm
+++ b/code/modules/power/singularity/singularity_stages.dm
@@ -32,8 +32,22 @@
var/dissipation_energy_loss = 1
/// What is the percent chance of an event each tick?
var/event_chance
+ /// Do we force a specific event when we proc events?
+ var/decl/singularity_event/forced_event = null
/// Will we wander around?
var/wander
+ /// Can explosions destroy the singularity?
+ var/explosion_vulnerable
+ /// What is the heavy range for the EM pulse event in this stage?
+ var/em_heavy_range = 8
+ /// What is the light range for the EM pulse event in this stage?
+ var/em_light_range = 10
+ /// What do characters feel when they're mesmerized during this stage?
+ var/mesmerize_text = "weak"
+ /// Do we ignore PPE for mesmerizing in this stage?
+ var/the_goggles_do_nothing = FALSE
+ /// Do we ignore obstacles in our way?
+ var/ignore_obstacles = FALSE
/decl/singularity_stage/validate()
. = ..()
@@ -171,29 +185,7 @@
dissipates_over_time = FALSE //It cant go smaller due to e loss.
wander = TRUE
event_chance = 20
+ ignore_obstacles = TRUE
/decl/singularity_stage/stage_five/grow_to(obj/effect/singularity/source)
source.visible_message(SPAN_DANGER("\The [source] has grown out of control!"))
-
-/decl/singularity_stage/stage_five/shrink_to(obj/effect/singularity/source)
- source.visible_message(SPAN_WARNING("\The [source] miraculously reduces in size and loses its supermatter properties."))
-
-/decl/singularity_stage/stage_super
- name = "super gravitational singularity"
- desc = "A gravitational singularity with the properties of supermatter. It has the power to destroy worlds."
- min_energy = 50000
- max_energy = INFINITY
- stage_size = STAGE_SUPER
- footprint = 6
- icon = 'icons/effects/352x352.dmi'
- icon_state = "singularity_s11"//uh, whoever drew that, you know that black holes are supposed to look dark right? What's this, the clown's singulo?
- pixel_x = -160
- pixel_y = -160
- grav_pull = 16
- consume_range = 5
- dissipates_over_time = 0 //It cant go smaller due to e loss
- event_chance = 25 //Events will fire off more often.
- wander = TRUE
-
-/decl/singularity_stage/stage_super/grow_to(obj/effect/singularity/source)
- source.visible_message(SPAN_SINISTER("You witness the creation of a destructive force that cannot possibly be stopped by human hands."))
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 4de22aa0616..d01aa247e4b 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -744,6 +744,9 @@
return FALSE
return TRUE
+/obj/item/gun/get_quick_interaction_handler(mob/user)
+ return GET_DECL(/decl/interaction_handler/gun/toggle_safety)
+
/obj/item/gun/get_alt_interactions(mob/user)
. = ..()
LAZYADD(., /decl/interaction_handler/gun/toggle_safety)
@@ -756,6 +759,7 @@
/decl/interaction_handler/gun/toggle_safety
name = "Toggle Safety"
+ examine_desc = "toggle the safety"
/decl/interaction_handler/gun/toggle_safety/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/gun = target
@@ -763,6 +767,7 @@
/decl/interaction_handler/gun/toggle_firemode
name = "Change Firemode"
+ examine_desc = "change the firemode"
/decl/interaction_handler/gun/toggle_firemode/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/gun = target
diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm
index 8534b7ddc7a..d4da8ee5045 100644
--- a/code/modules/projectiles/guns/projectile.dm
+++ b/code/modules/projectiles/guns/projectile.dm
@@ -360,6 +360,7 @@
/decl/interaction_handler/projectile/remove_silencer
name = "Remove Silencer"
+ examine_desc = "remove the silencer"
/decl/interaction_handler/projectile/remove_silencer/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/projectile/gun = target
@@ -367,6 +368,7 @@
/decl/interaction_handler/projectile/unload_ammo
name = "Remove Ammunition"
+ examine_desc = "unload the ammunition"
/decl/interaction_handler/projectile/unload_ammo/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/projectile/gun = target
diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm
index 0f54520856d..464ce437f7c 100644
--- a/code/modules/projectiles/guns/projectile/revolver.dm
+++ b/code/modules/projectiles/guns/projectile/revolver.dm
@@ -74,6 +74,7 @@
/decl/interaction_handler/revolver_spin_cylinder
name = "Spin Cylinder"
expected_target_type = /obj/item/gun/projectile/revolver
+ examine_desc = "spin the cylinder"
/decl/interaction_handler/revolver_spin_cylinder/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/projectile/revolver/R = target
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 07ad3c6c686..152cb7a6ab5 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -14,6 +14,18 @@
is_spawnable_type = FALSE
atom_damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, ELECTROCUTE are the only things that should be in here, Try not to use PAIN as it doesn't go through stun_effect_act
+ // Code for handling tails, if any.
+ /// If the projectile leaves a trail.
+ var/proj_trail = FALSE
+ /// How long the trail lasts.
+ var/proj_trail_lifespan = 0
+ /// What icon to use for the projectile trail.
+ var/proj_trail_icon = 'icons/effects/projectiles/trail.dmi'
+ /// What icon_state to use for the projectile trail.
+ var/proj_trail_icon_state = "trail"
+ /// Any extant trail effects.
+ var/list/proj_trails
+
var/bumped = 0 //Prevents it from hitting more than one guy at once
var/def_zone = "" //Aiming at
var/atom/movable/firer = null//Who shot it
@@ -316,7 +328,15 @@
return
/obj/item/projectile/proc/before_move()
- return
+ if(!proj_trail || !isturf(loc) || !proj_trail_icon || !proj_trail_icon_state || !proj_trail_lifespan)
+ return
+ var/obj/effect/overlay/projectile_trail/trail = new(loc)
+ trail.master = src
+ trail.icon = proj_trail_icon
+ trail.icon_state = proj_trail_icon_state
+ trail.set_density(FALSE)
+ LAZYADD(proj_trails, trail)
+ QDEL_IN(trail, proj_trail_lifespan)
/obj/item/projectile/proc/after_move()
if(hitscan && tracer_type && !(locate(/obj/effect/projectile) in loc))
@@ -609,6 +629,7 @@
trajectory.initialize_location(target.x, target.y, target.z, 0, 0)
/obj/item/projectile/Destroy()
+ QDEL_NULL_LIST(proj_trails)
if(hitscan)
if(loc && trajectory)
var/datum/point/pcache = trajectory.copy_to()
@@ -650,4 +671,4 @@
QDEL_NULL(beam_index)
/obj/item/projectile/proc/update_effect(var/obj/effect/projectile/effect)
- return
\ No newline at end of file
+ return
diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm
index 8e241456d22..ff77df0fa33 100644
--- a/code/modules/projectiles/projectile/change.dm
+++ b/code/modules/projectiles/projectile/change.dm
@@ -55,12 +55,9 @@
var/mob/living/new_mob = apply_transformation(M, choice)
if(new_mob)
new_mob.set_intent(I_FLAG_HARM)
- if(M.mind)
- for (var/spell/S in M.mind.learned_spells)
- new_mob.add_spell(new S.type)
- new_mob.set_intent(I_FLAG_HARM)
- transfer_key_from_mob_to_mob(M, new_mob)
- to_chat(new_mob, "Your form morphs into that of \a [choice].")
+ new_mob.copy_abilities_from(M)
+ transfer_key_from_mob_to_mob(M, new_mob)
+ to_chat(new_mob, "Your form morphs into that of \a [choice].")
else
new_mob = M
if(new_mob)
@@ -68,4 +65,3 @@
if(new_mob != M && !QDELETED(M))
qdel(M)
-
diff --git a/code/modules/projectiles/targeting/targeting_overlay.dm b/code/modules/projectiles/targeting/targeting_overlay.dm
index 5d5b1f9ba65..7210efedb4c 100644
--- a/code/modules/projectiles/targeting/targeting_overlay.dm
+++ b/code/modules/projectiles/targeting/targeting_overlay.dm
@@ -34,27 +34,24 @@
// Update HUD icons.
if(owner.gun_move_icon)
if(!(target_permissions & TARGET_CAN_MOVE))
- owner.gun_move_icon.icon_state = "no_walk0"
owner.gun_move_icon.SetName("Allow Movement")
else
- owner.gun_move_icon.icon_state = "no_walk1"
owner.gun_move_icon.SetName("Disallow Movement")
+ owner.gun_move_icon.update_icon()
if(owner.item_use_icon)
if(!(target_permissions & TARGET_CAN_CLICK))
- owner.item_use_icon.icon_state = "no_item0"
owner.item_use_icon.SetName("Allow Item Use")
else
- owner.item_use_icon.icon_state = "no_item1"
owner.item_use_icon.SetName("Disallow Item Use")
+ owner.item_use_icon.update_icon()
if(owner.radio_use_icon)
if(!(target_permissions & TARGET_CAN_RADIO))
- owner.radio_use_icon.icon_state = "no_radio0"
owner.radio_use_icon.SetName("Allow Radio Use")
else
- owner.radio_use_icon.icon_state = "no_radio1"
owner.radio_use_icon.SetName("Disallow Radio Use")
+ owner.radio_use_icon.update_icon()
var/message = "no longer permitted to "
var/use_span = "warning"
@@ -206,7 +203,7 @@
if(!no_message)
to_chat(owner, "You will no longer aim rather than fire.")
owner.client.remove_gun_icons()
- owner.gun_setting_icon.icon_state = "gun[active]"
+ owner.gun_setting_icon.update_icon()
/obj/aiming_overlay/proc/cancel_aiming(var/no_message = 0)
if(!aiming_with || !aiming_at)
diff --git a/code/modules/random_map/drop/drop_types.dm b/code/modules/random_map/drop/drop_types.dm
index a9f290a0aa6..1560263f996 100644
--- a/code/modules/random_map/drop/drop_types.dm
+++ b/code/modules/random_map/drop/drop_types.dm
@@ -22,12 +22,6 @@ var/global/list/datum/supply_drop_loot/supply_drop
/datum/supply_drop_loot/dd_SortValue()
return name
-/datum/supply_drop_loot/supermatter
- name = "Supermatter"
-/datum/supply_drop_loot/supermatter/New()
- ..()
- contents = list(/obj/machinery/power/supermatter)
-
/datum/supply_drop_loot/lasers
name = "Lasers"
container = /obj/structure/largecrate
diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm
index 67aee6ead08..cac32152287 100644
--- a/code/modules/reagents/Chemistry-Holder.dm
+++ b/code/modules/reagents/Chemistry-Holder.dm
@@ -797,37 +797,55 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new
// Options are touch_turf(), touch_mob() and touch_obj(). This does not handle transferring reagents to things.
// For example, splashing someone with water will get them wet and extinguish them if they are on fire,
// even if they are wearing an impermeable suit that prevents the reagents from contacting the skin.
-/datum/reagents/proc/touch_mob(var/mob/target)
+
+/datum/reagents/proc/touch_atom(atom/target, touch_atoms = TRUE)
+ if(ismob(target))
+ return touch_mob(target)
+ if(isobj(target))
+ return touch_obj(target)
+ if(isturf(target))
+ return touch_turf(target, touch_atoms)
+ return FALSE
+
+/datum/reagents/proc/touch_mob(mob/target)
if(!target || !istype(target) || !target.simulated)
return
for(var/rtype in reagent_volumes)
var/decl/material/current = GET_DECL(rtype)
current.touch_mob(target, REAGENT_VOLUME(src, rtype), src)
-/datum/reagents/proc/touch_turf(var/turf/target)
- if(!istype(target) || !target.simulated)
+/datum/reagents/proc/touch_turf(turf/touching_turf, touch_atoms = TRUE)
+
+ if(!istype(touching_turf) || !touching_turf.simulated)
return
+
for(var/rtype in reagent_volumes)
var/decl/material/current = GET_DECL(rtype)
- current.touch_turf(target, REAGENT_VOLUME(src, rtype), src)
+ current.touch_turf(touching_turf, REAGENT_VOLUME(src, rtype), src)
+
var/dirtiness = get_dirtiness()
if(dirtiness <= DIRTINESS_CLEAN)
- target.clean()
- target.remove_cleanables()
- if(dirtiness != DIRTINESS_NEUTRAL)
- if(dirtiness > DIRTINESS_NEUTRAL)
- target.add_dirt(ceil(total_volume * dirtiness))
- else
- if(dirtiness <= DIRTINESS_STERILE)
- target.germ_level -= min(total_volume*20, target.germ_level)
- for(var/obj/item/I in target.contents)
- I.was_bloodied = null
- for(var/obj/effect/decal/cleanable/blood/B in target)
- qdel(B)
- if(dirtiness <= DIRTINESS_CLEAN)
- target.clean()
-
-/datum/reagents/proc/touch_obj(var/obj/target)
+ touching_turf.clean()
+ touching_turf.remove_cleanables()
+
+ if(dirtiness > DIRTINESS_NEUTRAL)
+ touching_turf.add_dirt(ceil(total_volume * dirtiness))
+ else if(dirtiness < DIRTINESS_NEUTRAL)
+ if(dirtiness <= DIRTINESS_STERILE)
+ touching_turf.germ_level -= min(total_volume*20, touching_turf.germ_level)
+ for(var/obj/item/I in touching_turf.contents)
+ I.was_bloodied = null
+ for(var/obj/effect/decal/cleanable/blood/B in touching_turf)
+ qdel(B)
+ if(dirtiness <= DIRTINESS_CLEAN)
+ touching_turf.clean()
+
+ if(touch_atoms)
+ for(var/atom/movable/thing in touching_turf.get_contained_external_atoms())
+ if(thing.simulated && !istype(thing, /obj/effect/effect/smoke/chem))
+ touch_atom(thing)
+
+/datum/reagents/proc/touch_obj(obj/target)
if(!target || !istype(target) || !target.simulated)
return
for(var/rtype in reagent_volumes)
diff --git a/code/modules/reagents/Chemistry-Metabolism.dm b/code/modules/reagents/Chemistry-Metabolism.dm
index e1002809b1f..9c78f190ca2 100644
--- a/code/modules/reagents/Chemistry-Metabolism.dm
+++ b/code/modules/reagents/Chemistry-Metabolism.dm
@@ -20,7 +20,7 @@
parent = null
return ..()
-/datum/reagents/metabolism/proc/metabolize(var/list/dosage_tracker)
+/datum/reagents/metabolism/proc/metabolize(list/dosage_tracker)
if(!parent || total_volume < MINIMUM_CHEMICAL_VOLUME || !length(reagent_volumes))
return
for(var/rtype in reagent_volumes)
diff --git a/code/modules/reagents/chems/chems_alcohol.dm b/code/modules/reagents/chems/chems_alcohol.dm
index aa7ca92f847..44384d64365 100644
--- a/code/modules/reagents/chems/chems_alcohol.dm
+++ b/code/modules/reagents/chems/chems_alcohol.dm
@@ -226,8 +226,8 @@
if(M.bodytemperature > 310)
M.bodytemperature = max(310, M.bodytemperature - (5 * TEMPERATURE_DAMAGE_COEFFICIENT))
-/decl/material/liquid/alcohol/coffee/affect_overdose(mob/living/M, total_dose)
- ADJ_STATUS(M, STAT_JITTER, 5)
+/decl/material/liquid/alcohol/coffee/affect_overdose(mob/living/victim, total_dose)
+ ADJ_STATUS(victim, STAT_JITTER, 5)
/decl/material/liquid/alcohol/melonliquor
name = "melon liqueur"
diff --git a/code/modules/reagents/chems/chems_blood.dm b/code/modules/reagents/chems/chems_blood.dm
index e3a08e5b873..1e4696e3ffe 100644
--- a/code/modules/reagents/chems/chems_blood.dm
+++ b/code/modules/reagents/chems/chems_blood.dm
@@ -46,12 +46,12 @@
for(var/chem in other_chems)
my_chems[chem] = my_chems[chem] + other_chems[chem]
-/decl/material/liquid/blood/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
+/decl/material/liquid/blood/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
var/data = REAGENT_DATA(holder, type)
- if(!istype(T) || REAGENT_VOLUME(holder, type) < 3)
+ if(!istype(touching_turf) || REAGENT_VOLUME(holder, type) < 3)
return
- var/weakref/W = LAZYACCESS(data, DATA_BLOOD_DONOR)
- blood_splatter(T, W?.resolve() || holder.my_atom, 1)
+ var/weakref/donor = LAZYACCESS(data, DATA_BLOOD_DONOR)
+ blood_splatter(touching_turf, donor?.resolve() || holder.my_atom, 1)
/decl/material/liquid/blood/affect_ingest(var/mob/living/M, var/removed, var/datum/reagents/holder)
. = ..()
diff --git a/code/modules/reagents/chems/chems_compounds.dm b/code/modules/reagents/chems/chems_compounds.dm
index 42a44ac8fa1..468300ba172 100644
--- a/code/modules/reagents/chems/chems_compounds.dm
+++ b/code/modules/reagents/chems/chems_compounds.dm
@@ -35,11 +35,11 @@
addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living/human, update_eyes)), 5 SECONDS)
. = ..()
-/decl/material/liquid/glowsap/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/glowsap/affect_overdose(mob/living/victim, total_dose)
. = ..()
- M.add_chemical_effect(CE_TOXIN, 1)
- M.set_hallucination(60, 20)
- SET_STATUS_MAX(M, STAT_DRUGGY, 10)
+ victim.add_chemical_effect(CE_TOXIN, 1)
+ victim.set_hallucination(60, 20)
+ SET_STATUS_MAX(victim, STAT_DRUGGY, 10)
/decl/material/solid/blackpepper
name = "black pepper"
diff --git a/code/modules/reagents/chems/chems_drinks.dm b/code/modules/reagents/chems/chems_drinks.dm
index af54d84cd62..eca5276b785 100644
--- a/code/modules/reagents/chems/chems_drinks.dm
+++ b/code/modules/reagents/chems/chems_drinks.dm
@@ -379,9 +379,9 @@
..()
M.add_chemical_effect(CE_PULSE, 2)
-/decl/material/liquid/drink/coffee/affect_overdose(mob/living/M, total_dose)
- ADJ_STATUS(M, STAT_JITTER, 5)
- M.add_chemical_effect(CE_PULSE, 1)
+/decl/material/liquid/drink/coffee/affect_overdose(mob/living/victim, total_dose)
+ ADJ_STATUS(victim, STAT_JITTER, 5)
+ victim.add_chemical_effect(CE_PULSE, 1)
/decl/material/liquid/drink/coffee/build_presentation_name_from_reagents(var/obj/item/prop, var/supplied)
diff --git a/code/modules/reagents/chems/chems_drugs.dm b/code/modules/reagents/chems/chems_drugs.dm
index 9d36a9a5ae3..e9345200297 100644
--- a/code/modules/reagents/chems/chems_drugs.dm
+++ b/code/modules/reagents/chems/chems_drugs.dm
@@ -61,9 +61,9 @@
LAZYSET(holder.reagent_data, type, world.time)
to_chat(M, "You feel invigorated and calm.")
-/decl/material/liquid/nicotine/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/nicotine/affect_overdose(mob/living/victim, total_dose)
..()
- M.add_chemical_effect(CE_PULSE, 2)
+ victim.add_chemical_effect(CE_PULSE, 2)
/decl/material/liquid/sedatives
name = "sedatives"
@@ -253,10 +253,9 @@
if(istype(M))
M.remove_client_color(/datum/client_color/noir/thirdeye)
-/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/M, total_dose)
- M.take_damage(rand(1, 5), BRAIN)
- if(ishuman(M) && prob(10))
- var/mob/living/human/H = M
- H.seizure()
+/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/victim, total_dose)
+ victim.take_damage(rand(1, 5), BRAIN)
+ if(prob(10))
+ victim.seizure()
if(prob(10))
- to_chat(M, SPAN_DANGER("[pick(overdose_messages)]"))
+ to_chat(victim, SPAN_DANGER("[pick(overdose_messages)]"))
diff --git a/code/modules/reagents/chems/chems_medicines.dm b/code/modules/reagents/chems/chems_medicines.dm
index 701d2f1d476..7b8357a1767 100644
--- a/code/modules/reagents/chems/chems_medicines.dm
+++ b/code/modules/reagents/chems/chems_medicines.dm
@@ -52,14 +52,12 @@
uid = "chem_styptic"
var/effectiveness = 1
-/decl/material/liquid/brute_meds/affect_overdose(mob/living/M, var/datum/reagents/holder)
+/decl/material/liquid/brute_meds/affect_overdose(mob/living/victim, total_dose)
..()
- if(ishuman(M))
- M.add_chemical_effect(CE_BLOCKAGE, (15 + REAGENT_VOLUME(holder, type))/100)
- var/mob/living/human/H = M
- for(var/obj/item/organ/external/E in H.get_external_organs())
- if(E.status & ORGAN_ARTERY_CUT && prob(2 + REAGENT_VOLUME(holder, type) / overdose))
- E.status &= ~ORGAN_ARTERY_CUT
+ victim.add_chemical_effect(CE_BLOCKAGE, (15 + total_dose) / 100)
+ for(var/obj/item/organ/external/limb in victim.get_external_organs())
+ if((limb.status & ORGAN_ARTERY_CUT) && prob(2 + total_dose / overdose))
+ limb.status &= ~ORGAN_ARTERY_CUT
//This is a logistic function that effectively doubles the healing rate as brute amounts get to around 200. Any injury below 60 is essentially unaffected and there's a scaling inbetween.
#define ADJUSTED_REGEN_VAL(X) (6+(6/(1+200*2.71828**(-0.05*(X)))))
@@ -169,12 +167,10 @@
if(immunity_to_add > 0)
M.adjust_immunity(immunity_to_add) // Rapidly brings someone up to half immunity.
-/decl/material/liquid/immunobooster/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/immunobooster/affect_overdose(mob/living/victim, total_dose)
..()
- M.add_chemical_effect(CE_TOXIN, 1)
- var/mob/living/human/H = M
- if(istype(H))
- M.adjust_immunity(-0.5)
+ victim.add_chemical_effect(CE_TOXIN, 1)
+ victim.adjust_immunity(-0.5)
/decl/material/liquid/stimulants
name = "stimulants"
@@ -240,12 +236,12 @@
exoplanet_rarity_gas = MAT_RARITY_EXOTIC
uid = "chem_antibiotics"
-/decl/material/liquid/antibiotics/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/antibiotics/affect_overdose(mob/living/victim, total_dose)
..()
- M.adjust_immunity(-0.5)
- M.immunity = max(M.immunity - 0.25, 0)
+ victim.adjust_immunity(-0.5)
+ victim.immunity = max(victim.immunity - 0.25, 0)
if(prob(2))
- M.immunity_norm = max(M.immunity_norm - 1, 0)
+ victim.immunity_norm = max(victim.immunity_norm - 1, 0)
/decl/material/liquid/retrovirals
name = "retrovirals"
@@ -258,14 +254,12 @@
exoplanet_rarity_gas = MAT_RARITY_EXOTIC
uid = "chem_retrovirals"
-/decl/material/liquid/retrovirals/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/retrovirals/affect_overdose(mob/living/victim, total_dose)
. = ..()
- if(ishuman(M))
- var/mob/living/human/H = M
- for(var/obj/item/organ/external/E in H.get_external_organs())
- if(!BP_IS_PROSTHETIC(E) && prob(25) && !(E.status & ORGAN_MUTATED))
- E.mutate()
- E.limb_flags |= ORGAN_FLAG_DEFORMED
+ for(var/obj/item/organ/external/limb in victim.get_external_organs())
+ if(!BP_IS_PROSTHETIC(limb) && prob(25) && !(limb.status & ORGAN_MUTATED))
+ limb.mutate()
+ limb.limb_flags |= ORGAN_FLAG_DEFORMED
/decl/material/liquid/retrovirals/affect_blood(var/mob/living/M, var/removed, var/datum/reagents/holder)
. = ..()
@@ -404,8 +398,8 @@
break
..()
-/decl/material/liquid/clotting_agent/affect_overdose(mob/living/M, total_dose)
- var/obj/item/organ/internal/heart = GET_INTERNAL_ORGAN(M, BP_HEART)
+/decl/material/liquid/clotting_agent/affect_overdose(mob/living/victim, total_dose)
+ var/obj/item/organ/internal/heart = GET_INTERNAL_ORGAN(victim, BP_HEART)
if(heart && prob(25))
heart.take_general_damage(rand(1,3))
return ..()
diff --git a/code/modules/reagents/chems/chems_nutriment.dm b/code/modules/reagents/chems/chems_nutriment.dm
index d96d2b840d7..cc0774431ca 100644
--- a/code/modules/reagents/chems/chems_nutriment.dm
+++ b/code/modules/reagents/chems/chems_nutriment.dm
@@ -83,9 +83,9 @@
uid = "chem_nutriment_flour"
allergen_flags = ALLERGEN_GLUTEN
-/decl/material/liquid/nutriment/flour/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
+/decl/material/liquid/nutriment/flour/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
..()
- new /obj/effect/decal/cleanable/flour(T)
+ new /obj/effect/decal/cleanable/flour(touching_turf)
/decl/material/liquid/nutriment/batter
name = "batter"
@@ -102,9 +102,9 @@
boiling_point = 373
allergen_flags = ALLERGEN_EGG | ALLERGEN_GLUTEN
-/decl/material/liquid/nutriment/batter/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
+/decl/material/liquid/nutriment/batter/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
..()
- new /obj/effect/decal/cleanable/pie_smudge(T)
+ new /obj/effect/decal/cleanable/pie_smudge(touching_turf)
/decl/material/liquid/nutriment/batter/cakebatter
name = "cake batter"
diff --git a/code/modules/reagents/chems/chems_painkillers.dm b/code/modules/reagents/chems/chems_painkillers.dm
index 6647c2afed2..8ab62f4048f 100644
--- a/code/modules/reagents/chems/chems_painkillers.dm
+++ b/code/modules/reagents/chems/chems_painkillers.dm
@@ -112,17 +112,17 @@
M.add_chemical_effect(CE_ALCOHOL_TOXIC, 1)
M.add_chemical_effect(CE_BREATHLOSS, 1 * boozed) //drinking and opiating suppresses breathing.
-/decl/material/liquid/painkillers/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/painkillers/affect_overdose(mob/living/victim, total_dose)
..()
- M.add_chemical_effect(CE_PAINKILLER, pain_power*0.5) //extra painkilling for extra trouble
+ victim.add_chemical_effect(CE_PAINKILLER, pain_power*0.5) //extra painkilling for extra trouble
if(narcotic)
- SET_STATUS_MAX(M, STAT_DRUGGY, 10)
- M.set_hallucination(120, 30)
- M.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*2) //ODing on opiates can be deadly.
- if(isboozed(M))
- M.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*4) //Don't drink and OD on opiates folks
+ SET_STATUS_MAX(victim, STAT_DRUGGY, 10)
+ victim.set_hallucination(120, 30)
+ victim.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*2) //ODing on opiates can be deadly.
+ if(isboozed(victim))
+ victim.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*4) //Don't drink and OD on opiates folks
else
- M.add_chemical_effect(CE_TOXIN, 1)
+ victim.add_chemical_effect(CE_TOXIN, 1)
/decl/material/liquid/painkillers/proc/isboozed(var/mob/living/M)
. = 0
diff --git a/code/modules/reagents/chems/chems_pigments.dm b/code/modules/reagents/chems/chems_pigments.dm
index c5fc4192862..55c6be4c47c 100644
--- a/code/modules/reagents/chems/chems_pigments.dm
+++ b/code/modules/reagents/chems/chems_pigments.dm
@@ -85,9 +85,9 @@
painting.reset_color()
painting.set_alpha(keep_alpha)
-/decl/material/liquid/paint_stripper/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
- if(istype(T) && !isspaceturf(T))
- remove_paint(T, holder)
+/decl/material/liquid/paint_stripper/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
+ if(istype(touching_turf) && !isspaceturf(touching_turf))
+ remove_paint(touching_turf, holder)
/decl/material/liquid/paint_stripper/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder)
if(istype(O))
@@ -113,9 +113,9 @@
painting.set_color(holder.get_color())
painting.set_alpha(keep_alpha)
-/decl/material/liquid/paint/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
- if(istype(T) && !isspaceturf(T))
- apply_paint(T, holder, FLUID_MINIMUM_TRANSFER)
+/decl/material/liquid/paint/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
+ if(istype(touching_turf) && !isspaceturf(touching_turf))
+ apply_paint(touching_turf, holder, FLUID_MINIMUM_TRANSFER)
/decl/material/liquid/paint/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder)
if(istype(O))
diff --git a/code/modules/reagents/heat_sources/_heat_source.dm b/code/modules/reagents/heat_sources/_heat_source.dm
index b9295313707..eb5b3cebf44 100644
--- a/code/modules/reagents/heat_sources/_heat_source.dm
+++ b/code/modules/reagents/heat_sources/_heat_source.dm
@@ -5,8 +5,8 @@
#define HEATER_MODE_COOL "cool"
/obj/machinery/reagent_temperature
- name = "chemical heater"
- desc = "A small electric Bunsen, used to heat beakers and vials of chemicals."
+ name = "hotplate"
+ desc = "A small electric hotplate, used to heat cookware, beakers, or vials of chemicals."
icon = 'icons/obj/machines/heat_sources.dmi'
icon_state = "hotplate"
atom_flags = ATOM_FLAG_CLIMBABLE
@@ -70,6 +70,7 @@
/obj/machinery/reagent_temperature/ProcessAtomTemperature()
if(use_power >= POWER_USE_ACTIVE)
+
var/last_temperature = temperature
if(heater_mode == HEATER_MODE_HEAT && temperature < target_temperature)
temperature = min(target_temperature, temperature + heating_power)
@@ -79,10 +80,25 @@
if(container)
queue_temperature_atoms(container)
queue_icon_update()
+
+ // Hackery to heat pots placed onto a hotplate without also grilling/baking stuff.
+ if(isturf(loc))
+ var/datum/gas_mixture/environment = loc.return_air()
+ for(var/obj/item/chems/cooking_vessel/pot in loc.get_contained_external_atoms())
+ pot.fire_act(environment, temperature, 500)
+
return TRUE // Don't kill this processing loop unless we're not powered.
. = ..()
/obj/machinery/reagent_temperature/attackby(var/obj/item/thing, var/mob/user)
+
+ if(istype(thing, /obj/item/chems/cooking_vessel))
+ if(!user.try_unequip(thing, get_turf(src)))
+ return TRUE
+ thing.reset_offsets(anim_time = 0)
+ user.visible_message(SPAN_NOTICE("\The [user] places \the [thing] onto \the [src]."))
+ return TRUE
+
if(IS_WRENCH(thing))
if(use_power == POWER_USE_ACTIVE)
to_chat(user, SPAN_WARNING("Turn \the [src] off first!"))
diff --git a/code/modules/reagents/reactions/_reaction.dm b/code/modules/reagents/reactions/_reaction.dm
index e743ecf0ab2..fbc2eaa85d6 100644
--- a/code/modules/reagents/reactions/_reaction.dm
+++ b/code/modules/reagents/reactions/_reaction.dm
@@ -38,7 +38,7 @@
return 1
-/decl/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(thermal_product && location && ATOM_SHOULD_TEMPERATURE_ENQUEUE(location))
ADJUST_ATOM_TEMPERATURE(location, location.temperature + (location.get_thermal_mass_coefficient() * thermal_product))
@@ -61,8 +61,6 @@
if(reaction_volume > A)
reaction_volume = A
- var/alt_reaction_indicator = get_alternate_reaction_indicator(holder)
-
for(var/reactant in required_reagents)
holder.remove_reagent(reactant, reaction_volume * required_reagents[reactant], safety = 1)
@@ -71,7 +69,7 @@
if(result)
holder.add_reagent(result, amt_produced, data, safety = 1)
- on_reaction(holder, amt_produced, alt_reaction_indicator, data)
+ on_reaction(holder, amt_produced, data)
//called after processing reactions, if they occurred
/decl/chemical_reaction/proc/post_reaction(var/datum/reagents/holder)
diff --git a/code/modules/reagents/reactions/reaction_compounds.dm b/code/modules/reagents/reactions/reaction_compounds.dm
index 8e530dacaa5..a334f65b6ff 100644
--- a/code/modules/reagents/reactions/reaction_compounds.dm
+++ b/code/modules/reagents/reactions/reaction_compounds.dm
@@ -155,10 +155,20 @@
required_reagents = list(/decl/material/liquid/capsaicin = 2)
result = list(/decl/material/liquid/capsaicin/condensed = 1)
-/decl/chemical_reaction/compound/condensed_capsaicin/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/compound/condensed_capsaicin/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
. = ..()
holder?.add_reagent(/decl/material/liquid/water, created_volume)
+/decl/chemical_reaction/compound/nanitefluid
+ name = "Nanite Fluid Synthesis"
+ result = /decl/material/liquid/nanitefluid
+ required_reagents = list(/decl/material/liquid/plasticide = 1, /decl/material/solid/metal/aluminium = 1, /decl/material/liquid/lube = 1)
+ catalysts = list(/decl/material/liquid/crystal_agent = 1)
+ result_amount = 3
+ minimum_temperature = (-25 CELSIUS) - 100
+ maximum_temperature = -25 CELSIUS
+ mix_message = "The solution becomes a metallic slime."
+
// This is a bit silly, but we need a way to unify oil types until someone rewrites lanterns.
/decl/chemical_reaction/compound/fuel_oil
name = "Plant Fuel Oil"
diff --git a/code/modules/reagents/reactions/reaction_drugs.dm b/code/modules/reagents/reactions/reaction_drugs.dm
index 8f10b625a3c..a4f85cb3fa7 100644
--- a/code/modules/reagents/reactions/reaction_drugs.dm
+++ b/code/modules/reagents/reactions/reaction_drugs.dm
@@ -111,16 +111,6 @@
required_reagents = list(/decl/material/liquid/antirads = 1, /decl/material/solid/carbon = 1)
result_amount = 2
-/decl/chemical_reaction/compound/nanitefluid
- name = "Nanite Fluid"
- result = /decl/material/liquid/nanitefluid
- required_reagents = list(/decl/material/liquid/plasticide = 1, /decl/material/solid/metal/aluminium = 1, /decl/material/liquid/lube = 1)
- catalysts = list(/decl/material/liquid/crystal_agent = 1)
- result_amount = 3
- minimum_temperature = (-25 CELSIUS) - 100
- maximum_temperature = -25 CELSIUS
- mix_message = "The solution becomes a metallic slime."
-
/decl/chemical_reaction/drug/antibiotics
name = "Antibiotics"
result = /decl/material/liquid/antibiotics
diff --git a/code/modules/reagents/reactions/reaction_grenade_reaction.dm b/code/modules/reagents/reactions/reaction_grenade_reaction.dm
index ec529bef717..7827c6ac054 100644
--- a/code/modules/reagents/reactions/reaction_grenade_reaction.dm
+++ b/code/modules/reagents/reactions/reaction_grenade_reaction.dm
@@ -11,7 +11,7 @@
required_reagents = list(/decl/material/liquid/water = 1, /decl/material/solid/potassium = 1)
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/explosion_potassium/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/explosion_potassium/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
@@ -32,7 +32,7 @@
result_amount = null
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/flash_powder/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/flash_powder/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -58,7 +58,7 @@
mix_message = "The solution bubbles vigorously!"
maximum_temperature = T100C
-/decl/chemical_reaction/grenade_reaction/emp_pulse/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/emp_pulse/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
@@ -79,7 +79,7 @@
reaction_sound = 'sound/items/Welder.ogg'
mix_message = "The solution suddenly ignites!"
-/decl/chemical_reaction/grenade_reaction/flash_fire/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/flash_fire/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(istype(location))
@@ -93,7 +93,7 @@
result_amount = 0.4
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/chemsmoke/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/chemsmoke/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -112,7 +112,7 @@
result_amount = 2
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/foam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/foam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -129,7 +129,7 @@
result_amount = 5
mix_message = "The solution foams up violently!"
-/decl/chemical_reaction/grenade_reaction/metalfoam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/metalfoam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
@@ -151,7 +151,7 @@
result_amount = 5
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/ironfoam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/ironfoam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
diff --git a/code/modules/reagents/reactions/reaction_herbal.dm b/code/modules/reagents/reactions/reaction_herbal.dm
index b8a02ca07fe..62950dd1d64 100644
--- a/code/modules/reagents/reactions/reaction_herbal.dm
+++ b/code/modules/reagents/reactions/reaction_herbal.dm
@@ -3,7 +3,7 @@
result_amount = 2
minimum_temperature = 100 CELSIUS
-/decl/chemical_reaction/drug/herbal/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/drug/herbal/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
. = ..()
// Add plant matter to represent the herbs that the medicine has been leached out of.
holder?.add_reagent(/decl/material/solid/organic/plantmatter, created_volume)
diff --git a/code/modules/reagents/reactions/reaction_other.dm b/code/modules/reagents/reactions/reaction_other.dm
index 19c5613ea7e..dca52f041f6 100644
--- a/code/modules/reagents/reactions/reaction_other.dm
+++ b/code/modules/reagents/reactions/reaction_other.dm
@@ -10,7 +10,7 @@
return ..()
return 0
-/decl/chemical_reaction/soap_key/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/soap_key/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
var/obj/item/soap/S = holder.get_reaction_loc(chemical_reaction_flags)
if(istype(S) && S.key_data)
new /obj/item/key/temporary(get_turf(S), /decl/material/liquid/cleaner, S.key_data, strength)
diff --git a/code/modules/reagents/reactions/reaction_recipe_food.dm b/code/modules/reagents/reactions/reaction_recipe_food.dm
index bc052960e91..0ece0daefd2 100644
--- a/code/modules/reagents/reactions/reaction_recipe_food.dm
+++ b/code/modules/reagents/reactions/reaction_recipe_food.dm
@@ -4,7 +4,7 @@
abstract_type = /decl/chemical_reaction/recipe/food
var/obj_result
-/decl/chemical_reaction/recipe/food/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/recipe/food/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(obj_result && isturf(location))
diff --git a/code/modules/reagents/reactions/reaction_synthesis.dm b/code/modules/reagents/reactions/reaction_synthesis.dm
index 57192c726ae..79695861328 100644
--- a/code/modules/reagents/reactions/reaction_synthesis.dm
+++ b/code/modules/reagents/reactions/reaction_synthesis.dm
@@ -19,7 +19,7 @@
)
. = ..()
-/decl/chemical_reaction/synthesis/fiberglass/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/fiberglass/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -44,7 +44,7 @@
if(rtype != /decl/material/liquid/crystal_agent && REAGENT_VOLUME(holder, rtype) >= REAGENT_UNITS_PER_MATERIAL_SHEET)
return TRUE
-/decl/chemical_reaction/synthesis/crystalization/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/crystalization/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
var/list/removing_reagents = list()
@@ -78,7 +78,7 @@
continue
return TRUE
-/decl/chemical_reaction/synthesis/aerogel/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/aerogel/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
var/list/removing_reagents = list()
@@ -97,7 +97,7 @@
required_reagents = list(/decl/material/liquid/acid = 1, /decl/material/liquid/plasticide = 2)
mix_message = "The solution solidifies into a grey-white mass."
-/decl/chemical_reaction/synthesis/plastication/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/plastication/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -112,7 +112,7 @@
result_amount = 3
mix_message = "The solution hardens and begins to crystallize."
-/decl/chemical_reaction/synthesis/resin_pack/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/resin_pack/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(!istype(T))
@@ -133,7 +133,7 @@
mix_message = "The solution thickens and solidifies."
minimum_temperature = 100 CELSIUS
-/decl/chemical_reaction/synthesis/soap/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/soap/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(!istype(T))
@@ -164,7 +164,7 @@
minimum_temperature = 100 CELSIUS
var/chipboard_type = /decl/material/solid/organic/wood/chipboard
-/decl/chemical_reaction/synthesis/chipboard/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/chipboard/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(!istype(T))
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 99ec47811aa..db904892033 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -27,6 +27,8 @@
/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))
var/image/contents_overlay = get_reagents_overlay(use_single_icon ? icon_state : null)
if(contents_overlay)
add_overlay(contents_overlay)
@@ -204,6 +206,7 @@
/decl/interaction_handler/set_transfer/chems
expected_target_type = /obj/item/chems
+ examine_desc = "set the transfer volume"
/decl/interaction_handler/set_transfer/chems/is_possible(var/atom/target, var/mob/user)
. = ..()
@@ -220,6 +223,7 @@
name = "Empty On Floor"
expected_target_type = /obj/item/chems
interaction_flags = INTERACTION_NEEDS_INVENTORY | INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC
+ examine_desc = "empty $TARGET_THEM$ onto the floor"
/decl/interaction_handler/empty/chems/invoked(atom/target, mob/user, obj/item/prop)
var/turf/T = get_turf(user)
diff --git a/code/modules/reagents/reagent_containers/_glass.dm b/code/modules/reagents/reagent_containers/_glass.dm
index 50c6024ac0b..aee39d39921 100644
--- a/code/modules/reagents/reagent_containers/_glass.dm
+++ b/code/modules/reagents/reagent_containers/_glass.dm
@@ -114,12 +114,6 @@
. = ..()
// Drinking out of bowls.
-/obj/item/chems/glass/get_food_default_transfer_amount(mob/eater)
- return eater?.get_eaten_transfer_amount(amount_per_transfer_from_this)
-
-/obj/item/chems/glass/get_food_consumption_method(mob/eater)
- return EATING_METHOD_DRINK
-
/obj/item/chems/glass/get_edible_material_amount(mob/eater)
return reagents?.total_volume
@@ -155,3 +149,28 @@
LAZYADD(., /decl/interaction_handler/fill_from)
if(user?.get_active_held_item())
LAZYADD(., /decl/interaction_handler/empty_into)
+ if(can_lid())
+ LAZYADD(., /decl/interaction_handler/toggle_lid)
+
+/decl/interaction_handler/toggle_lid
+ name = "Toggle Lid"
+ expected_target_type = /obj/item/chems/glass
+
+/decl/interaction_handler/toggle_lid/is_possible(atom/target, mob/user, obj/item/prop)
+ . = ..()
+ if(. && !istype(prop))
+ var/obj/item/chems/glass/glass = target
+ return glass.can_lid()
+
+/decl/interaction_handler/toggle_lid/invoked(atom/target, mob/user, obj/item/prop)
+ var/obj/item/chems/glass/glass = target
+ if(istype(glass) && glass.can_lid())
+ if(ATOM_IS_OPEN_CONTAINER(glass))
+ to_chat(user, SPAN_NOTICE("You put the lid on \the [glass]."))
+ glass.atom_flags ^= ATOM_FLAG_OPEN_CONTAINER
+ else
+ to_chat(user, SPAN_NOTICE("You take the lid off \the [glass]."))
+ glass.atom_flags |= ATOM_FLAG_OPEN_CONTAINER
+ glass.update_icon()
+ return TRUE
+
diff --git a/code/modules/reagents/reagent_containers/beaker.dm b/code/modules/reagents/reagent_containers/beaker.dm
index 3b1ad5be042..ab42e686e93 100644
--- a/code/modules/reagents/reagent_containers/beaker.dm
+++ b/code/modules/reagents/reagent_containers/beaker.dm
@@ -178,5 +178,5 @@
matter = list(/decl/material/solid/organic/plastic = MATTER_AMOUNT_REINFORCEMENT)
volume = 120
-/obj/item/chems/glass/beaker/sulphuric/populate_reagents()
+/obj/item/chems/glass/beaker/sulfuric/populate_reagents()
add_to_reagents(/decl/material/liquid/acid, reagents.maximum_volume)
diff --git a/code/modules/reagents/reagent_containers/drinks.dm b/code/modules/reagents/reagent_containers/drinks.dm
index 46c56514eee..695412409f8 100644
--- a/code/modules/reagents/reagent_containers/drinks.dm
+++ b/code/modules/reagents/reagent_containers/drinks.dm
@@ -57,7 +57,7 @@
return
return ..()
-/obj/item/chems/drinks/standard_dispenser_refill(var/mob/user, var/obj/structure/reagent_dispensers/target, skip_container_check = FALSE)
+/obj/item/chems/drinks/standard_dispenser_refill(mob/user, obj/structure/reagent_dispensers/target, skip_container_check = FALSE)
return do_open_check(user) && ..()
/obj/item/chems/drinks/standard_pour_into(var/mob/user, var/atom/target)
diff --git a/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm b/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm
index a048bb7eac3..6c6cf548fe6 100644
--- a/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm
+++ b/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm
@@ -304,6 +304,7 @@
/decl/interaction_handler/open_pizza_box
expected_target_type = /obj/item/pizzabox
+ examine_desc = "open or close $TARGET_THEM$"
/decl/interaction_handler/open_pizza_box/is_possible(atom/target, mob/user, obj/item/prop)
. = ..()
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 9cd81a4c437..c3b4cbd9ff8 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -36,9 +36,6 @@
if(A?.storage || istype(A, /obj/structure/table) || istype(A, /obj/structure/closet) || istype(A, /obj/item/chems) || istype(A, /obj/structure/hygiene/sink) || istype(A, /obj/structure/janitorialcart))
return
- if(istype(A, /spell))
- return
-
if(proximity)
if(standard_dispenser_refill(user, A))
return
@@ -50,7 +47,7 @@
Spray_at(A, user, proximity)
if(reagents.has_reagent(/decl/material/liquid/acid))
- log_and_message_admins("fired sulphuric acid from \a [src].", user)
+ log_and_message_admins("fired sulfuric acid from \a [src].", user)
if(reagents.has_reagent(/decl/material/liquid/acid/polyacid))
log_and_message_admins("fired polyacid from \a [src].", user)
if(reagents.has_reagent(/decl/material/liquid/lube))
@@ -119,6 +116,7 @@
name = "Next Nozzle Setting"
expected_target_type = /obj/item/chems/spray
interaction_flags = INTERACTION_NEEDS_INVENTORY | INTERACTION_NEEDS_PHYSICAL_INTERACTION
+ examine_desc = "select the next nozzle spray amount"
/decl/interaction_handler/next_spray_amount/is_possible(obj/item/chems/spray/target, mob/user, obj/item/prop)
. = ..()
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index d8d5d4e5e06..778ed37be45 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -10,6 +10,7 @@
matter = list(/decl/material/solid/metal/steel = MATTER_AMOUNT_SECONDARY)
max_health = 100
tool_interaction_flags = TOOL_INTERACTION_DECONSTRUCT
+
var/wrenchable = TRUE
var/unwrenched = FALSE
var/tmp/volume = 1000
@@ -102,6 +103,7 @@
log_and_message_admins("opened a tank at [get_area_name(loc)].")
leak()
return TRUE
+
. = ..()
/obj/structure/reagent_dispensers/verb/set_amount_dispensed()
@@ -317,11 +319,12 @@
add_to_reagents(/decl/material/liquid/alcohol/beer, reagents.maximum_volume)
/obj/structure/reagent_dispensers/acid
- name = "sulphuric acid dispenser"
+ name = "sulfuric acid dispenser"
desc = "A dispenser of acid for industrial processes."
icon_state = "acidtank"
amount_dispensed = 10
anchored = TRUE
+ density = FALSE
/obj/structure/reagent_dispensers/acid/populate_reagents()
add_to_reagents(/decl/material/liquid/acid, reagents.maximum_volume)
@@ -351,6 +354,7 @@
/decl/interaction_handler/toggle_open/reagent_dispenser
name = "Toggle refilling cap"
expected_target_type = /obj/structure/reagent_dispensers
+ examine_desc = "open or close the refilling cap"
/decl/interaction_handler/toggle_open/reagent_dispenser/invoked(atom/target, mob/user, obj/item/prop)
if(target.atom_flags & ATOM_FLAG_OPEN_CONTAINER)
diff --git a/code/modules/sealant_gun/sealant_injector.dm b/code/modules/sealant_gun/sealant_injector.dm
index a3e89a44343..99f8553586d 100644
--- a/code/modules/sealant_gun/sealant_injector.dm
+++ b/code/modules/sealant_gun/sealant_injector.dm
@@ -103,6 +103,7 @@
/decl/interaction_handler/sealant_try_inject
name = "Inject Sealant"
expected_target_type = /obj/structure/sealant_injector
+ examine_desc = "inject sealant from a held item"
/decl/interaction_handler/sealant_try_inject/invoked(atom/target, mob/user, obj/item/prop)
var/obj/structure/sealant_injector/SI = target
diff --git a/code/modules/shuttles/landmarks.dm b/code/modules/shuttles/landmarks.dm
index 82cde0c759b..661bab8cf89 100644
--- a/code/modules/shuttles/landmarks.dm
+++ b/code/modules/shuttles/landmarks.dm
@@ -135,7 +135,7 @@ var/global/list/shuttle_landmarks = list()
/obj/effect/shuttle_landmark/automatic/sector_set(var/obj/effect/overmap/visitable/O)
..()
- SetName("[initial(name)] ([x],[y])")
+ SetName("[initial(name)] ([x],[y],[z])")
//Subtype that calls explosion on init to clear space for shuttles
/obj/effect/shuttle_landmark/automatic/clearing
diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm
index 5c615ad31b3..32980d3c189 100644
--- a/code/modules/species/species.dm
+++ b/code/modules/species/species.dm
@@ -57,9 +57,6 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200
var/flesh_color = "#ffc896" // Pink.
var/blood_oxy = 1
- // Preview in prefs positioning. If null, uses defaults set on a static list in preferences.dm.
- var/list/character_preview_screen_locs
-
var/organs_icon //species specific internal organs icons
var/strength = STR_MEDIUM
diff --git a/code/modules/spells/aoe_turf/aoe_turf.dm b/code/modules/spells/aoe_turf/aoe_turf.dm
deleted file mode 100644
index 0f7a721de80..00000000000
--- a/code/modules/spells/aoe_turf/aoe_turf.dm
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-Aoe turf spells target a ring of tiles around the user
-This ring has an outer radius (range) and an inner radius (inner_radius)
-Aoe turf spells have a useful flag: IGNOREDENSE. It is explained in setup.dm
-*/
-
-/spell/aoe_turf //affects all turfs in view or range (depends)
- spell_flags = IGNOREDENSE
- var/inner_radius = -1 //for all your ring spell needs
-
-/spell/aoe_turf/choose_targets(mob/user = usr)
- var/list/targets = list()
-
- for(var/turf/target in view_or_range(range, holder, selection_type))
- if(!(target in view_or_range(inner_radius, holder, selection_type)))
- if(target.density && (spell_flags & IGNOREDENSE))
- continue
- targets += target
-
- if(!targets.len) //doesn't waste the spell
- return
-
- return targets
\ No newline at end of file
diff --git a/code/modules/spells/aoe_turf/conjure/conjure.dm b/code/modules/spells/aoe_turf/conjure/conjure.dm
deleted file mode 100644
index 8dd91146310..00000000000
--- a/code/modules/spells/aoe_turf/conjure/conjure.dm
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Conjure spells spawn things (mobs, objs, turfs) in their summon_type
-How they spawn stuff is decided by behaviour vars, which are explained below
-*/
-
-/spell/aoe_turf/conjure
- name = "Conjure"
- desc = "This spell conjures objs of the specified types in range."
-
- school = "conjuration" //funny, that
-
- var/list/summon_type = list() //determines what exactly will be summoned
- //should NOT be text, like list(/obj/machinery/bot/ed209)
-
- range = 0 //default values: only spawn on the player tile
- selection_type = "view"
-
- duration = 0 // 0=permanent, any other time in deciseconds - how long the summoned objects last for
- var/summon_amt = 1 //amount of objects summoned
- var/summon_exclusive = 0 //spawn one of everything, instead of random things
-
- var/list/newVars = list() //vars of the summoned objects will be replaced with those where they meet
- //should have format of list("emagged" = 1,"name" = "Justicebot"), for example
-
- cast_sound = 'sound/magic/castsummon.ogg'
-
-/spell/aoe_turf/conjure/cast(list/targets, mob/user)
-
- for(var/i=1,i <= summon_amt,i++)
- if(!targets.len)
- break
- var/summoned_object_type
- if(summon_exclusive)
- if(!summon_type.len)
- break
- summoned_object_type = summon_type[1]
- summon_type -= summoned_object_type
- else
- summoned_object_type = pick(summon_type)
- var/turf/spawn_place = pick(targets)
- var/atom/summoned_object
- if(ispath(summoned_object_type,/turf))
- spawn_place.ChangeTurf(summoned_object_type)
- summoned_object = spawn_place
- else
- summoned_object = new summoned_object_type(spawn_place)
- var/atom/movable/overlay/animation = new /atom/movable/overlay(summoned_object)
- animation.SetName("conjure")
- animation.set_density(0)
- animation.anchored = TRUE
- animation.icon = 'icons/effects/effects.dmi'
- animation.layer = BASE_HUMAN_LAYER
- if(ismob(summoned_object)) //we want them to NOT attack us.
- var/mob/M = summoned_object
- M.faction = user.faction
- apply_vars(summoned_object, user)
-
- if(duration)
- spawn(duration)
- if(summoned_object && !isturf(summoned_object))
- qdel(summoned_object)
- conjure_animation(animation, spawn_place)
- return
-
-/spell/aoe_turf/conjure/proc/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
- qdel(animation)
-
-/spell/aoe_turf/conjure/proc/apply_vars(atom/summoned_object, mob/caster)
- if(!istype(summoned_object) || !length(newVars))
- return
- for(var/varName in newVars)
- if(varName in summoned_object.vars)
- summoned_object.vars[varName] = newVars[varName]
diff --git a/code/modules/spells/construct_spells.dm b/code/modules/spells/construct_spells.dm
deleted file mode 100644
index 0c705aff4fc..00000000000
--- a/code/modules/spells/construct_spells.dm
+++ /dev/null
@@ -1,10 +0,0 @@
-//////////////////////////////Construct Spells/////////////////////////
-
-/proc/findNullRod(var/atom/target)
- if(istype(target,/obj/item/nullrod))
- return 1
- else if(target.contents)
- for(var/atom/A in target.contents)
- if(findNullRod(A))
- return 1
- return 0
diff --git a/code/modules/spells/spell_code.dm b/code/modules/spells/spell_code.dm
deleted file mode 100644
index bfcf1f4d8f6..00000000000
--- a/code/modules/spells/spell_code.dm
+++ /dev/null
@@ -1,385 +0,0 @@
-var/global/list/spells = typesof(/spell) //needed for the badmin verb for now
-
-/spell
- var/name
- var/desc
- var/feedback = "" //what gets sent if this spell gets chosen by the spellbook.
- parent_type = /datum
- var/panel = "Spells"//What panel the proc holder needs to go on.
-
- var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
- /*Spell schools as follows:
- Racial - Only tagged to spells gained for being a certain race
- Conjuration - Creating an object or transporting it.
- Transmutation - Modifying an object or transforming it.
- Illusion - Altering perception or thought.
- */
- var/charge_type = Sp_RECHARGE //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that
-
- var/charge_max = 100 //recharge time in deciseconds if charge_type = Sp_RECHARGE or starting charges if charge_type = Sp_CHARGES
- var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = Sp_RECHARGE or -- each cast if charge_type = Sp_CHARGES
- var/still_recharging_msg = "The spell is still recharging."
-
- var/silenced = 0 //not a binary - the length of time we can't cast this for
- var/processing = 0 //are we processing already? Mainly used so that silencing a spell doesn't call process() again. (and inadvertedly making it run twice as fast)
-
- var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var"
- var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used
-
- var/spell_flags = 0
- var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
- var/invocation_type = SpI_NONE //can be none, whisper, shout, and emote
- var/range = 7 //the range of the spell; outer radius for aoe spells
- var/message = "" //whatever it says to the guy affected by it
- var/selection_type = "view" //can be "range" or "view"
- var/atom/movable/holder //where the spell is. Normally the user, can be an item
- var/duration = 0 //how long the spell lasts
-
- var/list/spell_levels = list(Sp_SPEED = 0, Sp_POWER = 0) //the current spell levels - total spell levels can be obtained by just adding the two values
- var/list/level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 0) //maximum possible levels in each category. Total does cover both.
- var/cooldown_reduc = 0 //If set, defines how much charge_max drops by every speed upgrade
- var/delay_reduc = 0
- var/cooldown_min = 0 //minimum possible cooldown for a charging spell
-
- var/overlay = 0
- var/overlay_icon = 'icons/obj/wizard.dmi'
- var/overlay_icon_state = "spell"
- var/overlay_lifespan = 0
-
- var/sparks_spread = 0
- var/sparks_amt = 0 //cropped at 10
- var/smoke_spread = 0 //1 - harmless, 2 - harmful
- var/smoke_amt = 0 //cropped at 10
-
- var/critfailchance = 0
- var/time_between_channels = 0 //Delay between casts
- var/number_of_channels = 1 //How many times can we channel?
-
- var/cast_delay = 1
- var/cast_sound = ""
-
- var/hud_state = "" //name of the icon used in generating the spell hud object
- var/override_base = ""
-
-
- var/obj/screen/connected_button
-
- var/hidden_from_codex = FALSE
-
-///////////////////////
-///SETUP AND PROCESS///
-///////////////////////
-
-/spell/New()
- ..()
-
- //still_recharging_msg = "[name] is still recharging."
- charge_counter = charge_max
-
-/spell/proc/process()
- if(processing)
- return
- processing = 1
- spawn(0)
- while(charge_counter < charge_max || silenced > 0)
- charge_counter = min(charge_max,charge_counter+1)
- silenced = max(0,silenced-1)
- sleep(1)
- if(connected_button)
- var/obj/screen/ability/spell/S = connected_button
- if(!istype(S))
- return
- S.update_charge(1)
- processing = 0
- return
-
-/////////////////
-/////CASTING/////
-/////////////////
-
-/spell/proc/choose_targets(mob/user = usr) //depends on subtype - see targeted.dm, aoe_turf.dm, dumbfire.dm, or code in general folder
- return
-
-/spell/proc/perform(mob/user = usr, skipcharge = 0) //if recharge is started is important for the trigger spells
- if(!holder)
- holder = user //just in case
- if(!cast_check(skipcharge, user))
- return
- to_chat(user, SPAN_NOTICE("You start casting \the [name]..."))
- if(cast_delay && !spell_do_after(user, cast_delay))
- return
- var/list/targets = choose_targets(user)
- if(!check_valid_targets(targets))
- to_chat(user, SPAN_WARNING("\The [name] fizzles. There are no valid targets nearby."))
- return
- var/time = 0
- admin_attacker_log(user, "attempted to cast the spell [name]")
- do
- time++
- if(!check_valid_targets(targets)) //make sure we HAVE something
- break
- if(cast_check(1,user, targets)) //we check again, otherwise you can choose a target and then wait for when you are no longer able to cast (I.E. Incapacitated) to use it.
- invocation(user, targets)
- take_charge(user, skipcharge)
- before_cast(targets) //applies any overlays and effects
- if(prob(critfailchance))
- critfail(targets, user)
- else
- cast(targets, user, time)
- after_cast(targets) //generates the sparks, smoke, target messages etc.
- else
- break
- while(time != number_of_channels && do_after(user, time_between_channels, incapacitation_flags = INCAPACITATION_KNOCKOUT|INCAPACITATION_FORCELYING|INCAPACITATION_STUNNED, same_direction=1))
- after_spell(targets, user, time) //When we are done with the spell completely.
-
-
-
-/spell/proc/cast(list/targets, mob/user, var/channel_duration) //the actual meat of the spell
- return
-
-/spell/proc/critfail(list/targets, mob/user) //the wizman has fucked up somehow
- return
-
-/spell/proc/after_spell(var/list/targets, var/mob/user, var/channel_duration) //After everything else is done.
- return
-
-/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types
- switch(type)
- if("bruteloss")
- target.take_damage(amount)
- if("fireloss")
- target.take_damage(amount, BURN)
- if("toxloss")
- target.take_damage(amount, TOX)
- if("oxyloss")
- target.take_damage(amount, OXY)
- if("brainloss")
- target.take_damage(amount, BRAIN)
- if("stunned")
- ADJ_STATUS(target, STAT_STUN, amount)
- if("weakened")
- ADJ_STATUS(target, STAT_WEAK, amount)
- if("paralysis")
- ADJ_STATUS(target, STAT_PARA, amount)
- else
- target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars
- return
-
-///////////////////////////
-/////CASTING WRAPPERS//////
-///////////////////////////
-
-/spell/proc/before_cast(list/targets)
- for(var/atom/target in targets)
- if(overlay)
- var/location
- if(isliving(target))
- location = target.loc
- else if(isturf(target))
- location = target
- var/obj/effect/overlay/spell = new /obj/effect/overlay(location)
- spell.icon = overlay_icon
- spell.icon_state = overlay_icon_state
- spell.anchored = TRUE
- spell.set_density(0)
- spawn(overlay_lifespan)
- qdel(spell)
-
-/spell/proc/after_cast(list/targets)
- if(cast_sound)
- playsound(get_turf(holder),cast_sound,50,1)
- for(var/atom/target in targets)
- var/location = get_turf(target)
- if(isliving(target) && message)
- to_chat(target, text("[message]"))
- if(sparks_spread)
- spark_at(location, amount = sparks_amt)
- if(smoke_spread)
- if(smoke_spread == 1)
- var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
- smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
- smoke.start()
- else if(smoke_spread == 2)
- var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad()
- smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
- smoke.start()
-
-/////////////////////
-////CASTING TOOLS////
-/////////////////////
-/*Checkers, cost takers, message makers, etc*/
-
-/spell/proc/cast_check(skipcharge = 0,mob/user = usr, var/list/targets) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
-
- if(silenced > 0)
- return 0
-
- if(!(src in user.mind.learned_spells) && holder == user && !(isanimal(user)))
- error("[user] utilized the spell '[src]' without having it.")
- to_chat(user, "You shouldn't have this spell! Something's wrong.")
- return 0
-
- var/turf/user_turf = get_turf(user)
- if(!user_turf)
- to_chat(user, "You cannot cast spells in null space!")
-
- if((spell_flags & Z2NOCAST) && isAdminLevel(user_turf.z)) //Certain spells are not allowed on the centcomm zlevel
- return 0
-
- if(spell_flags & CONSTRUCT_CHECK)
- for(var/turf/T in range(holder, 1))
- if(findNullRod(T))
- return 0
-
- if(!src.check_charge(skipcharge, user)) //sees if we can cast based on charges alone
- return 0
-
- if(holder == user)
- if(isanimal(user))
- var/mob/living/simple_animal/SA = user
- if(SA.purge)
- to_chat(SA, "The null sceptre's power interferes with your own!")
- return 0
-
- var/mob/living/L = user
- if(L.incapacitated(INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT))
- to_chat(user, "You can't cast spells while incapacitated!")
- return 0
-
- if(ishuman(user) && !(invocation_type in list(SpI_EMOTE, SpI_NONE)) && user.get_item_blocking_speech())
- to_chat(user, "Mmmf mrrfff!")
- return 0
-
- return 1
-
-/spell/proc/check_charge(var/skipcharge, mob/user)
- if(!skipcharge)
- switch(charge_type)
- if(Sp_RECHARGE)
- if(charge_counter < charge_max)
- to_chat(user, still_recharging_msg)
- return 0
- if(Sp_CHARGES)
- if(!charge_counter)
- to_chat(user, "[name] has no charges left.")
- return 0
- return 1
-
-/spell/proc/take_charge(mob/user = user, var/skipcharge)
- if(!skipcharge)
- switch(charge_type)
- if(Sp_RECHARGE)
- charge_counter = 0 //doesn't start recharging until the targets selecting ends
- src.process()
- return 1
- if(Sp_CHARGES)
- charge_counter-- //returns the charge if the targets selecting fails
- return 1
- if(Sp_HOLDVAR)
- adjust_var(user, holder_var_type, holder_var_amount)
- return 1
- return 0
- return 1
-
-/spell/proc/check_valid_targets(var/list/targets)
- if(!targets)
- return 0
- if(!islist(targets))
- targets = list(targets)
- else if(!targets.len)
- return 0
-
- var/list/valid_targets = view_or_range(range, holder, selection_type)
- for(var/target in targets)
- if(!(target in valid_targets))
- return 0
- return 1
-
-/spell/proc/invocation(mob/user = usr, var/list/targets) //spelling the spell out and setting it on recharge/reducing charges amount
-
- switch(invocation_type)
- if(SpI_SHOUT)
- if(prob(50))//Auto-mute? Fuck that noise
- user.say(invocation)
- else
- user.say(replacetext(invocation," ","`"))
- if(SpI_WHISPER)
- if(prob(50))
- user.whisper(invocation)
- else
- user.whisper(replacetext(invocation," ","`"))
- if(SpI_EMOTE)
- user.custom_emote(VISIBLE_MESSAGE, invocation)
-
-/////////////////////
-///UPGRADING PROCS///
-/////////////////////
-
-/spell/proc/can_improve(var/upgrade_type)
- if(level_max[Sp_TOTAL] <= ( spell_levels[Sp_SPEED] + spell_levels[Sp_POWER] )) //too many levels, can't do it
- return 0
-
- //if(upgrade_type && spell_levels[upgrade_type] && level_max[upgrade_type])
- if(upgrade_type && spell_levels[upgrade_type] >= level_max[upgrade_type])
- return 0
-
- return 1
-
-/spell/proc/empower_spell()
- if(!can_improve(Sp_POWER))
- return 0
-
- spell_levels[Sp_POWER]++
-
- return 1
-
-/spell/proc/quicken_spell()
- if(!can_improve(Sp_SPEED))
- return 0
-
- spell_levels[Sp_SPEED]++
-
- if(delay_reduc && cast_delay)
- cast_delay = max(0, cast_delay - delay_reduc)
- else if(cast_delay)
- cast_delay = round( max(0, initial(cast_delay) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) )
-
- if(charge_type == Sp_RECHARGE)
- if(cooldown_reduc)
- charge_max = max(cooldown_min, charge_max - cooldown_reduc)
- else
- charge_max = round( max(cooldown_min, initial(charge_max) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) //the fraction of the way you are to max speed levels is the fraction you lose
- if(charge_max < charge_counter)
- charge_counter = charge_max
-
- var/temp = ""
- name = initial(name)
- switch(level_max[Sp_SPEED] - spell_levels[Sp_SPEED])
- if(3)
- temp = "You have improved [name] into Efficient [name]."
- name = "Efficient [name]"
- if(2)
- temp = "You have improved [name] into Quickened [name]."
- name = "Quickened [name]"
- if(1)
- temp = "You have improved [name] into Free [name]."
- name = "Free [name]"
- if(0)
- temp = "You have improved [name] into Instant [name]."
- name = "Instant [name]"
-
- return temp
-
-/spell/proc/spell_do_after(var/mob/user, delay, var/numticks = 5)
- if(!user || isnull(user))
- return 0
-
- var/incap_flags = INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT
- return do_after(user,delay, incapacitation_flags = incap_flags)
-
-/proc/view_or_range(distance = world.view , center = usr , type)
- switch(type)
- if("view")
- . = view(distance,center)
- if("range")
- . = range(distance,center)
\ No newline at end of file
diff --git a/code/modules/spells/spells.dm b/code/modules/spells/spells.dm
deleted file mode 100644
index ad550747a7f..00000000000
--- a/code/modules/spells/spells.dm
+++ /dev/null
@@ -1,60 +0,0 @@
-/datum/mind
- var/list/learned_spells
-
-/mob/Stat()
- . = ..()
- if(. && ability_master && ability_master.spell_objects)
- for(var/obj/screen/ability/spell/screen in ability_master.spell_objects)
- var/spell/S = screen.spell
- if((!S.connected_button) || !statpanel(S.panel))
- continue //Not showing the noclothes spell
- switch(S.charge_type)
- if(Sp_RECHARGE)
- statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S.connected_button)
- if(Sp_CHARGES)
- statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button)
- if(Sp_HOLDVAR)
- statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button)
-
-/proc/restore_spells(var/mob/H)
- if(H.mind && H.mind.learned_spells)
- var/list/spells = list()
- for(var/spell/spell_to_remove in H.mind.learned_spells) //remove all the spells from other people.
- if(ismob(spell_to_remove.holder))
- var/mob/M = spell_to_remove.holder
- spells += spell_to_remove
- M.remove_spell(spell_to_remove)
-
- for(var/spell/spell_to_add in spells)
- H.add_spell(spell_to_add)
- H.ability_master.update_abilities(0,H)
-
-/mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready")
- if(!ability_master)
- ability_master = new(null, src)
- spell_to_add.holder = src
- if(mind)
- if(!mind.learned_spells)
- mind.learned_spells = list()
- mind.learned_spells |= spell_to_add
- ability_master.add_spell(spell_to_add, spell_base)
- return 1
-
-/mob/proc/remove_spell(var/spell/spell_to_remove)
- if(!spell_to_remove || !istype(spell_to_remove))
- return
-
- if(mind)
- mind.learned_spells -= spell_to_remove
- if (ability_master)
- ability_master.remove_ability(ability_master.get_ability_by_spell(spell_to_remove))
- return 1
-
-/mob/proc/silence_spells(var/amount = 0)
- if(amount < 0)
- return
-
- if(!ability_master)
- return
-
- ability_master.silence_spells(amount)
\ No newline at end of file
diff --git a/code/modules/spells/targeted/ethereal_jaunt.dm b/code/modules/spells/targeted/ethereal_jaunt.dm
deleted file mode 100644
index 55a0ed83359..00000000000
--- a/code/modules/spells/targeted/ethereal_jaunt.dm
+++ /dev/null
@@ -1,120 +0,0 @@
-/spell/targeted/ethereal_jaunt
- name = "Ethereal Jaunt"
- desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls."
- feedback = "EJ"
- school = "transmutation"
- charge_max = 30 SECONDS
- spell_flags = Z2NOCAST | INCLUDEUSER
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
- max_targets = 1
- level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 3)
- cooldown_min = 10 SECONDS //50 deciseconds reduction per rank
- duration = 5 SECONDS
-
- hud_state = "wiz_jaunt"
-
-/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded
- for(var/mob/living/target in targets)
- if(HAS_TRANSFORMATION_MOVEMENT_HANDLER(target))
- continue
-
- if(target.buckled)
- target.buckled.unbuckle_mob()
- spawn(0)
- var/mobloc = get_turf(target.loc)
- var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( mobloc )
- var/atom/movable/overlay/animation = new /atom/movable/overlay(holder)
- animation.SetName("water")
- animation.set_density(0)
- animation.anchored = TRUE
- animation.icon = 'icons/mob/mob.dmi'
- animation.layer = FLY_LAYER
- target.extinguish_fire()
- if(target.buckled)
- target.buckled = null
- jaunt_disappear(animation, target)
- target.forceMove(holder)
- jaunt_steam(mobloc)
- sleep(duration)
- mobloc = holder.last_valid_turf
- animation.forceMove(mobloc)
- jaunt_steam(mobloc)
- holder.reappearing = 1
- sleep(20)
- jaunt_reappear(animation, target)
- sleep(5)
- if(!target.forceMove(mobloc))
- for(var/direction in list(1,2,4,8,5,6,9,10))
- var/turf/T = get_step(mobloc, direction)
- if(T)
- if(target.forceMove(T))
- break
- target.client.eye = target
- qdel(animation)
- qdel(holder)
-
-/spell/targeted/ethereal_jaunt/empower_spell()
- if(!..())
- return 0
- duration += 2 SECONDS
-
- return "[src] now lasts longer."
-
-/spell/targeted/ethereal_jaunt/proc/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target)
- animation.icon_state = "liquify"
- flick("liquify",animation)
- playsound(get_turf(target), 'sound/magic/ethereal_enter.ogg', 30)
-
-/spell/targeted/ethereal_jaunt/proc/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target)
- flick("reappear",animation)
- playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 30)
-
-/spell/targeted/ethereal_jaunt/proc/jaunt_steam(var/mobloc)
- var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
- steam.set_up(10, 0, mobloc)
- steam.start()
-
-/obj/effect/dummy/spell_jaunt
- name = "water"
- icon = 'icons/effects/effects.dmi'
- icon_state = "nothing"
- var/canmove = 1
- var/reappearing = 0
- density = FALSE
- anchored = TRUE
- var/turf/last_valid_turf
-
-/obj/effect/dummy/spell_jaunt/Initialize()
- . = ..()
- last_valid_turf = get_turf(loc)
-
-/obj/effect/dummy/spell_jaunt/Destroy()
- // Eject contents if deleted somehow
- for(var/atom/movable/AM in src)
- AM.dropInto(loc)
- return ..()
-
-/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction)
- if (!canmove || reappearing) return
- var/turf/newLoc = get_step(src, direction)
- if(!(newLoc.turf_flags & TURF_FLAG_NOJAUNT))
- forceMove(newLoc)
- var/turf/T = get_turf(loc)
- if(!T.contains_dense_objects())
- last_valid_turf = T
- else
- to_chat(user, "Some strange aura is blocking the way!")
- canmove = 0
- addtimer(CALLBACK(src, PROC_REF(allow_move)), 2)
-
-/obj/effect/dummy/spell_jaunt/proc/allow_move()
- canmove = TRUE
-
-/obj/effect/dummy/spell_jaunt/explosion_act(blah)
- SHOULD_CALL_PARENT(FALSE)
- return
-
-/obj/effect/dummy/spell_jaunt/bullet_act(blah)
- return
diff --git a/code/modules/spells/targeted/shift.dm b/code/modules/spells/targeted/shift.dm
deleted file mode 100644
index 2bcc684939a..00000000000
--- a/code/modules/spells/targeted/shift.dm
+++ /dev/null
@@ -1,24 +0,0 @@
-/spell/targeted/ethereal_jaunt/shift
- name = "Phase Shift"
- desc = "This spell allows you to pass through walls"
-
- charge_max = 200
- spell_flags = Z2NOCAST | INCLUDEUSER | CONSTRUCT_CHECK
- invocation_type = SpI_NONE
- range = -1
- duration = 50 //in deciseconds
-
- hud_state = "const_shift"
-
-/spell/targeted/ethereal_jaunt/shift/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target)
- animation.icon_state = "phase_shift"
- animation.set_dir(target.dir)
- flick("phase_shift",animation)
-
-/spell/targeted/ethereal_jaunt/shift/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target)
- animation.icon_state = "phase_shift2"
- animation.set_dir(target.dir)
- flick("phase_shift2",animation)
-
-/spell/targeted/ethereal_jaunt/shift/jaunt_steam(var/mobloc)
- return
diff --git a/code/modules/spells/targeted/targeted.dm b/code/modules/spells/targeted/targeted.dm
deleted file mode 100644
index 733bbf1e540..00000000000
--- a/code/modules/spells/targeted/targeted.dm
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
-Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range
-Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm
-*/
-
-/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob
- var/max_targets = 1 //leave 0 for unlimited targets in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range
- var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast
-
-
- var/amt_weakened = 0
- var/amt_paralysis = 0
- var/amt_stunned = 0
-
- var/amt_dizziness = 0
- var/amt_confused = 0
- var/amt_stuttering = 0
-
- //set to negatives for healing unless commented otherwise
- var/amt_dam_fire = 0
- var/amt_dam_brute = 0
- var/amt_dam_oxy = 0
- var/amt_dam_tox = 0
- var/amt_dam_robo = 0
- var/amt_brain = 0
- var/amt_radiation = 0
- var/amt_blood = 0 //Positive numbers to add blood
- var/amt_organ = 0 //Positive numbers for healing
-
- var/amt_eye_blind = 0
- var/amt_eye_blurry = 0
-
- var/effect_state = null //What effect to show on each, if any
- var/effect_duration = 0
- var/effect_color = "#ffffff"
-
- var/list/compatible_mobs = list()
-
-
-/spell/targeted/choose_targets(mob/user = usr)
- var/list/targets = list()
-
- if(max_targets == 0) //unlimited
- if(range == -2)
- targets = global.living_mob_list_
- else
- for(var/mob/living/target in view_or_range(range, holder, selection_type))
- targets += target
-
- else if(max_targets == 1) //single target can be picked
- if((range == 0 || range == -1) && spell_flags & INCLUDEUSER)
- targets += user
- else
- var/list/possible_targets = list()
- var/list/starting_targets
- if(range == -2)
- starting_targets = global.living_mob_list_
- else
- starting_targets = view_or_range(range, holder, selection_type)
-
- for(var/mob/living/M in starting_targets)
- if(!(spell_flags & INCLUDEUSER) && M == user)
- continue
- if(compatible_mobs && compatible_mobs.len)
- if(!is_type_in_list(M, compatible_mobs)) continue
- if(compatible_mobs && compatible_mobs.len && !is_type_in_list(M, compatible_mobs))
- continue
- possible_targets += M
-
- if(possible_targets.len)
- targets += pick(possible_targets)
- //Adds a safety check post-input to make sure those targets are actually in range.
-
-
- else
- var/list/possible_targets = list()
- var/list/starting_targets
-
- if(range == -2)
- starting_targets = global.living_mob_list_
- else
- starting_targets = view_or_range(range, holder, selection_type)
-
- for(var/mob/living/target in starting_targets)
- if(!(spell_flags & INCLUDEUSER) && target == user)
- continue
- if(compatible_mobs && !is_type_in_list(target, compatible_mobs))
- continue
- possible_targets += target
-
- for(var/i=1,i<=max_targets,i++)
- if(!possible_targets.len)
- break
- if(target_ignore_prev)
- var/target = pick(possible_targets)
- possible_targets -= target
- targets += target
- else
- targets += pick(possible_targets)
-
- if(!(spell_flags & INCLUDEUSER) && (user in targets))
- targets -= user
-
- if(compatible_mobs && compatible_mobs.len)
- for(var/mob/living/target in targets) //filters out all the non-compatible mobs
- if(!is_type_in_list(target, compatible_mobs))
- targets -= target
-
- return targets
-
-/spell/targeted/cast(var/list/targets, mob/user)
- for(var/mob/living/target in targets)
- if(range >= 0)
- if(!(target in view_or_range(range, holder, selection_type))) //filter at time of casting
- targets -= target
- continue
- apply_spell_damage(target)
-
-/spell/targeted/proc/apply_spell_damage(mob/living/target)
- target.take_damage(amt_dam_brute, do_update_health = FALSE)
- target.take_damage(amt_dam_fire, BURN, do_update_health = FALSE)
- target.take_damage(amt_dam_tox, TOX, do_update_health = FALSE)
- target.take_damage(amt_dam_oxy, OXY)
- if(ishuman(target))
- var/mob/living/human/H = target
- for(var/obj/item/organ/internal/affecting in H.get_internal_organs())
- if(affecting && istype(affecting))
- affecting.heal_damage(amt_organ, amt_organ)
- for(var/obj/item/organ/external/affecting in H.get_external_organs())
- if(affecting && istype(affecting))
- var/dam = BP_IS_PROSTHETIC(affecting) ? -amt_dam_robo : amt_organ
- affecting.heal_damage(dam, dam, robo_repair = BP_IS_PROSTHETIC(affecting))
- H.adjust_blood(amt_blood)
- H.take_damage(amt_brain, BRAIN)
- H.radiation += min(H.radiation, amt_radiation)
-
- target.update_icon()
- //disabling
- SET_STATUS_MAX(target, STAT_WEAK, amt_weakened)
- SET_STATUS_MAX(target, STAT_PARA, amt_paralysis)
- SET_STATUS_MAX(target, STAT_STUN, amt_stunned)
- if(amt_weakened || amt_paralysis || amt_stunned)
- if(target.buckled)
- target.buckled = null
- ADJ_STATUS(target, STAT_BLIND, amt_eye_blind)
- ADJ_STATUS(target, STAT_BLURRY, amt_eye_blurry)
- ADJ_STATUS(target, STAT_DIZZY, amt_dizziness)
- ADJ_STATUS(target, STAT_CONFUSE, amt_confused)
- ADJ_STATUS(target, STAT_STUTTER, amt_stuttering)
- if(effect_state)
- var/obj/o = new /obj/effect/temporary(get_turf(target), effect_duration, 'icons/effects/effects.dmi', effect_state)
- o.color = effect_color
diff --git a/code/modules/submaps/submap_job.dm b/code/modules/submaps/submap_job.dm
index 9bc3687a1ae..89d8b2f3871 100644
--- a/code/modules/submaps/submap_job.dm
+++ b/code/modules/submaps/submap_job.dm
@@ -7,7 +7,8 @@
create_record = FALSE
total_positions = 4
outfit_type = /decl/outfit/job/survivor
- hud_icon = "hudblank"
+ hud_icon_state = "hudblank"
+ hud_icon = null
available_by_default = FALSE
allowed_ranks = null
allowed_branches = null
@@ -55,7 +56,12 @@
if(islist(blacklisted_species) && !length(blacklisted_species))
blacklisted_species |= SSmodpacks.default_submap_blacklisted_species
- if(!abstract_job)
+ if(abstract_job)
+ if(!hud_icon)
+ hud_icon = global.using_map.hud_icons
+ if(!hud_icon_state)
+ hud_icon_state = "hud[ckey(title)]"
+ else
spawnpoints = list()
owner = _owner
..()
diff --git a/code/modules/tools/components/head.dm b/code/modules/tools/components/head.dm
index 5d7aa85f512..e8e408c7c76 100644
--- a/code/modules/tools/components/head.dm
+++ b/code/modules/tools/components/head.dm
@@ -40,6 +40,11 @@ var/global/list/_tool_properties_cache = list()
desc = "The head of a hoe."
icon_state = "hoe"
+/obj/item/tool_component/head/chisel
+ name = "chisel head"
+ desc = "The head of a chisel."
+ icon_state = "hoe"
+
/obj/item/tool_component/head/handaxe
name = "hand axe head"
desc = "The head of a hand axe."
@@ -58,3 +63,8 @@ var/global/list/_tool_properties_cache = list()
icon_state = "sledgehammer"
w_class = ITEM_SIZE_NORMAL
+/obj/item/tool_component/head/forging_hammer
+ name = "forging hammer head"
+ desc = "The head of a forging hammer."
+ icon_state = "forging"
+ w_class = ITEM_SIZE_NORMAL
diff --git a/code/modules/tools/subtypes/axes.dm b/code/modules/tools/subtypes/axes.dm
index d2de61af41b..49535017564 100644
--- a/code/modules/tools/subtypes/axes.dm
+++ b/code/modules/tools/subtypes/axes.dm
@@ -22,6 +22,9 @@
material = /decl/material/solid/metal/iron
handle_material = /decl/material/solid/organic/wood/ebony
+/obj/item/tool/axe/iron
+ material = /decl/material/solid/metal/iron
+
/obj/item/tool/axe/ebony/bronze
material = /decl/material/solid/metal/bronze
diff --git a/code/modules/tools/subtypes/hammers.dm b/code/modules/tools/subtypes/hammers.dm
index bb1c9ee58cd..79e5e26956d 100644
--- a/code/modules/tools/subtypes/hammers.dm
+++ b/code/modules/tools/subtypes/hammers.dm
@@ -79,3 +79,18 @@
TOOL_SHOVEL = TOOL_QUALITY_DECENT
)
return tool_qualities
+
+/obj/item/tool/hammer/forge
+ name = "forging hammer"
+ desc = "A heavy hammer, used to forge hot metal at an anvil."
+ icon = 'icons/obj/items/tool/hammers/forge.dmi'
+ w_class = ITEM_SIZE_NORMAL
+
+// Forging hammers are not great at general hammer tasks (too heavy I guess),
+// and also don't work as crowbars due to missing the nail ripper/flange,
+// but will be more effective at forging when blacksmithy is merged.
+/obj/item/tool/hammer/forge/get_initial_tool_qualities()
+ var/static/list/tool_qualities = list(
+ TOOL_HAMMER = TOOL_QUALITY_MEDIOCRE
+ )
+ return tool_qualities
diff --git a/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm b/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm
index e41572bbd63..22e68e9011e 100644
--- a/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm
+++ b/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm
@@ -1,7 +1,7 @@
/obj/machinery/giga_drill
name = "alien drill"
desc = "A giant, alien drill mounted on long treads."
- icon = 'icons/obj/mining.dmi'
+ icon = 'icons/obj/machines/gigadrill.dmi'
icon_state = "gigadrill"
var/active = 0
var/drill_time = 10
diff --git a/code/modules/xenoarcheaology/boulder.dm b/code/modules/xenoarcheaology/boulder.dm
index ad492eb65ef..ba7a38c2f3d 100644
--- a/code/modules/xenoarcheaology/boulder.dm
+++ b/code/modules/xenoarcheaology/boulder.dm
@@ -1,8 +1,8 @@
/obj/structure/boulder
name = "boulder"
desc = "A large boulder, somewhat bigger than a small boulder."
- icon = 'icons/obj/mining.dmi'
- icon_state = "boulder1"
+ icon = 'icons/obj/structures/boulder.dmi'
+ icon_state = ICON_STATE_WORLD
density = TRUE
opacity = TRUE
anchored = TRUE
@@ -30,7 +30,7 @@
/obj/structure/boulder/Initialize(var/ml, var/_mat, var/coloration)
. = ..()
- icon_state = "boulder[rand(1,6)]"
+ icon_state = "[initial(icon_state)][rand(1,6)]"
if(coloration)
color = coloration
excavation_level = rand(5, 50)
diff --git a/code/modules/xenoarcheaology/datums/artifact_find.dm b/code/modules/xenoarcheaology/datums/artifact_find.dm
index b70f17112e8..242af56502d 100644
--- a/code/modules/xenoarcheaology/datums/artifact_find.dm
+++ b/code/modules/xenoarcheaology/datums/artifact_find.dm
@@ -2,8 +2,6 @@
var/artifact_id
var/artifact_find_type
var/static/potential_finds = list(
- /obj/machinery/power/supermatter = 5,
- /obj/machinery/power/supermatter/shard = 25,
/obj/machinery/auto_cloner = 100,
/obj/machinery/giga_drill = 100,
/obj/machinery/replicator = 100,
diff --git a/code/modules/xenoarcheaology/tools/tools.dm b/code/modules/xenoarcheaology/tools/tools.dm
index 213d77ff128..813f424e7f1 100644
--- a/code/modules/xenoarcheaology/tools/tools.dm
+++ b/code/modules/xenoarcheaology/tools/tools.dm
@@ -10,8 +10,8 @@
/obj/item/bag/fossils
name = "fossil satchel"
desc = "Transports delicate fossils in suspension so they don't break during transit."
- icon = 'icons/obj/mining.dmi'
- icon_state = "satchel"
+ icon = 'icons/obj/items/mining_satchel.dmi'
+ icon_state = ICON_STATE_WORLD
slot_flags = SLOT_LOWER_BODY | SLOT_POCKET
w_class = ITEM_SIZE_NORMAL
storage = /datum/storage/bag/fossils
diff --git a/code/unit_tests/icon_tests.dm b/code/unit_tests/icon_tests.dm
index 3c003aba22d..58783a20f51 100644
--- a/code/unit_tests/icon_tests.dm
+++ b/code/unit_tests/icon_tests.dm
@@ -299,3 +299,64 @@
else
pass("All vendors have all icons and icon states.")
return 1
+
+
+/datum/unit_test/HUDS_shall_have_icon_states
+ name = "ICON STATE: HUD overlays shall have appropriate icon_states"
+
+/datum/unit_test/HUDS_shall_have_icon_states/start_test()
+ var/failed_jobs = 0
+ var/failed_sanity_checks = 0
+
+ // Throwing implants and health HUDs in here.
+ // Antag HUDs are tested by special role validation.
+
+ var/static/list/implant_hud_states = list(
+ "hud_imp_blank" = "Blank",
+ "hud_imp_loyal" = "Loyalty",
+ "hud_imp_unknown" = "Unknown",
+ "hud_imp_tracking" = "Tracking",
+ "hud_imp_chem" = "Chemical",
+ )
+ for(var/implant_hud_state in implant_hud_states)
+ if(!check_state_in_icon(implant_hud_state, global.using_map.implant_hud_icons))
+ log_bad("Sanity Check - Missing map [implant_hud_states[implant_hud_state]] implant HUD icon_state '[implant_hud_state]' from icon [global.using_map.implant_hud_icons]")
+ failed_sanity_checks++
+
+ var/static/list/med_hud_states = list(
+ "blank" = "Blank",
+ "flatline" = "Flatline",
+ "0" = "Dead",
+ "1" = "Healthy",
+ "2" = "Lightly injured",
+ "3" = "Moderately injured",
+ "4" = "Severely injured",
+ "5" = "Dying",
+ )
+ for(var/med_hud_state in med_hud_states)
+ if(!check_state_in_icon(med_hud_state, global.using_map.med_hud_icons))
+ log_bad("Sanity Check - Missing map [med_hud_states[med_hud_state]] medical HUD icon_state '[med_hud_state]' from icon [global.using_map.med_hud_icons]")
+ failed_sanity_checks++
+ var/static/list/global_states = list(
+ "" = "Default/unnamed",
+ "hudunknown" = "Unknown role",
+ "hudhealthy" = "Healthy mob",
+ "hudill" = "Diseased mob",
+ "huddead" = "Dead mob"
+ )
+ for(var/global_state in global_states)
+ if(!check_state_in_icon(global_state, global.using_map.hud_icons))
+ log_bad("Sanity Check - Missing map [global_states[global_state]] HUD icon_state '[global_state]' from icon [global.using_map.hud_icons]")
+ failed_sanity_checks++
+
+ for(var/job_name in SSjobs.titles_to_datums)
+ var/datum/job/job = SSjobs.titles_to_datums[job_name]
+ if(!check_state_in_icon(job.hud_icon_state, job.hud_icon))
+ log_bad("[job.title] - Missing HUD icon: [job.hud_icon_state] in icon [job.hud_icon]")
+ failed_jobs++
+
+ if(failed_sanity_checks || failed_jobs)
+ fail("[global.using_map.type] - [failed_sanity_checks] failed sanity check\s, [failed_jobs] job\s with missing HUD icon.")
+ else
+ pass("All jobs have a HUD icon.")
+ return 1
diff --git a/code/unit_tests/job_tests.dm b/code/unit_tests/job_tests.dm
index 858063c9bad..b6b652731f8 100644
--- a/code/unit_tests/job_tests.dm
+++ b/code/unit_tests/job_tests.dm
@@ -35,36 +35,6 @@
pass("All jobs had outfit types.")
return 1
-/datum/unit_test/jobs_shall_have_a_HUD_icon
- name = "JOB: Shall have a HUD icon"
-
-/datum/unit_test/jobs_shall_have_a_HUD_icon/start_test()
- var/failed_jobs = 0
- var/failed_sanity_checks = 0
-
- var/list/job_huds = get_states_in_icon_cached(global.using_map.id_hud_icons)
-
- if(!job_huds[""])
- log_bad("Sanity Check - Missing default/unnamed HUD icon")
- failed_sanity_checks++
-
- if(!job_huds["hudunknown"])
- log_bad("Sanity Check - Missing HUD icon: hudunknown")
- failed_sanity_checks++
-
- for(var/job_name in SSjobs.titles_to_datums)
- var/datum/job/J = SSjobs.titles_to_datums[job_name]
- var/hud_icon_state = J.hud_icon
- if(!job_huds[hud_icon_state])
- log_bad("[J.title] - Missing HUD icon: [hud_icon_state]")
- failed_jobs++
-
- if(failed_sanity_checks || failed_jobs)
- fail("[global.using_map.id_hud_icons] - [failed_sanity_checks] failed sanity check\s, [failed_jobs] job\s with missing HUD icon.")
- else
- pass("All jobs have a HUD icon.")
- return 1
-
/datum/unit_test/jobs_shall_have_a_unique_title
name = "JOBS: All Job Datums Shall Have A Unique Title"
diff --git a/code/unit_tests/turf_icons.dm b/code/unit_tests/turf_icons.dm
index 5cf5cb9dce7..3319864ee2a 100644
--- a/code/unit_tests/turf_icons.dm
+++ b/code/unit_tests/turf_icons.dm
@@ -8,8 +8,7 @@
/turf/unsimulated
)
var/list/excepted_types = list(
- /turf/unsimulated/map,
- /turf/unsimulated/wall/cascade
+ /turf/unsimulated/map
)
/datum/unit_test/turf_floor_icons_shall_be_valid/setup_test()
diff --git a/html/changelog.html b/html/changelog.html
index daa00b874bd..58aeb978adc 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -52,6 +52,20 @@
-->
+
16 January 2025
+
MistakeNot4892 updated:
+
+
The White and Minimalist HUD styles can now be customised to use a specific overlay color.
+
The Shaded Hills river now flows north.
+
Snow, mud and sand will now show footprints.
+
+
+
15 January 2025
+
MistakeNot4892 updated:
+
+
The way you interact with barrels and well has been significantly reworked; clicking with a bucket or tool should give a list of options to pick from. Please report bugs with this on the tracker.
+
+
08 January 2025
MistakeNot4892 updated:
@@ -95,15 +109,6 @@
MistakeNot4892 updated:
Swapped barrel icons out for Doe's much nicer barrels.
-
-
13 November 2024
-
Penelope Haze updated:
-
-
Added a new wooden bucket sprite.
-
Quills now have a limited amount of ink, which can be refilled in an inkwell.
-
Crayons are now slowly used up while writing on paper, at a rate of one charge per 25 characters. (Crayons have a default of 30 charges.)