Their neck has already been already cut, you can't make the bleeding any worse!")
@@ -65,7 +65,7 @@
H.visible_message("[user] slits [H]'s throat!", \
"[user] slits your throat...")
H.apply_damage(item_force, BRUTE, BODY_ZONE_HEAD)
- H.bleed_rate = CLAMP(H.bleed_rate + 20, 0, 30)
+ H.bleed_rate = clamp(H.bleed_rate + 20, 0, 30)
H.apply_status_effect(/datum/status_effect/neck_slice)
/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat)
@@ -98,6 +98,8 @@
"You butcher [meat].")
ButcherEffects(meat)
meat.harvest(butcher)
+ meat.log_message("has been butchered by [key_name(butcher)]", LOG_ATTACK)
+ meat.investigate_log("was gibbed via butchering", INVESTIGATE_DEATHS)
meat.gib(FALSE, FALSE, TRUE)
/datum/component/butchering/proc/ButcherEffects(mob/living/meat) //extra effects called on butchering, override this via subtypes
diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm
index bf0ab993a21e8..2838e70c19450 100644
--- a/code/datums/components/chasm.dm
+++ b/code/datums/components/chasm.dm
@@ -116,8 +116,7 @@
if (isliving(AM))
var/mob/living/L = AM
L.notransform = TRUE
- L.Stun(200)
- L.resting = TRUE
+ L.Paralyze(20 SECONDS)
var/oldtransform = AM.transform
var/oldcolor = AM.color
diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm
index 4e0b168d6f8ce..5334171425b8f 100644
--- a/code/datums/components/embedded.dm
+++ b/code/datums/components/embedded.dm
@@ -133,7 +133,7 @@
var/damage = weapon.w_class * pain_mult
var/max_damage = weapon.w_class * max_damage_mult + weapon.throwforce
var/pain_chance_current = DT_PROB_RATE(pain_chance / 100, delta_time) * 100
- if(pain_stam_pct && victim.stam_paralyzed) //if it's a less-lethal embed, give them a break if they're already stamcritted
+ if(pain_stam_pct && HAS_TRAIT_FROM(victim, TRAIT_INCAPACITATED, STAMINA)) //if it's a less-lethal embed, give them a break if they're already stamcritted
pain_chance_current *= 0.2
damage *= 0.5
else if(victim.mobility_flags & ~MOBILITY_STAND)
@@ -142,7 +142,7 @@
if(harmful && prob(pain_chance_current))
var/damage_left = max_damage - limb.get_damage()
var/damage_wanted = (1-pain_stam_pct) * damage
- var/damage_to_deal = CLAMP(damage_wanted, 0, damage_left)
+ var/damage_to_deal = clamp(damage_wanted, 0, damage_left)
var/damage_as_stam = damage_wanted - damage_to_deal
if(!damage_to_deal)
to_chat(victim, "[weapon] embedded in your [limb.name] stings a little!")
diff --git a/code/datums/components/empprotection.dm b/code/datums/components/empprotection.dm
deleted file mode 100644
index bb94b08e55a9b..0000000000000
--- a/code/datums/components/empprotection.dm
+++ /dev/null
@@ -1,13 +0,0 @@
-/datum/component/empprotection
- var/flags = NONE
-
-/datum/component/empprotection/Initialize(_flags)
- if(!istype(parent, /atom))
- return COMPONENT_INCOMPATIBLE
- flags = _flags
- RegisterSignal(parent, list(COMSIG_ATOM_EMP_ACT), PROC_REF(getEmpFlags))
-
-/datum/component/empprotection/proc/getEmpFlags(datum/source, severity)
- SIGNAL_HANDLER
-
- return flags
diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm
index ef2ae7346db6d..161e6c05d6a17 100644
--- a/code/datums/components/food/edible.dm
+++ b/code/datums/components/food/edible.dm
@@ -200,14 +200,14 @@ Behavior that's still missing from this component that original food items had t
for(var/obj/item/crafted_part in this_food.contents)
crafted_part.reagents?.trans_to(this_food.reagents, crafted_part.reagents.maximum_volume, CRAFTED_FOOD_INGREDIENT_REAGENT_MODIFIER)
- var/list/objects_to_delete = list()
+ var/list/objects_to_delete = this_food.contents.Copy()
// Remove all non recipe objects from the contents
for(var/content_object in this_food.contents)
- for(var/recipe_object in recipe.real_parts)
+ for(var/recipe_object in recipe.parts)
if(istype(content_object, recipe_object))
- continue
- objects_to_delete += content_object
+ objects_to_delete -= content_object
+ break
QDEL_LIST(objects_to_delete)
diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm
index cd0c49d93bfd2..4b0ce2501eee2 100644
--- a/code/datums/components/nanites.dm
+++ b/code/datums/components/nanites.dm
@@ -8,11 +8,11 @@
var/safety_threshold = 50 //how low nanites will get before they stop processing/triggering
var/cloud_id = 0 //0 if not connected to the cloud, 1-100 to set a determined cloud backup to draw from
var/cloud_active = TRUE //if false, won't sync to the cloud
- var/next_sync = 0
var/list/datum/nanite_program/programs = list()
var/max_programs = NANITE_PROGRAM_LIMIT
+ COOLDOWN_DECLARE(next_sync)
- var/list/datum/nanite_program/protocol/protocols = list() ///Separate list of protocol programs, to avoid looping through the whole programs list when cheking for conflicts
+ var/list/datum/nanite_program/protocol/protocols = list() /// Separate list of protocol programs, to avoid looping through the whole programs list when cheking for conflicts
var/start_time = 0 ///Timestamp to when the nanites were first inserted in the host
var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans
var/diagnostics = TRUE //if TRUE, displays program list when scanned by nanite scanners
@@ -103,42 +103,40 @@
/datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, amount, cloud)
if(new_nanites)
- adjust_nanites(null, new_nanites.nanite_volume)
+ adjust_nanites(amount = new_nanites.nanite_volume)
else
- adjust_nanites(null, amount) //just add to the nanite volume
+ adjust_nanites(amount = amount) //just add to the nanite volume
/datum/component/nanites/process(delta_time)
if(!IS_IN_STASIS(host_mob))
- adjust_nanites(null, regen_rate * delta_time)
+ adjust_nanites(amount = (regen_rate + (SSresearch.science_tech.researched_nodes["nanite_harmonic"] ? HARMONIC_REGEN_BOOST : 0)) * delta_time)
add_research()
- for(var/X in programs)
- var/datum/nanite_program/NP = X
- NP.on_process()
- if(cloud_id && cloud_active && world.time > next_sync)
+ for(var/datum/nanite_program/program as anything in programs)
+ program.on_process()
+ if(cloud_id && cloud_active && COOLDOWN_FINISHED(src, next_sync))
cloud_sync()
- next_sync = world.time + NANITE_SYNC_DELAY
+ COOLDOWN_START(src, next_sync, NANITE_SYNC_DELAY)
set_nanite_bar()
+/// Deletes nanites!
/datum/component/nanites/proc/delete_nanites()
SIGNAL_HANDLER
qdel(src)
-//Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status)
+/// Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status)
/datum/component/nanites/proc/sync(datum/signal_source, datum/component/nanites/source, full_overwrite = TRUE, copy_settings = TRUE, copy_activation = FALSE)
SIGNAL_HANDLER
var/list/programs_to_remove = programs.Copy()
var/list/programs_to_add = source.programs.Copy()
- for(var/X in programs)
- var/datum/nanite_program/NP = X
- for(var/Y in programs_to_add)
- var/datum/nanite_program/SNP = Y
- if(NP.type == SNP.type)
- programs_to_remove -= NP
- programs_to_add -= SNP
- SNP.copy_programming(NP, copy_activation)
+ for(var/datum/nanite_program/current_program as anything in programs)
+ for(var/datum/nanite_program/new_program as anything in programs_to_add)
+ if(current_program.type == new_program.type)
+ programs_to_remove -= current_program
+ programs_to_add -= new_program
+ new_program.copy_programming(current_program, copy_activation)
break
if(full_overwrite)
for(var/X in programs_to_remove)
@@ -148,9 +146,10 @@
cloud_id = source.cloud_id
safety_threshold = source.safety_threshold
for(var/X in programs_to_add)
- var/datum/nanite_program/SNP = X
- add_program(null, SNP.copy())
+ for(var/datum/nanite_program/program as anything in programs_to_add)
+ add_program(new_program = program.copy())
+/// Syncs the nanites to their assigned cloud copy, if it is available. If it is not, there is a small chance of a software error instead.
/datum/component/nanites/proc/cloud_sync()
if(cloud_id)
var/datum/nanite_cloud_backup/backup = SSnanites.get_cloud_backup(cloud_id)
@@ -164,13 +163,13 @@
var/datum/nanite_program/NP = pick(programs)
NP.software_error()
+/// Adds a nanite program, replacing existing unique programs of the same type. A source program can be specified to copy its programming onto the new one.
/datum/component/nanites/proc/add_program(datum/source, datum/nanite_program/new_program, datum/nanite_program/source_program)
SIGNAL_HANDLER
- for(var/X in programs)
- var/datum/nanite_program/NP = X
- if(NP.unique && NP.type == new_program.type)
- qdel(NP)
+ for(var/datum/nanite_program/program as anything in programs)
+ if(program.unique && program.type == new_program.type)
+ qdel(program)
if(programs.len >= max_programs)
return COMPONENT_PROGRAM_NOT_INSTALLED
if(source_program)
@@ -182,16 +181,70 @@
/datum/component/nanites/proc/consume_nanites(amount, force = FALSE)
if(!force && safety_threshold && (nanite_volume - amount < safety_threshold))
return FALSE
- adjust_nanites(null, -amount)
+ adjust_nanites(amount = -amount)
return (nanite_volume > 0)
+/// Modifies the current nanite volume, then checks if the nanites are depleted or exceeding the maximum amount
/datum/component/nanites/proc/adjust_nanites(datum/source, amount)
SIGNAL_HANDLER
- nanite_volume = clamp(nanite_volume + amount, 0, max_nanites)
+ nanite_volume += amount
+ if(nanite_volume > max_nanites)
+ reject_excess_nanites()
if(nanite_volume <= 0) //oops we ran out
qdel(src)
+/**
+ * Handles how nanites leave the host's body if they find out that they're currently exceeding the maximum supported amount
+ *
+ * IC explanation:
+ * Normally nanites simply discard excess volume by slowing replication or 'sweating' it out in imperceptible amounts,
+ * but if there is a large excess volume, likely due to a programming change that leaves them unable to support their current volume,
+ * the nanites attempt to leave the host as fast as necessary to prevent nanite poisoning. This can range from minor oozing to nanites
+ * rapidly bursting out from every possible pathway, causing temporary inconvenience to the host.
+ */
+/datum/component/nanites/proc/reject_excess_nanites()
+ var/excess = nanite_volume - max_nanites
+ nanite_volume = max_nanites
+
+ switch(excess)
+ if(0 to NANITE_EXCESS_MINOR) //Minor excess amount, the extra nanites are quietly expelled without visible effects
+ return
+ if((NANITE_EXCESS_MINOR + 0.1) to NANITE_EXCESS_VOMIT) //Enough nanites getting rejected at once to be visible to the naked eye
+ host_mob.visible_message("A grainy grey slurry starts oozing out of [host_mob].", "A grainy grey slurry starts oozing out of your skin.", vision_distance = 4);
+ if((NANITE_EXCESS_VOMIT + 0.1) to NANITE_EXCESS_BURST) //Nanites getting rejected in massive amounts, but still enough to make a semi-orderly exit through vomit
+ if(iscarbon(host_mob))
+ var/mob/living/carbon/C = host_mob
+ host_mob.visible_message("[host_mob] vomits a grainy grey slurry!", "You suddenly vomit a metallic-tasting grainy grey slurry!");
+ C.vomit(0, FALSE, TRUE, FLOOR(excess / 100, 1), FALSE, VOMIT_NANITE, FALSE)
+ else
+ host_mob.visible_message("A metallic grey slurry bursts out of [host_mob]'s skin!", "A metallic grey slurry violently bursts out of your skin!");
+ if(isturf(host_mob.drop_location()))
+ var/turf/T = host_mob.drop_location()
+ T.add_vomit_floor(host_mob, VOMIT_NANITE, FALSE)
+ if((NANITE_EXCESS_BURST + 0.1) to INFINITY) //Way too many nanites, they just leave through the closest exit before they harm/poison the host
+ host_mob.visible_message("A torrent of metallic grey slurry violently bursts out of [host_mob]'s face and floods out of [host_mob.p_their()] skin!",
+ "A torrent of metallic grey slurry violently bursts out of your eyes, ears, and mouth, and floods out of your skin!");
+
+ host_mob.adjust_blindness(15) //nanites coming out of your eyes
+ host_mob.Paralyze(12 SECONDS)
+ if(iscarbon(host_mob))
+ var/mob/living/carbon/C = host_mob
+ var/obj/item/organ/ears/ears = C.getorganslot(ORGAN_SLOT_EARS)
+ if(ears)
+ ears.adjustEarDamage(0, 30) //nanites coming out of your ears
+ C.vomit(0, FALSE, TRUE, 2, FALSE, VOMIT_NANITE, FALSE) //nanites coming out of your mouth
+
+ //nanites everywhere
+ if(isturf(host_mob.drop_location()))
+ var/turf/T = host_mob.drop_location()
+ T.add_vomit_floor(host_mob, VOMIT_NANITE, FALSE)
+ for(var/turf/adjacent_turf in oview(host_mob, 1))
+ if(adjacent_turf.density || !adjacent_turf.Adjacent(T))
+ continue
+ adjacent_turf.add_vomit_floor(host_mob, VOMIT_NANITE, FALSE)
+
+/// Updates the nanite volume bar visible in diagnostic HUDs
/datum/component/nanites/proc/set_nanite_bar(remove = FALSE)
var/image/holder = host_mob.hud_list[DIAG_NANITE_FULL_HUD]
var/icon/I = icon(host_mob.icon, host_mob.icon_state, host_mob.dir)
@@ -207,7 +260,7 @@
SIGNAL_HANDLER
nanite_volume *= (rand(60, 90) * 0.01) //Lose 10-40% of nanites
- adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume
+ adjust_nanites(amount = -(rand(5, 50))) //Lose 5-50 flat nanite volume
if(prob(40/severity))
cloud_id = 0
for(var/X in programs)
@@ -223,18 +276,16 @@
if(!HAS_TRAIT_NOT_FROM(host_mob, TRAIT_SHOCKIMMUNE, "nanites"))//Another shock protection must protect nanites too, but nanites protect only host
nanite_volume *= (rand(45, 80) * 0.01) //Lose 20-55% of nanites
- adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume
- for(var/X in programs)
- var/datum/nanite_program/NP = X
- NP.on_shock(shock_damage)
+ adjust_nanites(amount = -(rand(5, 50))) //Lose 5-50 flat nanite volume
+ for(var/datum/nanite_program/program as anything in programs)
+ program.on_shock(shock_damage)
/datum/component/nanites/proc/on_minor_shock(datum/source)
SIGNAL_HANDLER
- adjust_nanites(null, -(rand(5, 15))) //Lose 5-15 flat nanite volume
- for(var/X in programs)
- var/datum/nanite_program/NP = X
- NP.on_minor_shock()
+ adjust_nanites(amount = -(rand(5, 15))) //Lose 5-15 flat nanite volume
+ for(var/datum/nanite_program/program as anything in programs)
+ program.on_minor_shock()
/datum/component/nanites/proc/check_stealth(datum/source)
SIGNAL_HANDLER
@@ -244,24 +295,20 @@
/datum/component/nanites/proc/on_death(datum/source, gibbed)
SIGNAL_HANDLER
- for(var/X in programs)
- var/datum/nanite_program/NP = X
- NP.on_death(gibbed)
+ for(var/datum/nanite_program/program as anything in programs)
+ program.on_death(gibbed)
/datum/component/nanites/proc/receive_signal(datum/source, code, source = "an unidentified source")
SIGNAL_HANDLER
- for(var/X in programs)
- var/datum/nanite_program/NP = X
- NP.receive_signal(code, source)
+ for(var/datum/nanite_program/program as anything in programs)
+ program.receive_nanite_signal(code, source)
/datum/component/nanites/proc/receive_comm_signal(datum/source, comm_code, comm_message, comm_source = "an unidentified source")
SIGNAL_HANDLER
- for(var/X in programs)
- if(istype(X, /datum/nanite_program/comm))
- var/datum/nanite_program/comm/NP = X
- NP.receive_comm_signal(comm_code, comm_message, comm_source)
+ for(var/datum/nanite_program/comm/program in programs)
+ program.receive_comm_signal(comm_code, comm_message, comm_source)
/datum/component/nanites/proc/check_viable_biotype()
SIGNAL_HANDLER
@@ -287,7 +334,7 @@
/datum/component/nanites/proc/set_max_volume(datum/source, amount)
SIGNAL_HANDLER
- max_nanites = max(1, max_nanites)
+ max_nanites = max(1, amount)
/datum/component/nanites/proc/set_cloud(datum/source, amount)
SIGNAL_HANDLER
@@ -368,10 +415,9 @@
if(!diagnostics)
message += "Diagnostics Disabled"
else
- for(var/X in programs)
- var/datum/nanite_program/program = X
+ for(var/datum/nanite_program/program as anything in programs)
message += "[program.name] | [program.activated ? "Active" : "Inactive"]"
- for(var/datum/nanite_rule/rule in program.rules)
+ for(var/datum/nanite_rule/rule as anything in program.rules)
message += "[GLOB.TAB][rule.display()]"
. = TRUE
if(length(message))
@@ -382,32 +428,31 @@
data["has_nanites"] = TRUE
data["nanite_volume"] = nanite_volume
- data["regen_rate"] = regen_rate
+ data["regen_rate"] = regen_rate + (SSresearch.science_tech.researched_nodes["nanite_harmonic"] ? HARMONIC_REGEN_BOOST : 0)
data["safety_threshold"] = safety_threshold
data["cloud_id"] = cloud_id
data["cloud_active"] = cloud_active
var/list/mob_programs = list()
var/id = 1
- for(var/X in programs)
- var/datum/nanite_program/P = X
+ for(var/datum/nanite_program/program as anything in programs)
var/list/mob_program = list()
- mob_program["name"] = P.name
- mob_program["desc"] = P.desc
+ mob_program["name"] = program.name
+ mob_program["desc"] = program.desc
mob_program["id"] = id
if(scan_level >= 2)
- mob_program["activated"] = P.activated
- mob_program["use_rate"] = P.use_rate
- mob_program["can_trigger"] = P.can_trigger
- mob_program["trigger_cost"] = P.trigger_cost
- mob_program["trigger_cooldown"] = P.trigger_cooldown / 10
+ mob_program["activated"] = program.activated
+ mob_program["use_rate"] = program.use_rate
+ mob_program["can_trigger"] = program.can_trigger
+ mob_program["trigger_cost"] = program.trigger_cost
+ mob_program["trigger_cooldown"] = program.trigger_cooldown / 10
if(scan_level >= 3)
- mob_program["timer_restart"] = P.timer_restart / 10
- mob_program["timer_shutdown"] = P.timer_shutdown / 10
- mob_program["timer_trigger"] = P.timer_trigger / 10
- mob_program["timer_trigger_delay"] = P.timer_trigger_delay / 10
- var/list/extra_settings = P.get_extra_settings_frontend()
+ mob_program["timer_restart"] = program.timer_restart / 10
+ mob_program["timer_shutdown"] = program.timer_shutdown / 10
+ mob_program["timer_trigger"] = program.timer_trigger / 10
+ mob_program["timer_trigger_delay"] = program.timer_trigger_delay / 10
+ var/list/extra_settings = program.get_extra_settings_frontend()
mob_program["extra_settings"] = extra_settings
if(LAZYLEN(extra_settings))
mob_program["has_extra_settings"] = TRUE
@@ -415,14 +460,13 @@
mob_program["has_extra_settings"] = FALSE
if(scan_level >= 4)
- mob_program["activation_code"] = P.activation_code
- mob_program["deactivation_code"] = P.deactivation_code
- mob_program["kill_code"] = P.kill_code
- mob_program["trigger_code"] = P.trigger_code
+ mob_program["activation_code"] = program.activation_code
+ mob_program["deactivation_code"] = program.deactivation_code
+ mob_program["kill_code"] = program.kill_code
+ mob_program["trigger_code"] = program.trigger_code
var/list/rules = list()
var/rule_id = 1
- for(var/Z in P.rules)
- var/datum/nanite_rule/nanite_rule = Z
+ for(var/datum/nanite_rule/nanite_rule as anything in program.rules)
var/list/rule = list()
rule["display"] = nanite_rule.display()
rule["program_id"] = id
diff --git a/code/datums/components/storage/concrete/bag_of_holding.dm b/code/datums/components/storage/concrete/bag_of_holding.dm
index def1aef30e398..28f3cde185955 100644
--- a/code/datums/components/storage/concrete/bag_of_holding.dm
+++ b/code/datums/components/storage/concrete/bag_of_holding.dm
@@ -29,6 +29,7 @@
message_admins("[ADMIN_LOOKUPFLW(user)] detonated a bag of holding at [ADMIN_VERBOSEJMP(loccheck)].")
log_game("[key_name(user)] detonated a bag of holding at [loc_name(loccheck)].")
+ user.investigate_log("has been gibbed by a bag of holding recursive insertion.", INVESTIGATE_DEATHS)
user.gib(TRUE, TRUE, TRUE)
new/obj/boh_tear(loccheck)
qdel(A)
diff --git a/code/datums/components/storage/concrete/pockets.dm b/code/datums/components/storage/concrete/pockets.dm
index 1f7c822b17473..fd9ad899d4394 100644
--- a/code/datums/components/storage/concrete/pockets.dm
+++ b/code/datums/components/storage/concrete/pockets.dm
@@ -17,6 +17,7 @@
/datum/component/storage/concrete/pockets/small
max_items = 1
+ max_w_class = WEIGHT_CLASS_SMALL
attack_hand_interact = FALSE
/datum/component/storage/concrete/pockets/tiny
diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm
index 4d9865bd8b3d1..27f419f677271 100644
--- a/code/datums/components/storage/storage.dm
+++ b/code/datums/components/storage/storage.dm
@@ -335,8 +335,8 @@
numbered_contents = _process_numerical_display()
adjusted_contents = numbered_contents.len
- var/columns = CLAMP(max_items, 1, screen_max_columns)
- var/rows = CLAMP(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows)
+ var/columns = clamp(max_items, 1, screen_max_columns)
+ var/rows = clamp(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows)
standard_orient_objs(rows, columns, numbered_contents)
//This proc draws out the inventory and places the items on it. It uses the standard position.
diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm
index 5bf3b39a87b52..66831e30a094d 100644
--- a/code/datums/components/wet_floor.dm
+++ b/code/datums/components/wet_floor.dm
@@ -180,7 +180,7 @@
/datum/component/wet_floor/proc/_do_add_wet(type, duration_minimum, duration_add, duration_maximum)
var/time = 0
if(LAZYACCESS(time_left_list, "[type]"))
- time = CLAMP(LAZYACCESS(time_left_list, "[type]") + duration_add, duration_minimum, duration_maximum)
+ time = clamp(LAZYACCESS(time_left_list, "[type]") + duration_add, duration_minimum, duration_maximum)
else
time = min(duration_minimum, duration_maximum)
LAZYSET(time_left_list, "[type]", time)
diff --git a/code/datums/dash_weapon.dm b/code/datums/dash_weapon.dm
index 410b5e0a42983..de768730c96f3 100644
--- a/code/datums/dash_weapon.dm
+++ b/code/datums/dash_weapon.dm
@@ -47,7 +47,7 @@
to_chat(user, "You cannot dash here!")
/datum/action/innate/dash/proc/charge()
- current_charges = CLAMP(current_charges + 1, 0, max_charges)
+ current_charges = clamp(current_charges + 1, 0, max_charges)
owner.update_action_buttons_icon()
if(recharge_sound)
playsound(dashing_item, recharge_sound, 50, 1)
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index c5857fadb9359..efb0b9fe6727c 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -282,7 +282,7 @@
SetSpread()
permeability_mod = max(CEILING(0.4 * transmission, 1), 1)
- cure_chance = 15 - CLAMP(resistance, -5, 5) // can be between 10 and 20
+ cure_chance = 15 - clamp(resistance, -5, 5) // can be between 10 and 20
stage_prob = max(stage_rate, 2)
SetDanger(severity)
GenerateCure()
@@ -357,7 +357,7 @@
// Will generate a random cure, the less resistance the symptoms have, the harder the cure.
/datum/disease/advance/proc/GenerateCure()
- var/res = CLAMP(resistance - (symptoms.len / 2), 1, advance_cures.len)
+ var/res = clamp(resistance - (symptoms.len / 2), 1, advance_cures.len)
if(archivecure != res)
cures = list(pick(advance_cures[res]))
// Get the cure name from the cure_id
@@ -548,12 +548,12 @@
var/datum/disease/advance/A = make_copy ? Copy() : src
if(!initial && A.mutable && (spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS))
var/minimum = 1
- if(prob(CLAMP(35-(A.resistance + A.stealth - A.speed), 0, 50) * (A.mutability)))//stealthy/resistant diseases are less likely to mutate. this means diseases used to farm mutations should be easier to cure. hypothetically.
+ if(prob(clamp(35-(A.resistance + A.stealth - A.speed), 0, 50) * (A.mutability)))//stealthy/resistant diseases are less likely to mutate. this means diseases used to farm mutations should be easier to cure. hypothetically.
if(infectee.job == "clown" || infectee.job == "mime" || prob(1))//infecting a clown or mime can evolve l0 symptoms/. they can also appear very rarely
minimum = 0
else
- minimum = CLAMP(A.severity - 1, 1, 7)
- A.Evolve(minimum, CLAMP(A.severity + 4, minimum, 9))
+ minimum = clamp(A.severity - 1, 1, 7)
+ A.Evolve(minimum, clamp(A.severity + 4, minimum, 9))
A.id = GetDiseaseID()
A.keepid = TRUE//this is really janky, but basically mutated diseases count as the original disease
//if you want to evolve a higher level symptom you need to test and spread a deadly virus among test subjects.
diff --git a/code/datums/diseases/advance/symptoms/alcohol.dm b/code/datums/diseases/advance/symptoms/alcohol.dm
index 2e0e5ebff4f92..31d476d0a7f5f 100644
--- a/code/datums/diseases/advance/symptoms/alcohol.dm
+++ b/code/datums/diseases/advance/symptoms/alcohol.dm
@@ -41,6 +41,6 @@
warningstrings = list("ahyguabngaghabyugbauwf", "You feel sick", "It feels like you drank too much", "You feel like doing something unwise")
else
warningstrings = list("You feel buzzed", "You feel a bit tipsy")
- M.drunkenness = CLAMP(M.drunkenness + target * ((A.stage - 1) * 0.1), M.drunkenness, target)
+ M.drunkenness = clamp(M.drunkenness + target * ((A.stage - 1) * 0.1), M.drunkenness, target)
if(prob(5 * A.stage))
to_chat(M, "[pick(warningstrings)]")
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index d7bf4065ad374..5be972687faf0 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -121,13 +121,13 @@
ADD_TRAIT(M, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT)
if(HAS_TRAIT(M, TRAIT_DEATHCOMA))
return power
- else if(M.IsUnconscious() || M.stat == UNCONSCIOUS)
+ if(M.IsSleeping())
+ return power * 0.25 //Voluntary unconsciousness yields lower healing.
+ if(M.stat == UNCONSCIOUS)
return power * 0.9
- else if(M.stat == SOFT_CRIT)
+ if(M.stat == SOFT_CRIT)
return power * 0.5
- else if(M.IsSleeping())
- return power * 0.25
- else if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma)
+ if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma)
to_chat(M, "You feel yourself slip into a deep, regenerative slumber.")
active_coma = TRUE
addtimer(CALLBACK(src, PROC_REF(coma), M), 60)
@@ -137,7 +137,6 @@
M.fakedeath(TRAIT_REGEN_COMA)
else
M.Unconscious(300, TRUE, TRUE)
- M.update_stat()
M.update_mobility()
addtimer(CALLBACK(src, PROC_REF(uncoma), M), 300)
@@ -149,7 +148,6 @@
M.cure_fakedeath(TRAIT_REGEN_COMA)
else
M.SetUnconscious(0)
- M.update_stat()
M.update_mobility()
/datum/symptom/heal/coma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
@@ -502,7 +500,7 @@ im not even gonna bother with these for the following symptoms. typed em out, co
var/mob/living/carbon/M = A.affected_mob
ownermind = M.mind
if(!A.carrier && !A.dormant)
- sizemult = CLAMP((0.5 + A.stage_rate / 10), 1.1, 1.5)
+ sizemult = clamp((0.5 + A.stage_rate / 10), 1.1, 1.5)
M.resize = sizemult
M.update_transform()
@@ -759,7 +757,7 @@ im not even gonna bother with these for the following symptoms. typed em out, co
var/excess = max(((min(amt, C.blood_volume) - (BLOOD_VOLUME_NORMAL - H.blood_volume)) / 4), 0)
H.blood_volume = min(H.blood_volume + min(amt, C.blood_volume), BLOOD_VOLUME_NORMAL)
C.blood_volume = max(C.blood_volume - amt, 0)
- gainedpoints = CLAMP(excess, 0, maxbloodpoints - bloodpoints)
+ gainedpoints = clamp(excess, 0, maxbloodpoints - bloodpoints)
C.visible_message("Blood flows from [C.name]'s wounds into [H.name]!", "Blood flows from your wounds into [H.name]!")
playsound(C.loc, 'sound/magic/exit_blood.ogg', 25, 1)
return gainedpoints
@@ -793,7 +791,7 @@ im not even gonna bother with these for the following symptoms. typed em out, co
if(gainedpoints)
playsound(M.loc, 'sound/magic/exit_blood.ogg', 50, 1)
M.visible_message("Blood flows from the floor into [M.name]!", "You consume the errant blood")
- return CLAMP(gainedpoints, 0, maxbloodpoints - bloodpoints)
+ return clamp(gainedpoints, 0, maxbloodpoints - bloodpoints)
if(ishuman(M) && aggression)//finally, attack mobs touching the host.
var/mob/living/carbon/human/H = M
for(var/mob/living/carbon/human/C in ohearers(1, H))
@@ -805,9 +803,9 @@ im not even gonna bother with these for the following symptoms. typed em out, co
var/excess = max(((min(amt, C.blood_volume) - (BLOOD_VOLUME_NORMAL - H.blood_volume)) / 4 * power), 0)
H.blood_volume = min(H.blood_volume + min(amt, C.blood_volume), BLOOD_VOLUME_NORMAL)
C.blood_volume = max(C.blood_volume - amt, 0)
- gainedpoints += CLAMP(excess, 0, maxbloodpoints - bloodpoints)
+ gainedpoints += clamp(excess, 0, maxbloodpoints - bloodpoints)
C.visible_message("Blood flows from [C.name]'s wounds into [H.name]!", "Blood flows from your wounds into [H.name]!")
- return CLAMP(gainedpoints, 0, maxbloodpoints - bloodpoints)
+ return clamp(gainedpoints, 0, maxbloodpoints - bloodpoints)
/datum/symptom/parasite
diff --git a/code/datums/diseases/advance/symptoms/shedding.dm b/code/datums/diseases/advance/symptoms/shedding.dm
index 7c241301a017f..1adfc9eb453e6 100644
--- a/code/datums/diseases/advance/symptoms/shedding.dm
+++ b/code/datums/diseases/advance/symptoms/shedding.dm
@@ -33,6 +33,9 @@ BONUS
return
var/mob/living/M = A.affected_mob
+
+ if(HAS_TRAIT(M, TRAIT_NOHAIRLOSS))
+ return
if(prob(base_message_chance))
to_chat(M, "[pick("Your scalp itches.", "Your skin feels flaky.")]")
if(ishuman(M))
diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm
index 2be16dd8c49cf..742c6e2316bb0 100644
--- a/code/datums/diseases/gbs.dm
+++ b/code/datums/diseases/gbs.dm
@@ -26,6 +26,7 @@
if(4)
to_chat(affected_mob, "Your body feels as if it's trying to rip itself apart!")
if(prob(50))
+ affected_mob.investigate_log("has been gibbed by GBS.", INVESTIGATE_DEATHS)
affected_mob.gib()
else
return
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 9a8da6bb3e2f4..fba41e9067f1b 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -665,11 +665,14 @@
else
switch(rand(0,5))
if(0)
+ investigate_log("has been gibbed by DNA instability.", INVESTIGATE_DEATHS)
gib()
if(1)
+ investigate_log("has been dusted by DNA instability.", INVESTIGATE_DEATHS)
dust()
if(2)
+ investigate_log("has been killed by DNA instability.", INVESTIGATE_DEATHS)
death()
petrify(INFINITY)
if(3)
@@ -678,6 +681,7 @@
if(BP)
BP.dismember()
else
+ investigate_log("has been gibbed by DNA instability.", INVESTIGATE_DEATHS)
gib()
else
set_species(/datum/species/dullahan)
diff --git a/code/datums/elements/empprotection.dm b/code/datums/elements/empprotection.dm
new file mode 100644
index 0000000000000..8d5d798c3cb89
--- /dev/null
+++ b/code/datums/elements/empprotection.dm
@@ -0,0 +1,20 @@
+/datum/element/empprotection
+ element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE
+ id_arg_index = 2
+ var/flags = NONE
+
+/datum/element/empprotection/Attach(datum/target, _flags)
+ . = ..()
+ if(. == ELEMENT_INCOMPATIBLE || !isatom(target))
+ return ELEMENT_INCOMPATIBLE
+ flags = _flags
+ RegisterSignal(target, COMSIG_ATOM_EMP_ACT, PROC_REF(getEmpFlags))
+
+/datum/element/empprotection/Detach(atom/target)
+ UnregisterSignal(target, COMSIG_ATOM_EMP_ACT)
+ return ..()
+
+/datum/element/empprotection/proc/getEmpFlags(datum/source, severity)
+ SIGNAL_HANDLER
+
+ return flags
diff --git a/code/datums/elements/mirage_border.dm b/code/datums/elements/mirage_border.dm
index c3b3eecc3e347..c23f2c6110ba0 100644
--- a/code/datums/elements/mirage_border.dm
+++ b/code/datums/elements/mirage_border.dm
@@ -20,9 +20,9 @@
if(istext(range))
range = max(getviewsize(range)[1], getviewsize(range)[2])
- var/z = CLAMP(target_turf.z, 1, world.maxz)
- var/turf/southwest = locate(CLAMP(x - (direction & WEST ? range : 0), 1, world.maxx), CLAMP(y - (direction & SOUTH ? range : 0), 1, world.maxy), z)
- var/turf/northeast = locate(CLAMP(x + (direction & EAST ? range : 0), 1, world.maxx), CLAMP(y + (direction & NORTH ? range : 0), 1, world.maxy), z)
+ var/z = clamp(target_turf.z, 1, world.maxz)
+ var/turf/southwest = locate(clamp(x - (direction & WEST ? range : 0), 1, world.maxx), clamp(y - (direction & SOUTH ? range : 0), 1, world.maxy), z)
+ var/turf/northeast = locate(clamp(x + (direction & EAST ? range : 0), 1, world.maxx), clamp(y + (direction & NORTH ? range : 0), 1, world.maxy), z)
holder.vis_contents += block(southwest, northeast)
if(direction & SOUTH)
holder.pixel_y -= world.icon_size * range
diff --git a/code/datums/elements/update_icon_blocker.dm b/code/datums/elements/update_icon_blocker.dm
new file mode 100644
index 0000000000000..674b314ec9c15
--- /dev/null
+++ b/code/datums/elements/update_icon_blocker.dm
@@ -0,0 +1,12 @@
+//Prevents calling anything in update_icon() like update_icon_state() or update_overlays()
+
+/datum/element/update_icon_blocker/Attach(datum/target)
+ . = ..()
+ if(!istype(target, /atom))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON, PROC_REF(block_update_icon))
+
+/datum/element/update_icon_blocker/proc/block_update_icon()
+ SIGNAL_HANDLER
+
+ return COMSIG_ATOM_NO_UPDATE_ICON_STATE | COMSIG_ATOM_NO_UPDATE_OVERLAYS
diff --git a/code/datums/elements/update_icon_updates_onmob.dm b/code/datums/elements/update_icon_updates_onmob.dm
new file mode 100644
index 0000000000000..0ec9a472e64f6
--- /dev/null
+++ b/code/datums/elements/update_icon_updates_onmob.dm
@@ -0,0 +1,18 @@
+//update_icon() may change the onmob icons
+//Very good name, I know
+
+/datum/element/update_icon_updates_onmob/Attach(datum/target)
+ . = ..()
+ if(!istype(target, /obj/item))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, PROC_REF(update_onmob))
+
+/datum/element/update_icon_updates_onmob/proc/update_onmob(obj/item/target)
+ SIGNAL_HANDLER
+
+ if(ismob(target.loc))
+ var/mob/M = target.loc
+ if(M.is_holding(target))
+ M.update_inv_hands()
+ else
+ M.regenerate_icons() //yeah this is shit, but we don't know which update_foo() proc to call instead so we'll call them all
diff --git a/code/datums/helper_datums/stack_end_detector.dm b/code/datums/helper_datums/stack_end_detector.dm
new file mode 100644
index 0000000000000..fd700ac8f21ae
--- /dev/null
+++ b/code/datums/helper_datums/stack_end_detector.dm
@@ -0,0 +1,31 @@
+/**
+ Stack End Detector.
+ Can detect if a given code stack has exited, used by the mc for stack overflow detection.
+ **/
+/datum/stack_end_detector
+ var/datum/weakref/_WF
+ var/datum/stack_canary/_canary
+
+/datum/stack_end_detector/New()
+ _canary = new()
+ _WF = WEAKREF(_canary)
+
+/** Prime the stack overflow detector.
+ Store the return value of this proc call in a proc level var.
+ Can only be called once.
+**/
+/datum/stack_end_detector/proc/prime_canary()
+ if (!_canary)
+ CRASH("Prime_canary called twice")
+ . = _canary
+ _canary = null
+
+/// Returns true if the stack is still going. Calling before the canary has been primed also returns true
+/datum/stack_end_detector/proc/check()
+ return !!_WF.resolve()
+
+/// Stack canary. Will go away if the stack it was primed by is ended by byond for return or stack overflow reasons.
+/datum/stack_canary
+
+/// empty proc to avoid warnings about unused variables. Call this proc on your canary in the stack it's watching.
+/datum/stack_canary/proc/use_variable()
diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm
index 6236dd249ff1a..643845af95e97 100644
--- a/code/datums/martial/krav_maga.dm
+++ b/code/datums/martial/krav_maga.dm
@@ -105,7 +105,7 @@
"[A] slams your chest! You can't breathe!", null, COMBAT_MESSAGE_RANGE)
playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1)
if(D.losebreath <= 10)
- D.losebreath = CLAMP(D.losebreath + 5, 0, 10)
+ D.losebreath = clamp(D.losebreath + 5, 0, 10)
D.adjustOxyLoss(10)
log_combat(A, D, "quickchoked")
return 1
@@ -116,7 +116,7 @@
playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1)
D.apply_damage(5, A.dna.species.attack_type)
if(D.silent <= 10)
- D.silent = CLAMP(D.silent + 10, 0, 10)
+ D.silent = clamp(D.silent + 10, 0, 10)
log_combat(A, D, "neck chopped")
return 1
diff --git a/code/datums/martial/tribal_claw.dm b/code/datums/martial/tribal_claw.dm
index d59e853ed14c8..d7e6dc2b951bd 100644
--- a/code/datums/martial/tribal_claw.dm
+++ b/code/datums/martial/tribal_claw.dm
@@ -61,7 +61,7 @@ Deals 15 brute to head(reduced by armor) and causes a rapid bleeding effect simi
D.visible_message("[A] cuts [D]'s jugular vein with their claws!", \
"[A] cuts your jugular vein!")
D.apply_damage(15, BRUTE, BODY_ZONE_HEAD, def_check)
- D.bleed_rate = CLAMP(D.bleed_rate + 20, 0, 30)
+ D.bleed_rate = clamp(D.bleed_rate + 20, 0, 30)
D.apply_status_effect(/datum/status_effect/neck_slice)
A.do_attack_animation(D, ATTACK_EFFECT_CLAW)
playsound(get_turf(D), 'sound/weapons/slash.ogg', 50, 1, -1)
@@ -77,7 +77,7 @@ Deals 15 brute to head(reduced by armor) and causes a rapid bleeding effect simi
D.Knockdown(5) //Without knockdown target still stands up while T3 grabbed.
A.setGrabState(GRAB_NECK)
if(D.silent <= 10)
- D.silent = CLAMP(D.silent + 10, 0, 10)
+ D.silent = clamp(D.silent + 10, 0, 10)
/datum/martial_art/tribal_claw/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 6f949de012d3c..a5f2331ff4383 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -353,6 +353,8 @@
var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key, TRUE, FALSE, gamemode, telecrystals)
if(src.has_antag_datum(/datum/antagonist/incursion))
U.uplink_flag = UPLINK_INCURSION
+ if(src.has_antag_datum(/datum/antagonist/traitor/excommunicate))
+ U.uplink_flag = UPLINK_EXCOMMUNICATE
if(!U)
CRASH("Uplink creation failed.")
U.setup_unlock_code()
diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm
index 0f90293d9a941..f0a253f66fde0 100644
--- a/code/datums/mutations.dm
+++ b/code/datums/mutations.dm
@@ -5,6 +5,8 @@
var/quality
var/static/list/visual_indicators = list()
var/obj/effect/proc_holder/spell/power
+ /// A list of traits to apply to the user whenever this mutation is active.
+ var/list/traits
var/layer_used = MUTATIONS_LAYER //which mutation layer to use
var/list/species_allowed = list() //to restrict mutation to only certain species
var/list/mobtypes_allowed = list() //to restrict mutation to only certain mobs
@@ -46,9 +48,11 @@
timed = TRUE
if(copymut && istype(copymut, /datum/mutation))
copy_mutation(copymut)
+ if(traits && !islist(traits))
+ traits = list(traits)
/datum/mutation/proc/on_acquiring(mob/living/carbon/C)
- if(!C || !istype(C) || C.stat == DEAD || !C.has_dna() || (src in C.dna.mutations))
+ if(!istype(C) || C.stat == DEAD || !C.has_dna() || (src in C.dna.mutations))
return TRUE
if(length(mobtypes_allowed) && !mobtypes_allowed.Find(C.type))
return TRUE
@@ -78,6 +82,8 @@
if(!modified && can_chromosome == CHROMOSOME_USED)
addtimer(CALLBACK(src, PROC_REF(modify), 5)) //gonna want children calling ..() to run first
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
+ for(var/trait in traits)
+ ADD_TRAIT(C, trait, "[type]")
/datum/mutation/proc/get_visual_indicator()
return
@@ -96,7 +102,7 @@
return
/datum/mutation/proc/on_losing(mob/living/carbon/owner)
- if(owner && istype(owner) && (owner.dna.mutations.Remove(src)))
+ if(istype(owner) && (owner.dna.mutations.Remove(src)))
if(length(visual_indicators))
var/list/mut_overlay = list()
if(owner.overlays_standing[layer_used])
@@ -109,8 +115,9 @@
owner.RemoveSpell(power)
qdel(src)
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
- return 0
- return 1
+ REMOVE_TRAITS_IN(owner, "[type]")
+ return FALSE
+ return TRUE
/mob/living/carbon/proc/update_mutations_overlay()
if(!has_dna())
@@ -143,7 +150,7 @@
modified = TRUE
/datum/mutation/proc/copy_mutation(datum/mutation/HM)
- if(!HM)
+ if(!istype(HM))
return
chromosome_name = HM.chromosome_name
stabilizer_coeff = HM.stabilizer_coeff
@@ -173,7 +180,10 @@
if(!ispath(power) || !owner)
return FALSE
- power = new power()
+ if(ispath(power, /obj/effect/proc_holder/spell/targeted/touch/mutation))
+ power = new power(null, src)
+ else
+ power = new power()
power.action_background_icon_state = "bg_tech_blue_on"
power.panel = "Genetic"
owner.AddSpell(power)
diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm
index 43194c541e0e2..e74bca0a8e492 100644
--- a/code/datums/mutations/actions.dm
+++ b/code/datums/mutations/actions.dm
@@ -5,8 +5,6 @@
difficulty = 12
power = /obj/effect/proc_holder/spell/targeted/telepathy
instability = 10
- energy_coeff = 1
-
/datum/mutation/olfaction
name = "Transcendent Olfaction"
@@ -15,13 +13,12 @@
difficulty = 12
power = /obj/effect/proc_holder/spell/targeted/olfaction
instability = 30
- synchronizer_coeff = 1
- var/reek = 200
+ energy_coeff = 1
/obj/effect/proc_holder/spell/targeted/olfaction
name = "Remember the Scent"
desc = "Get a scent off of the item you're currently holding to track it. With an empty hand, you'll track the scent you've remembered."
- charge_max = 100
+ charge_max = 10 SECONDS
clothes_req = FALSE
range = -1
include_user = TRUE
@@ -35,13 +32,13 @@
var/old_target = tracking_target
possible = list()
var/list/prints = sniffed.return_fingerprints()
- for(var/mob/living/carbon/C in GLOB.carbon_list)
- if(prints[rustg_hash_string(RUSTG_HASH_MD5, C.dna.uni_identity)])
- possible |= C
+ for(var/mob/living/carbon/potential_target in GLOB.carbon_list)
+ if(prints[rustg_hash_string(RUSTG_HASH_MD5, potential_target.dna.uni_identity)])
+ possible |= potential_target
if(!length(possible))
- to_chat(user,"Despite your best efforts, there are no scents to be found on [sniffed]...")
+ to_chat(user, "Despite your best efforts, there are no scents to be found on [sniffed]...")
return
- tracking_target = input(user, "Choose a scent to remember.", "Scent Tracking") as null|anything in sort_names(possible)
+ tracking_target = tgui_input_list(user, "Choose a scent to remember.", "Scent Tracking", sort_names(possible))
if(!tracking_target)
if(!old_target)
to_chat(user,"You decide against remembering any scents. Instead, you notice your own nose in your peripheral vision. This goes on to remind you of that one time you started breathing manually and couldn't stop. What an awful day that was.")
@@ -49,7 +46,7 @@
tracking_target = old_target
on_the_trail(user)
return
- to_chat(user,"You pick up the scent of [tracking_target]. The hunt begins.")
+ to_chat(user,"You pick up the scent of [tracking_target]. The hunt begins.")
on_the_trail(user)
return
@@ -74,7 +71,7 @@
return
var/direction_text = "[dir2text(get_dir(usr, tracking_target))]"
if(direction_text)
- to_chat(user,"You consider [tracking_target]'s scent. The trail leads [direction_text].")
+ to_chat(user,"You consider [tracking_target]'s scent. The trail leads [direction_text].")
/datum/mutation/firebreath
name = "Fire Breath"
@@ -91,8 +88,8 @@
/datum/mutation/firebreath/modify()
..()
if(power)
- var/obj/effect/proc_holder/spell/aimed/firebreath/S = power
- S.strength = GET_MUTATION_POWER(src)
+ var/obj/effect/proc_holder/spell/aimed/firebreath/firebreath = power
+ firebreath.strength = GET_MUTATION_POWER(src)
/obj/effect/proc_holder/spell/aimed/firebreath
name = "Fire Breath"
@@ -100,7 +97,7 @@
school = "evocation"
invocation = ""
invocation_type = INVOCATION_NONE
- charge_max = 600
+ charge_max = 1 MINUTES
clothes_req = FALSE
range = 20
projectile_type = /obj/projectile/magic/fireball/firebreath
@@ -113,27 +110,27 @@
/obj/effect/proc_holder/spell/aimed/firebreath/before_cast(list/targets)
. = ..()
- if(iscarbon(usr))
- var/mob/living/carbon/C = usr
- if(C.is_mouth_covered())
- C.adjust_fire_stacks(2)
- C.IgniteMob()
- to_chat(C,"Something in front of your mouth caught fire!")
- return FALSE
+ var/mob/living/carbon/user = usr
+ if(!istype(user))
+ return
+ if(user.is_mouth_covered())
+ user.adjust_fire_stacks(2)
+ user.IgniteMob()
+ to_chat(user, "Something in front of your mouth caught fire!")
+ return FALSE
-/obj/effect/proc_holder/spell/aimed/firebreath/ready_projectile(obj/projectile/P, atom/target, mob/user, iteration)
- if(!istype(P, /obj/projectile/magic/fireball))
+/obj/effect/proc_holder/spell/aimed/firebreath/ready_projectile(obj/projectile/magic/fireball/fireball, atom/target, mob/user, iteration)
+ if(!istype(fireball))
return
- var/obj/projectile/magic/fireball/F = P
- F.exp_light = strength-1
- F.exp_fire += strength
+ fireball.exp_light = strength - 1
+ fireball.exp_fire += strength
/obj/projectile/magic/fireball/firebreath
name = "fire breath"
exp_heavy = 0
exp_light = 0
exp_flash = 0
- exp_fire= 4
+ exp_fire = 4
magic = FALSE
/datum/mutation/void
@@ -148,7 +145,7 @@
/datum/mutation/void/on_life()
if(!isturf(owner.loc))
return
- if(prob((0.5+((100-dna.stability)/20))) * GET_MUTATION_SYNCHRONIZER(src)) //very rare, but enough to annoy you hopefully. +0.5 probability for every 10 points lost in stability
+ if(prob((0.5 + ((100 - dna.stability) / 20))) * GET_MUTATION_SYNCHRONIZER(src)) //very rare, but enough to annoy you hopefully. +0.5 probability for every 10 points lost in stability
new /obj/effect/immortality_talisman/void(get_turf(owner), owner)
/obj/effect/proc_holder/spell/self/void
@@ -156,15 +153,15 @@
desc = "A rare genome that attracts odd forces not usually observed. May sometimes pull you in randomly."
school = "evocation"
clothes_req = FALSE
- charge_max = 600
+ charge_max = 1 MINUTES
invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!"
invocation_type = INVOCATION_SHOUT
action_icon_state = "void_magnet"
/obj/effect/proc_holder/spell/self/void/can_cast(mob/user = usr)
- . = ..()
if(!isturf(user.loc))
return FALSE
+ return ..()
/obj/effect/proc_holder/spell/self/void/cast(mob/user = usr)
. = ..()
@@ -176,37 +173,28 @@
quality = POSITIVE
instability = 30
power = /obj/effect/proc_holder/spell/self/self_amputation
-
energy_coeff = 1
- synchronizer_coeff = 1
/obj/effect/proc_holder/spell/self/self_amputation
name = "Drop a limb"
desc = "Concentrate to make a random limb pop right off your body."
clothes_req = FALSE
human_req = FALSE
- charge_max = 100
+ charge_max = 10 SECONDS
action_icon_state = "autotomy"
-/obj/effect/proc_holder/spell/self/self_amputation/cast(mob/user = usr)
- if(!iscarbon(user))
+/obj/effect/proc_holder/spell/self/self_amputation/cast(mob/living/carbon/user = usr)
+ if(!istype(user) || HAS_TRAIT(user, TRAIT_NODISMEMBER))
return
-
- var/mob/living/carbon/C = user
- if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
- return
-
var/list/parts = list()
- for(var/obj/item/bodypart/BP as() in C.bodyparts)
- if(BP.body_part != HEAD && BP.body_part != CHEST)
- if(BP.dismemberable)
- parts += BP
- if(!parts.len)
- to_chat(usr, "You can't shed any more limbs!")
+ for(var/obj/item/bodypart/part as() in user.bodyparts)
+ if(part.body_part != HEAD && part.body_part != CHEST && part.dismemberable)
+ parts += part
+ if(!length(parts))
+ to_chat(user, "You can't shed any more limbs!")
return
-
- var/obj/item/bodypart/BP = pick(parts)
- BP.dismember()
+ var/obj/item/bodypart/yeeted_limb = pick(parts)
+ yeeted_limb.dismember()
/datum/mutation/overload
name = "Overload"
@@ -216,84 +204,30 @@
instability = 30
power = /obj/effect/proc_holder/spell/self/overload
species_allowed = list(SPECIES_ETHEREAL)
+ energy_coeff = 1
+ power_coeff = 1
+
+/datum/mutation/overload/modify()
+ ..()
+ if(power)
+ var/static/max_range = min(getviewsize(world.view)[1], getviewsize(world.view)[2]) - 2
+ var/obj/effect/proc_holder/spell/self/overload/overload = power
+ overload.max_distance = min(max_range, initial(overload.max_distance) * GET_MUTATION_POWER(src))
/obj/effect/proc_holder/spell/self/overload
name = "Overload"
desc = "Concentrate to make your skin energize."
clothes_req = FALSE
human_req = FALSE
- charge_max = 400
+ charge_max = 40 SECONDS
action_icon_state = "blind"
var/max_distance = 4
-/obj/effect/proc_holder/spell/self/overload/cast(mob/user = usr)
+/obj/effect/proc_holder/spell/self/overload/cast(mob/living/carbon/human/user)
if(!isethereal(user))
return
-
var/list/mob/targets = oviewers(max_distance, get_turf(user))
visible_message("[user] emits a blinding light!")
- for(var/mob/living/carbon/C in targets)
- if(C.flash_act(1))
- C.Paralyze(10 + (5*max_distance))
-
-/datum/mutation/overload/modify()
- if(power)
- var/obj/effect/proc_holder/spell/self/overload/S = power
- S.max_distance = 4 * GET_MUTATION_POWER(src)
-
-/datum/mutation/acidooze
- name = "Acidic Hands"
- desc = "Allows an Oozeling to metabolize some of their blood into acid, concentrated on their hands."
- quality = POSITIVE
- locked = TRUE
- instability = 30
- power = /obj/effect/proc_holder/spell/targeted/touch/acidooze
- species_allowed = list(SPECIES_OOZELING)
-
-/obj/effect/proc_holder/spell/targeted/touch/acidooze
- name = "Acidic Hands"
- desc = "Concentrate to make some of your blood become acidic."
- clothes_req = FALSE
- human_req = FALSE
- charge_max = 100
- action_icon_state = "summons"
- var/volume = 10
- hand_path = /obj/item/melee/touch_attack/acidooze
- drawmessage = "You secrete acid into your hand."
- dropmessage = "You let the acid in your hand dissipate."
-
-/obj/item/melee/touch_attack/acidooze
- name = "\improper acidic hand"
- desc = "Keep away from children, paperwork, and children doing paperwork."
- catchphrase = null
- icon = 'icons/effects/blood.dmi'
- var/icon_left = "bloodhand_left"
- var/icon_right = "bloodhand_right"
- icon_state = "bloodhand_left"
- item_state = "fleshtostone"
-
-/obj/item/melee/touch_attack/acidooze/equipped(mob/user, slot)
- . = ..()
- //these are intentionally inverted
- var/i = user.get_held_index_of_item(src)
- if(!(i % 2))
- icon_state = icon_left
- else
- icon_state = icon_right
-
-/obj/item/melee/touch_attack/acidooze/afterattack(atom/target, mob/living/carbon/user, proximity)
- if(!proximity || !isoozeling(user))
- return
- var/mob/living/carbon/C = user
- if(!target || user.incapacitated())
- return FALSE
- if(C.blood_volume < 40)
- to_chat(user, "You don't have enough blood to do that!")
- return FALSE
- if(target.acid_act(50, 15))
- user.visible_message("[user] rubs globs of vile stuff all over [target].")
- C.blood_volume = max(C.blood_volume - 20, 0)
- return ..()
- else
- to_chat(user, "You cannot dissolve this object.")
- return FALSE
+ for(var/mob/living/carbon/target in targets)
+ if(target.flash_act(1))
+ target.Paralyze(10 + (5 * max_distance))
diff --git a/code/datums/mutations/antenna.dm b/code/datums/mutations/antenna.dm
index 23cf729cbae13..bb04b532f32de 100644
--- a/code/datums/mutations/antenna.dm
+++ b/code/datums/mutations/antenna.dm
@@ -6,16 +6,6 @@
difficulty = 8
var/datum/weakref/radio_weakref
-/obj/item/implant/radio/antenna
- name = "internal antenna organ"
- desc = "The internal organ part of the antenna. Science has not yet given it a good name."
- icon = 'icons/obj/radio.dmi'//maybe make a unique sprite later. not important
- icon_state = "walkietalkie"
-
-/obj/item/implant/radio/antenna/Initialize(mapload)
- ..()
- radio.name = "internal antenna"
-
/datum/mutation/antenna/on_acquiring(mob/living/carbon/owner)
if(..())
return
@@ -37,3 +27,13 @@
/datum/mutation/antenna/get_visual_indicator()
return visual_indicators[type][1]
+
+/obj/item/implant/radio/antenna
+ name = "internal antenna organ"
+ desc = "The internal organ part of the antenna. Science has not yet given it a good name."
+ icon = 'icons/obj/radio.dmi'//maybe make a unique sprite later. not important
+ icon_state = "walkietalkie"
+
+/obj/item/implant/radio/antenna/Initialize()
+ . = ..()
+ radio.name = "internal antenna"
diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm
index bc4f6f2ccac15..cde24cbb591d0 100644
--- a/code/datums/mutations/body.dm
+++ b/code/datums/mutations/body.dm
@@ -14,7 +14,7 @@
owner.Unconscious(200 * GET_MUTATION_POWER(src))
owner.Jitter(1000 * GET_MUTATION_POWER(src))
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "epilepsy", /datum/mood_event/epilepsy)
- addtimer(CALLBACK(src, PROC_REF(jitter_less)), 90)
+ addtimer(CALLBACK(src, PROC_REF(jitter_less)), 9 SECONDS)
/datum/mutation/epilepsy/proc/jitter_less()
if(owner)
@@ -105,17 +105,7 @@
name = "Clumsiness"
desc = "A genome that inhibits certain brain functions, causing the holder to appear clumsy. Honk"
quality = MINOR_NEGATIVE
-
-/datum/mutation/clumsy/on_acquiring(mob/living/carbon/owner)
- if(..())
- return
- ADD_TRAIT(owner, TRAIT_CLUMSY, GENETIC_MUTATION)
-
-/datum/mutation/clumsy/on_losing(mob/living/carbon/owner)
- if(..())
- return
- REMOVE_TRAIT(owner, TRAIT_CLUMSY, GENETIC_MUTATION)
-
+ traits = TRAIT_CLUMSY
//Tourettes causes you to randomly stand in place and shout.
/datum/mutation/tourettes
@@ -134,8 +124,8 @@
owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]", forced="tourette's syndrome")
var/x_offset_old = owner.pixel_x
var/y_offset_old = owner.pixel_y
- var/x_offset = owner.pixel_x + rand(-2,2)
- var/y_offset = owner.pixel_y + rand(-1,1)
+ var/x_offset = owner.pixel_x + rand(-2, 2)
+ var/y_offset = owner.pixel_y + rand(-1, 1)
animate(owner, pixel_x = x_offset, pixel_y = y_offset, time = 1)
animate(owner, pixel_x = x_offset_old, pixel_y = y_offset_old, time = 1)
@@ -145,19 +135,13 @@
name = "Deafness"
desc = "The holder of this genome is completely deaf."
quality = NEGATIVE
+ traits = TRAIT_DEAF
/datum/mutation/deaf/on_acquiring(mob/living/carbon/owner)
if(..())
return
- ADD_TRAIT(owner, TRAIT_DEAF, GENETIC_MUTATION)
SEND_SOUND(owner, sound(null))
-/datum/mutation/deaf/on_losing(mob/living/carbon/owner)
- if(..())
- return
- REMOVE_TRAIT(owner, TRAIT_DEAF, GENETIC_MUTATION)
-
-
//Monified turns you into a monkey.
/datum/mutation/race
name = "Monkified"
@@ -174,7 +158,7 @@
. = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE | TR_KEEPAI, FALSE, TRUE)
/datum/mutation/race/on_losing(mob/living/carbon/monkey/owner)
- if(owner && ismonkey(owner) && owner.stat != DEAD && !..())
+ if(istype(owner) && owner.stat != DEAD && !..())
. = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE | TR_KEEPAI, TRUE, original_species)
/datum/mutation/glow
@@ -182,28 +166,26 @@
desc = "You permanently emit a light with a random color and intensity."
quality = POSITIVE
instability = 5
+ power_coeff = 1
+ conflicts = list(ANTIGLOWY)
var/obj/effect/dummy/luminescent_glow/glowth //shamelessly copied from luminescents
var/glow = 2.5
var/range = 2.5
- power_coeff = 1
- conflicts = list(/datum/mutation/glow/anti)
/datum/mutation/glow/on_acquiring(mob/living/carbon/owner)
- . = ..()
- if(.)
+ if(..())
return
glowth = new(owner)
modify()
/datum/mutation/glow/modify()
- if(!glowth)
+ if(QDELETED(glowth))
return
var/power = GET_MUTATION_POWER(src)
glowth.set_light_range_power_color(range * power, glow * power, "#[dna.features["mcolor"]]")
/datum/mutation/glow/on_losing(mob/living/carbon/owner)
- . = ..()
- if(.)
+ if(..())
return
QDEL_NULL(glowth)
@@ -211,7 +193,7 @@
name = "Anti-Glow"
desc = "Your skin seems to attract and absorb nearby light creating 'darkness' around you."
glow = -3.5 //Slightly stronger, since negating light tends to be harder than making it.
- conflicts = list(/datum/mutation/glow)
+ conflicts = list(GLOWY)
locked = TRUE
/datum/mutation/strong
@@ -226,16 +208,7 @@
quality = POSITIVE
difficulty = 16
instability = 25
-
-/datum/mutation/insulated/on_acquiring(mob/living/carbon/owner)
- if(..())
- return
- ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "genetics")
-
-/datum/mutation/insulated/on_losing(mob/living/carbon/owner)
- if(..())
- return
- REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "genetics")
+ traits = TRAIT_SHOCKIMMUNE
/datum/mutation/fire
name = "Fiery Sweat"
@@ -278,13 +251,13 @@
/datum/mutation/badblink/on_life()
if(prob(warpchance))
var/warpmessage = pick(
- "With a sickening 720 degree twist of their back, [owner] vanishes into thin air.",
- "[owner] does some sort of strange backflip into another dimension. It looks pretty painful.",
- "[owner] does a jump to the left, a step to the right, and warps out of reality.",
- "[owner]'s torso starts folding inside out until it vanishes from reality, taking [owner] with it.",
- "One moment, you see [owner]. The next, [owner] is gone.")
+ "With a sickening 720 degree twist of their back, [owner] vanishes into thin air.",
+ "[owner] does some sort of strange backflip into another dimension. It looks pretty painful.",
+ "[owner] does a jump to the left, a step to the right, and warps out of reality.",
+ "[owner]'s torso starts folding inside out until it vanishes from reality, taking [owner] with it.",
+ "One moment, you see [owner]. The next, [owner] is gone.")
owner.visible_message(warpmessage, "You feel a wave of nausea as you fall through reality!")
- var/warpdistance = rand(10,15) * GET_MUTATION_POWER(src)
+ var/warpdistance = rand(10, 15) * GET_MUTATION_POWER(src)
do_teleport(owner, get_turf(owner), warpdistance, channel = TELEPORT_CHANNEL_BLINK)
owner.adjust_disgust(GET_MUTATION_SYNCHRONIZER(src) * (warpchance * warpdistance))
warpchance = 0
@@ -297,17 +270,17 @@
desc = "Subject has acidic chemicals building up underneath their skin. This is often lethal."
quality = NEGATIVE
difficulty = 18//high so it's hard to unlock and use on others
- var/msgcooldown = 0
+ COOLDOWN_DECLARE(message_cooldown)
/datum/mutation/acidflesh/on_life()
if(prob(25))
- if(world.time > msgcooldown)
+ if(COOLDOWN_FINISHED(src, message_cooldown))
to_chat(owner, "Your acid flesh bubbles...")
- msgcooldown = world.time + 200
+ COOLDOWN_START(src, message_cooldown, 20 SECONDS)
if(prob(15))
- owner.acid_act(rand(30,50), 10)
+ owner.acid_act(rand(30, 50), 10)
owner.visible_message("[owner]'s skin bubbles and pops.", "Your bubbling flesh pops! It burns!")
- playsound(owner,'sound/weapons/sear.ogg', 50, 1)
+ playsound(owner, 'sound/weapons/sear.ogg', vol = 50, vary = TRUE)
/datum/mutation/gigantism
name = "Gigantism"//negative version of dwarfism
@@ -351,15 +324,18 @@
desc = "A mutation that disrupts coordination in the legs. It makes standing up after getting knocked down very difficult."
quality = NEGATIVE
difficulty = 16
- var/stun_cooldown = 0
+ COOLDOWN_DECLARE(stun_cooldown)
/datum/mutation/extrastun/on_life()
- if(world.time > stun_cooldown)
- if(owner.AmountKnockdown() || owner.AmountStun())
- owner.SetKnockdown(owner.AmountKnockdown()*2)
- owner.SetStun(owner.AmountStun()*2)
- owner.visible_message("[owner] tries to stand up, but trips!", "You trip over your own feet!")
- stun_cooldown = world.time + 300
+ if(!COOLDOWN_FINISHED(src, stun_cooldown))
+ return
+ var/knockdown = owner.AmountKnockdown()
+ var/stun = owner.AmountStun()
+ if(knockdown || stun)
+ owner.SetKnockdown(knockdown * 2)
+ owner.SetStun(stun * 2)
+ owner.visible_message("[owner] tries to stand up, but trips!", "You trip over your own feet!")
+ COOLDOWN_START(src, stun_cooldown, 30 SECONDS)
/datum/mutation/strongwings
name = "Strengthened Wings"
@@ -368,12 +344,13 @@
locked = TRUE
difficulty = 12
instability = 15
+ power_coeff = 1
species_allowed = list(SPECIES_APID, SPECIES_MOTH)
/datum/mutation/strongwings/on_acquiring()
if(..())
return
- var/obj/item/organ/wings/wings = locate(/obj/item/organ/wings) in owner.internal_organs
+ var/obj/item/organ/wings/wings = owner.getorganslot(ORGAN_SLOT_WINGS)
if(!wings)
to_chat(owner, "You don't have wings to strengthen!")
return
@@ -383,7 +360,7 @@
moth_wings.Refresh(owner)
else if(istype(wings, /obj/item/organ/wings/bee))
var/obj/item/organ/wings/bee/bee_wings = wings
- bee_wings.jumpdist += (6 * GET_MUTATION_POWER(src)) - 3
+ bee_wings.jumpdist = initial(bee_wings.jumpdist) + (6 * GET_MUTATION_POWER(src)) - 3
else
to_chat(owner, "Those wings are incompatible with the mutation!")
return
@@ -392,7 +369,7 @@
/datum/mutation/strongwings/on_losing()
if(..())
return
- var/obj/item/organ/wings/wings = locate(/obj/item/organ/wings) in owner.internal_organs
+ var/obj/item/organ/wings/wings = owner.getorganslot(ORGAN_SLOT_WINGS)
if(!wings)
return
if(istype(wings, /obj/item/organ/wings/moth))
@@ -402,9 +379,14 @@
to_chat(owner, "Your wings feel weak.")
else if(istype(wings, /obj/item/organ/wings/bee))
var/obj/item/organ/wings/bee/bee_wings = wings
- bee_wings.jumpdist -= (6 * GET_MUTATION_POWER(src)) - 3
+ bee_wings.jumpdist = initial(bee_wings.jumpdist)
to_chat(owner, "Your wings feel weak.")
+/datum/mutation/strongwings/modify()
+ ..()
+ var/obj/item/organ/wings/bee/bee_wings = owner.getorganslot(ORGAN_SLOT_WINGS)
+ if(istype(bee_wings))
+ bee_wings.jumpdist = initial(bee_wings.jumpdist) + (6 * GET_MUTATION_POWER(src)) - 3
/datum/mutation/catclaws
name = "Cat Claws"
desc = "Subject's hands grow sharpened claws."
@@ -412,22 +394,32 @@
locked = TRUE
difficulty = 12
instability = 25
+ power_coeff = 1
species_allowed = list(SPECIES_FELINID)
var/added_damage = 6
/datum/mutation/catclaws/on_acquiring()
if(..())
return
- added_damage = min(17, 6 * GET_MUTATION_POWER(src) + owner.dna.species.punchdamage)
- added_damage -= owner.dna.species.punchdamage
+ added_damage = min(17, initial(added_damage) * GET_MUTATION_POWER(src) + owner.dna.species.punchdamage) - owner.dna.species.punchdamage
owner.dna.species.punchdamage += added_damage
- to_chat(owner, "Claws extend from your fingertips.")
owner.dna.species.attack_verb = "slash"
+ owner.dna.species.attack_sound = 'sound/weapons/slash.ogg'
+ owner.dna.species.miss_sound = 'sound/weapons/slashmiss.ogg'
+ to_chat(owner, "Claws extend from your fingertips.")
/datum/mutation/catclaws/on_losing()
if(..())
return
- owner.dna.species.punchdamage -= added_damage
to_chat(owner, " Your claws retract into your hand.")
+ owner.dna.species.punchdamage -= added_damage
owner.dna.species.attack_verb = initial(owner.dna.species.attack_verb)
-
+ owner.dna.species.attack_sound = initial(owner.dna.species.attack_sound)
+ owner.dna.species.miss_sound = initial(owner.dna.species.miss_sound)
+
+/datum/mutation/catclaws/modify()
+ ..()
+ if(added_damage)
+ owner.dna.species.punchdamage -= added_damage
+ added_damage = min(17, initial(added_damage) * GET_MUTATION_POWER(src) + owner.dna.species.punchdamage) - owner.dna.species.punchdamage
+ owner.dna.species.punchdamage += added_damage
diff --git a/code/datums/mutations/chameleon.dm b/code/datums/mutations/chameleon.dm
index 7c78011ee9337..9c9e06915347c 100644
--- a/code/datums/mutations/chameleon.dm
+++ b/code/datums/mutations/chameleon.dm
@@ -5,6 +5,8 @@
quality = POSITIVE
difficulty = 16
instability = 25
+ power_coeff = 1
+ /// How much the user's alpha is reduced every life tick they are not moving.
var/effect_speed = 25
/datum/mutation/chameleon/on_acquiring(mob/living/carbon/owner)
@@ -12,6 +14,11 @@
return
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
+/datum/mutation/chameleon/on_losing(mob/living/carbon/owner)
+ if(..())
+ return
+ owner.alpha = 255
+
/datum/mutation/chameleon/on_life()
owner.alpha = max(0, owner.alpha - effect_speed)
@@ -21,9 +28,7 @@
/datum/mutation/chameleon/on_attack_hand(atom/target, proximity)
if(proximity) //stops tk from breaking chameleon
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
- return
-/datum/mutation/chameleon/on_losing(mob/living/carbon/owner)
- if(..())
- return
- owner.alpha = 255
+/datum/mutation/chameleon/modify()
+ ..()
+ effect_speed = round(initial(effect_speed) * GET_MUTATION_POWER(src))
diff --git a/code/datums/mutations/cluwne.dm b/code/datums/mutations/cluwne.dm
index 437ad8b68e163..318e5e63db173 100644
--- a/code/datums/mutations/cluwne.dm
+++ b/code/datums/mutations/cluwne.dm
@@ -11,7 +11,7 @@
owner.dna.add_mutation(EPILEPSY)
owner.setOrganLoss(ORGAN_SLOT_BRAIN, 199)
- playsound(owner.loc, 'sound/misc/bikehorn_creepy.ogg', 50, 1)
+ playsound(owner.loc, 'sound/misc/bikehorn_creepy.ogg', vol = 50, vary = TRUE)
owner.equip_to_slot_or_del(new /obj/item/storage/backpack/clown(owner), ITEM_SLOT_BACK) // this is purely for cosmetic purposes incase they aren't wearing anything in that slot
if(!istype(owner.wear_mask, /obj/item/clothing/mask/cluwne))
if(!owner.doUnEquip(owner.wear_mask))
diff --git a/code/datums/mutations/cold.dm b/code/datums/mutations/cold.dm
index f46d8df38cc78..be012a988cce0 100644
--- a/code/datums/mutations/cold.dm
+++ b/code/datums/mutations/cold.dm
@@ -4,15 +4,14 @@
quality = POSITIVE
instability = 10
difficulty = 10
- synchronizer_coeff = 1
+ energy_coeff = 1
power = /obj/effect/proc_holder/spell/targeted/conjure_item/snow
/obj/effect/proc_holder/spell/targeted/conjure_item/snow
name = "Create Snow"
desc = "Concentrates cryokinetic forces to create snow, useful for snow-like construction."
item_type = /obj/item/stack/sheet/snow
-
- charge_max = 50
+ charge_max = 5 SECONDS
delete_old = FALSE
action_icon_state = "snow"
@@ -22,7 +21,7 @@
quality = POSITIVE
instability = 10
difficulty = 10
- synchronizer_coeff = 1
+ energy_coeff = 1
locked = TRUE
power = /obj/effect/proc_holder/spell/targeted/conjure_item/wax
@@ -30,7 +29,7 @@
name = "Secrete Wax"
desc = "Concentrate to spit out some wax, useful for bee-themed construction."
item_type = /obj/item/stack/sheet/wax
- charge_max = 50
+ charge_max = 5 SECONDS
delete_old = FALSE
action_icon_state = "honey"
@@ -40,14 +39,21 @@
quality = POSITIVE //upsides and downsides
instability = 20
difficulty = 12
- synchronizer_coeff = 1
+ energy_coeff = 1
+ power_coeff = 1
power = /obj/effect/proc_holder/spell/aimed/cryo
+/datum/mutation/cryokinesis/modify()
+ ..()
+ if(power)
+ var/obj/effect/proc_holder/spell/aimed/cryo/cryobeam = power
+ cryobeam.power = GET_MUTATION_POWER(src)
+
/obj/effect/proc_holder/spell/aimed/cryo
name = "Cryobeam"
desc = "This power fires a frozen bolt at a target."
- charge_max = 150
- cooldown_min = 150
+ charge_max = 15 SECONDS
+ cooldown_min = 15 SECONDS
clothes_req = FALSE
range = 3
projectile_type = /obj/projectile/temp/cryo
@@ -56,4 +62,9 @@
active_msg = "You focus your cryokinesis!"
deactive_msg = "You relax."
active = FALSE
+ var/power = 1
+/obj/effect/proc_holder/spell/aimed/cryo/ready_projectile(obj/projectile/temp/cryo/cryobeam, atom/target, mob/user, iteration)
+ if(!istype(cryobeam))
+ return
+ cryobeam.temperature *= power
diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm
index 5d6679d521c3c..96fe31b2ba3ad 100644
--- a/code/datums/mutations/hulk.dm
+++ b/code/datums/mutations/hulk.dm
@@ -10,16 +10,18 @@
health_req = 25
instability = 40
locked = TRUE
+ traits = list(
+ TRAIT_STUNIMMUNE,
+ TRAIT_PUSHIMMUNE,
+ TRAIT_CONFUSEIMMUNE,
+ TRAIT_IGNOREDAMAGESLOWDOWN,
+ TRAIT_NOSTAMCRIT,
+ TRAIT_NOLIMBDISABLE
+ )
/datum/mutation/hulk/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- ADD_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK)
- ADD_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK)
- ADD_TRAIT(owner, TRAIT_CONFUSEIMMUNE, TRAIT_HULK)
- ADD_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_HULK)
- ADD_TRAIT(owner, TRAIT_NOSTAMCRIT, TRAIT_HULK)
- ADD_TRAIT(owner, TRAIT_NOLIMBDISABLE, TRAIT_HULK)
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "hulk", /datum/mood_event/hulk)
RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech))
owner.update_body_parts()
@@ -36,12 +38,6 @@
/datum/mutation/hulk/on_losing(mob/living/carbon/human/owner)
if(..())
return
- REMOVE_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK)
- REMOVE_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK)
- REMOVE_TRAIT(owner, TRAIT_CONFUSEIMMUNE, TRAIT_HULK)
- REMOVE_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_HULK)
- REMOVE_TRAIT(owner, TRAIT_NOSTAMCRIT, TRAIT_HULK)
- REMOVE_TRAIT(owner, TRAIT_NOLIMBDISABLE, TRAIT_HULK)
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "hulk")
owner.update_body_parts()
UnregisterSignal(owner, COMSIG_MOB_SAY)
diff --git a/code/datums/mutations/radioactive.dm b/code/datums/mutations/radioactive.dm
index 03d89f6d763b5..2dd8630e6710e 100644
--- a/code/datums/mutations/radioactive.dm
+++ b/code/datums/mutations/radioactive.dm
@@ -6,14 +6,13 @@
difficulty = 8
power_coeff = 1
-
-/datum/mutation/radioactive/on_life()
- radiation_pulse(owner, 20 * GET_MUTATION_POWER(src))
-
/datum/mutation/radioactive/New(class_ = MUT_OTHER, timer, datum/mutation/copymut)
..()
if(!(type in visual_indicators))
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "radiation", -MUTATIONS_LAYER))
+/datum/mutation/radioactive/on_life()
+ radiation_pulse(owner, 20 * GET_MUTATION_POWER(src))
+
/datum/mutation/radioactive/get_visual_indicator()
return visual_indicators[type][1]
diff --git a/code/datums/mutations/sight.dm b/code/datums/mutations/sight.dm
index f41646bc08ae1..9ca7f2c107d85 100644
--- a/code/datums/mutations/sight.dm
+++ b/code/datums/mutations/sight.dm
@@ -39,19 +39,16 @@
difficulty = 18
instability = 25
locked = TRUE
- var/visionflag = TRAIT_THERMAL_VISION
+ traits = TRAIT_THERMAL_VISION
/datum/mutation/thermal/on_acquiring(mob/living/carbon/owner)
if(..())
return
-
- ADD_TRAIT(owner, visionflag, GENETIC_MUTATION)
owner.update_sight()
/datum/mutation/thermal/on_losing(mob/living/carbon/owner)
if(..())
return
- REMOVE_TRAIT(owner, visionflag, GENETIC_MUTATION)
owner.update_sight()
//X-ray Vision lets you see through walls.
@@ -60,7 +57,7 @@
desc = "A strange mutation that allows the user to see between the spaces of walls." //actual x-ray would mean you'd constantly be blasting rads, wich might be fun for later //hmb
instability = 35
locked = TRUE
- visionflag = TRAIT_XRAY_VISION
+ traits = TRAIT_XRAY_VISION
//Laser Eyes lets you shoot lasers from your eyes!
/datum/mutation/laser_eyes
diff --git a/code/datums/mutations/space_adaptation.dm b/code/datums/mutations/space_adaptation.dm
index e5d294e6925b1..837c0235c6ada 100644
--- a/code/datums/mutations/space_adaptation.dm
+++ b/code/datums/mutations/space_adaptation.dm
@@ -5,6 +5,7 @@
quality = POSITIVE
difficulty = 16
instability = 30
+ traits = list(TRAIT_RESISTCOLD, TRAIT_RESISTLOWPRESSURE)
/datum/mutation/space_adaptation/New(class_ = MUT_OTHER, timer, datum/mutation/copymut)
..()
@@ -13,16 +14,3 @@
/datum/mutation/space_adaptation/get_visual_indicator()
return visual_indicators[type][1]
-
-/datum/mutation/space_adaptation/on_acquiring(mob/living/carbon/owner)
- if(..())
- return
- ADD_TRAIT(owner, TRAIT_RESISTCOLD, "space_adaptation")
- ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "space_adaptation")
-
-/datum/mutation/space_adaptation/on_losing(mob/living/carbon/owner)
- if(..())
- return
- REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, "space_adaptation")
- REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "space_adaptation")
-
diff --git a/code/datums/mutations/speech.dm b/code/datums/mutations/speech.dm
index dfce6b4e4681f..2e55f493b662b 100644
--- a/code/datums/mutations/speech.dm
+++ b/code/datums/mutations/speech.dm
@@ -10,7 +10,6 @@
if(prob(10))
owner.stuttering = max(10, owner.stuttering)
-
/datum/mutation/wacky
name = "Wacky"
desc = "Effects not tested..."
@@ -35,17 +34,7 @@
name = "Mute"
desc = "Inherited mutation that completely inhibits the vocal section of the brain."
quality = NEGATIVE
-
-/datum/mutation/mute/on_acquiring(mob/living/carbon/owner)
- if(..())
- return
- ADD_TRAIT(owner, TRAIT_MUTE, GENETIC_MUTATION)
-
-/datum/mutation/mute/on_losing(mob/living/carbon/owner)
- if(..())
- return
- REMOVE_TRAIT(owner, TRAIT_MUTE, GENETIC_MUTATION)
-
+ traits = TRAIT_MUTE
/datum/mutation/smile
name = "Smile"
@@ -116,16 +105,7 @@
name = "Unintelligible"
desc = "Hereditary mutation that partially inhibits the vocal center of the brain, resulting in a severe speech disorder."
quality = NEGATIVE
-
-/datum/mutation/unintelligible/on_acquiring(mob/living/carbon/owner)
- if(..())
- return
- ADD_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, GENETIC_MUTATION)
-
-/datum/mutation/unintelligible/on_losing(mob/living/carbon/owner)
- if(..())
- return
- REMOVE_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, GENETIC_MUTATION)
+ traits = TRAIT_UNINTELLIGIBLE_SPEECH
/datum/mutation/swedish
name = "Swedish"
diff --git a/code/datums/mutations/touch.dm b/code/datums/mutations/touch.dm
index de3d60e650530..e7ae13357265e 100644
--- a/code/datums/mutations/touch.dm
+++ b/code/datums/mutations/touch.dm
@@ -4,50 +4,103 @@
quality = POSITIVE
locked = TRUE
difficulty = 16
- power = /obj/effect/proc_holder/spell/targeted/touch/shock
+ power = /obj/effect/proc_holder/spell/targeted/touch/mutation/shock
instability = 30
locked = TRUE
+ energy_coeff = 1
+ power_coeff = 1
-/obj/effect/proc_holder/spell/targeted/touch/shock
+/obj/effect/proc_holder/spell/targeted/touch/mutation/shock
name = "Shock Touch"
desc = "Channel electricity to your hand to shock people with."
drawmessage = "You channel electricity into your hand."
dropmessage = "You let the electricity from your hand dissipate."
- hand_path = /obj/item/melee/touch_attack/shock
- charge_max = 100
- clothes_req = FALSE
+ hand_path = /obj/item/melee/touch_attack/mutation/shock
+ charge_max = 10 SECONDS
action_icon_state = "zap"
-/obj/item/melee/touch_attack/shock
+/obj/item/melee/touch_attack/mutation/shock
name = "\improper shock touch"
desc = "This is kind of like when you rub your feet on a shag rug so you can zap your friends, only a lot less safe."
- catchphrase = null
on_use_sound = 'sound/weapons/zapbang.ogg'
icon_state = "zapper"
item_state = "zapper"
-/obj/item/melee/touch_attack/shock/afterattack(atom/target, mob/living/carbon/user, proximity)
- user.Beam(target, icon_state="lightning[rand(1,12)]", time=5, maxdistance = 32)
+/obj/item/melee/touch_attack/mutation/shock/afterattack(atom/target, mob/living/carbon/user, proximity)
+ if(QDELETED(target) || isturf(target))
+ return
+ user.Beam(target, icon_state = "lightning[rand(1, 12)]", time = 5, maxdistance = 32)
+ var/zap = 15 * GET_MUTATION_POWER(parent_mutation)
if(iscarbon(target))
- var/mob/living/carbon/C = target
- if(C.electrocute_act(15, user, 1, FALSE, FALSE, FALSE, FALSE, FALSE))//doesnt stun. never let this stun
- C.dropItemToGround(C.get_active_held_item())
- C.dropItemToGround(C.get_inactive_held_item())
- C.confused += 15
- C.visible_message("[user] electrocutes [target]!","[user] electrocutes you!")
- use_charge(user)
- return ..()
+ var/mob/living/carbon/ctarget = target
+ if(ctarget.electrocute_act(zap, user, stun = FALSE)) //doesnt stun. never let this stun
+ ctarget.drop_all_held_items()
+ ctarget.confused += zap
+ ctarget.visible_message("[user] electrocutes [target]!","[user] electrocutes you!")
else
user.visible_message("[user] fails to electrocute [target]!")
- use_charge(user)
- return ..()
else if(isliving(target))
- var/mob/living/L = target
- L.electrocute_act(15, user, 1, FALSE, FALSE, FALSE, FALSE)
- L.visible_message("[user] electrocutes [target]!","[user] electrocutes you!")
- use_charge(user)
- return ..()
+ var/mob/living/ltarget = target
+ ltarget.electrocute_act(zap, user, stun = FALSE)
+ ltarget.visible_message("[user] electrocutes [target]!","[user] electrocutes you!")
else
to_chat(user,"The electricity doesn't seem to affect [target]...")
- use_charge(user)
+ use_charge(user)
+ return ..()
+
+/datum/mutation/acidooze
+ name = "Acidic Hands"
+ desc = "Allows an Oozeling to metabolize some of their blood into acid, concentrated on their hands."
+ quality = POSITIVE
+ locked = TRUE
+ instability = 30
+ power = /obj/effect/proc_holder/spell/targeted/touch/mutation/acidooze
+ power_coeff = 1
+ energy_coeff = 1
+ synchronizer_coeff = 1
+ species_allowed = list(SPECIES_OOZELING)
+
+/obj/effect/proc_holder/spell/targeted/touch/mutation/acidooze
+ name = "Acidic Hands"
+ desc = "Concentrate to make some of your blood become acidic."
+ clothes_req = FALSE
+ human_req = FALSE
+ charge_max = 10 SECONDS
+ action_icon_state = "summons"
+ hand_path = /obj/item/melee/touch_attack/mutation/acidooze
+ drawmessage = "You secrete acid into your hand."
+ dropmessage = "You let the acid in your hand dissipate."
+
+/obj/item/melee/touch_attack/mutation/acidooze
+ name = "\improper acidic hand"
+ desc = "Keep away from children, paperwork, and children doing paperwork."
+ icon = 'icons/effects/blood.dmi'
+ icon_state = "bloodhand_left"
+ item_state = "fleshtostone"
+ var/static/base_acid_volume = 15
+ var/static/base_blood_cost = 20
+ var/static/icon_left = "bloodhand_left"
+ var/static/icon_right = "bloodhand_right"
+
+/obj/item/melee/touch_attack/mutation/acidooze/equipped(mob/user, slot)
+ . = ..()
+ //these are intentionally inverted
+ icon_state = (user.get_held_index_of_item(src) % 2) ? icon_right : icon_left
+
+/obj/item/melee/touch_attack/mutation/acidooze/afterattack(atom/target, mob/living/carbon/user, proximity)
+ if(!proximity || !isoozeling(user))
+ return
+ if(!target || user.incapacitated())
+ return FALSE
+ var/acid_volume = base_acid_volume * GET_MUTATION_POWER(parent_mutation)
+ var/blood_cost = base_blood_cost * GET_MUTATION_SYNCHRONIZER(parent_mutation)
+ if(user.blood_volume < (blood_cost * 2))
+ to_chat(user, "You don't have enough blood to do that!")
+ return FALSE
+ if(target.acid_act(50, acid_volume))
+ user.visible_message("[user] rubs globs of vile stuff all over [target].")
+ user.blood_volume = max(user.blood_volume - blood_cost, 0)
return ..()
+ else
+ to_chat(user, "You cannot dissolve this object.")
+ return FALSE
diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm
index 3d00f3cd6bb5b..3dc2a6572d5d3 100644
--- a/code/datums/progressbar.dm
+++ b/code/datums/progressbar.dm
@@ -42,7 +42,7 @@
if (user.client)
user.client.images += bar
- progress = CLAMP(progress, 0, goal)
+ progress = clamp(progress, 0, goal)
last_progress = progress
bar.icon_state = "prog_bar_[round(((progress / goal) * 100), 5)]"
if (!shown)
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index db2a786170f95..e969ec3acbf14 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -484,6 +484,7 @@
healSnake.desc = "A mystical snake previously trapped upon the Rod of Asclepius, now freed of its burden. Unlike the average snake, its bites contain chemicals with minor healing properties."
new /obj/effect/decal/cleanable/ash(owner.loc)
new /obj/item/rod_of_asclepius(owner.loc)
+ owner.investigate_log("has been consumed by the Rod of Asclepius.", INVESTIGATE_DEATHS)
qdel(owner)
else
if(iscarbon(owner))
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 8a447462570ef..944e109ec07a5 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -33,9 +33,11 @@
if(!.)
return
ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
+ ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
/datum/status_effect/incapacitating/stun/on_remove()
REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
+ REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
return ..()
//KNOCKDOWN
@@ -46,6 +48,16 @@
/datum/status_effect/incapacitating/immobilized
id = "immobilized"
+/datum/status_effect/incapacitating/immobilized/on_apply()
+ . = ..()
+ if(!.)
+ return
+ ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
+
+/datum/status_effect/incapacitating/immobilized/on_remove()
+ REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
+ return ..()
+
/datum/status_effect/incapacitating/paralyzed
id = "paralyzed"
@@ -54,9 +66,11 @@
if(!.)
return
ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
+ ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
/datum/status_effect/incapacitating/paralyzed/on_remove()
REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
+ REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
return ..()
//UNCONSCIOUS
@@ -68,10 +82,10 @@
. = ..()
if(!.)
return
- ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
+ ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id))
/datum/status_effect/incapacitating/unconscious/on_remove()
- REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
+ REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id))
return ..()
/datum/status_effect/incapacitating/unconscious/tick()
@@ -99,6 +113,16 @@
human_owner = null
return ..()
+/datum/status_effect/incapacitating/sleeping/on_apply()
+ . = ..()
+ if(!.)
+ return
+ ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id))
+
+/datum/status_effect/incapacitating/sleeping/on_remove()
+ REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id))
+ return ..()
+
/datum/status_effect/incapacitating/sleeping/tick()
if(owner.maxHealth)
var/health_ratio = owner.health / owner.maxHealth
@@ -149,26 +173,22 @@
if(.)
update_time_of_death()
owner.reagents?.end_metabolization(owner, FALSE)
- owner.update_mobility()
SEND_SIGNAL(owner, COMSIG_LIVING_ENTER_STASIS)
-/* Mobility refactor
/datum/status_effect/grouped/stasis/on_apply()
. = ..()
if(!.)
return
ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
- ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
-*/
+ //ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
+ owner.update_mobility() // TEMPORARY
/datum/status_effect/grouped/stasis/tick()
update_time_of_death()
/datum/status_effect/grouped/stasis/on_remove()
- /* Mobility refactor
REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
- REMOVE_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
- */
+ //REMOVE_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
owner.update_mobility()
update_time_of_death()
SEND_SIGNAL(owner, COMSIG_LIVING_EXIT_STASIS)
diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm
index 42715522e8f30..f5fa401c6622e 100644
--- a/code/datums/status_effects/gas.dm
+++ b/code/datums/status_effects/gas.dm
@@ -6,6 +6,16 @@
var/icon/cube
var/can_melt = TRUE
+/datum/status_effect/freon/on_apply()
+ . = ..()
+ if(!.)
+ return
+ ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
+
+/datum/status_effect/freon/on_remove()
+ REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
+ return ..()
+
/atom/movable/screen/alert/status_effect/freon
name = "Frozen Solid"
desc = "You're frozen inside an ice cube, and cannot move! You can still do stuff, like shooting. Resist out of the cube!"
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index a548abf750f3f..b9b821bf46b73 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -53,7 +53,7 @@
var/list/status = list()
status += "The door bolts [A.locked ? "have fallen!" : "look up."]"
status += "The test light is [A.hasPower() ? (A.isElectrified() ? "bright and flicking" : "on") : "off"]."
- status += "The AI connection light is [A.aiControlDisabled || (A.obj_flags & EMAGGED) ? "off" : "on"]."
+ status += "The AI connection light is [A.aiControlDisabled ? "off" : "on"]."
status += "The check wiring light is [A.safe ? "off" : "on"]."
status += "The timer is powered [A.autoclose ? "on" : "off"]."
status += "The speed light is [A.normalspeed ? "on" : "off"]."
@@ -68,15 +68,14 @@
if(isliving(usr) && A.hasPower() && A.isElectrified())
if (A.shock(usr, 100))
return
- if(A.hasPower()) //Multitool has no effect at all if the door has lost power
+ switch(wire)
+ if(WIRE_POWER1, WIRE_POWER2) // Pulse to lose power, or reset the delay before restoring power if already lost
+ A.loseMainPower()
+ if(WIRE_BACKUP1, WIRE_BACKUP2) // Pulse to lose backup power, or reset the delay before restoring power if already lost
+ A.loseBackupPower()
+ if(A.hasPower()) //Multitool has no effect on other wires if the door has no power
switch(wire)
- if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power.
- A.loseMainPower()
- if(WIRE_BACKUP1, WIRE_BACKUP2) // Pulse to loose backup power.
- A.loseBackupPower()
- if(WIRE_OPEN) // Pulse to open door (only works not emagged and ID wire is cut or no access is required).
- if(A.obj_flags & EMAGGED)
- return
+ if(WIRE_OPEN) // Pulse to open door
if(A.id_scan_hacked() || A.check_access(null))
if(A.density)
INVOKE_ASYNC(A, TYPE_PROC_REF(/obj/machinery/door/airlock, open))
diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm
index cd378dc4b9151..ad9e520ff63fa 100644
--- a/code/game/area/Space_Station_13_areas.dm
+++ b/code/game/area/Space_Station_13_areas.dm
@@ -121,6 +121,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
ambience_index = AMBIENCE_MAINT
ambient_buzz = 'sound/ambience/source_corridor2.ogg'
ambient_buzz_vol = 20
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
rare_ambient_sounds = list(
'sound/machines/airlock.ogg',
'sound/effects/snap.ogg',
@@ -153,10 +154,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/department/chapel
name = "Chapel Maintenance"
icon_state = "maint_chapel"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/maintenance/department/chapel/monastery
name = "Monastery Maintenance"
icon_state = "maint_monastery"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/maintenance/department/crew_quarters/bar
name = "Bar Maintenance"
@@ -179,14 +182,17 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/department/engine/atmos
name = "Atmospherics Maintenance"
icon_state = "maint_atmos"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/maintenance/department/security
name = "Security Maintenance"
icon_state = "maint_sec"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/maintenance/department/security/brig
name = "Brig Maintenance"
icon_state = "maint_brig"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/maintenance/department/medical
name = "Medbay Maintenance"
@@ -215,6 +221,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/department/bridge
name = "Bridge Maintenance"
icon_state = "maint_bridge"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/maintenance/department/engine
name = "Engineering Maintenance"
@@ -369,10 +376,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
//Hallway
/area/hallway
- sound_environment = SOUND_AREA_STANDARD_STATION
- lights_always_start_on = TRUE
/area/hallway
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
+ sound_environment = SOUND_AREA_STANDARD_STATION
+ lights_always_start_on = TRUE
lighting_colour_tube = "#ffce99"
lighting_colour_bulb = "#ffdbb4"
lighting_brightness_tube = 8
@@ -403,6 +411,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway/secondary/command
name = "Command Hallway"
icon_state = "bridge_hallway"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/hallway/secondary/construction
name = "Construction Area"
@@ -455,6 +464,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway/upper/secondary/command
name = "Upper Command Hallway"
icon_state = "bridge_hallway"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/hallway/upper/secondary/construction
name = "Upper Construction Area"
@@ -507,6 +517,9 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "showroom"
sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR
+/area/crew_quarters
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
+
/area/crew_quarters/heads/captain
name = "Captain's Office"
icon_state = "captain"
@@ -571,6 +584,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
//Crew
/area/crew_quarters
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
lighting_colour_tube = "#ffce99"
lighting_colour_bulb = "#ffdbb4"
lighting_brightness_tube = 8
@@ -581,10 +595,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/dorms
name = "Dormitories"
icon_state = "dorms"
- area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
mood_bonus = 3
mood_message = "There's no place like the dorms!\n"
+/area/commons
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
+
/area/commons/dorms/barracks
name = "Sleep Barracks"
@@ -684,6 +700,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "bar"
mood_bonus = 5
mood_message = "I love being in the bar!\n"
+ lights_always_start_on = TRUE
lighting_colour_tube = "#fff4d6"
lighting_colour_bulb = "#ffebc1"
sound_environment = SOUND_AREA_WOODFLOOR
@@ -704,13 +721,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
. = ..()
GLOB.bar_areas += src
-/area/service/bar
- lights_always_start_on = TRUE
-
-/area/service/bar/Initialize(mapload)
- . = ..()
- GLOB.bar_areas += src
-
/area/crew_quarters/bar/atrium
name = "Atrium"
icon_state = "bar"
@@ -748,6 +758,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Library"
icon_state = "library"
flags_1 = NONE
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
lighting_colour_tube = "#ffce99"
lighting_colour_bulb = "#ffdbb4"
@@ -768,6 +779,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/chapel
icon_state = "chapel"
ambience_index = AMBIENCE_HOLY
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
flags_1 = NONE
clockwork_warp_allowed = FALSE
clockwork_warp_fail = "The consecration here prevents you from warping in."
@@ -801,6 +813,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "law"
sound_environment = SOUND_AREA_SMALL_SOFTFLOOR
airlock_hack_difficulty = AIRLOCK_WIRE_SECURITY_PROTECTED
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
//Engineering
@@ -939,6 +952,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/solars
name = "Solar Maintenance"
icon_state = "yellow"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/maintenance/solars/port
name = "Port Solar Maintenance"
@@ -984,6 +998,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/medical
name = "Medical"
icon_state = "medbay"
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
ambience_index = AMBIENCE_MEDICAL
sound_environment = SOUND_AREA_STANDARD_STATION
mood_bonus = 2
@@ -1024,10 +1039,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/medical/storage
name = "Medbay Storage"
icon_state = "med_storage"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/medical/office
name = "Medical Office"
icon_state = "med_office"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/medical/break_room
name = "Medical Break Room"
@@ -1056,6 +1073,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
ambience_index = AMBIENCE_VIROLOGY
flags_1 = NONE
airlock_hack_difficulty = AIRLOCK_WIRE_SECURITY_PROTECTED
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/medical/morgue
name = "Morgue"
@@ -1070,6 +1088,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Chemistry"
icon_state = "chem"
airlock_hack_difficulty = AIRLOCK_WIRE_SECURITY_PROTECTED
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/medical/chemistry/upper
name = "Upper Chemistry"
@@ -1083,6 +1102,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Surgery"
icon_state = "surgery"
airlock_hack_difficulty = AIRLOCK_WIRE_SECURITY_ADVANCED
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/medical/surgery/aux
name = "Auxillery Surgery"
@@ -1091,6 +1111,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/medical/cryo
name = "Cryogenics"
icon_state = "cryo"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/medical/exam_room
name = "Exam Room"
@@ -1100,6 +1121,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Genetics Lab"
icon_state = "genetics"
airlock_hack_difficulty = AIRLOCK_WIRE_SECURITY_PROTECTED
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/medical/genetics/cloning
name = "Cloning Lab"
@@ -1108,6 +1130,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/medical/sleeper
name = "Medbay Treatment Center"
icon_state = "exam_room"
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
//Security
@@ -1348,6 +1371,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Hydroponics"
icon_state = "hydro"
sound_environment = SOUND_AREA_STANDARD_STATION
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
airlock_hack_difficulty = AIRLOCK_WIRE_SECURITY_SIMPLE
color_correction = /datum/client_colour/area_color/cold_ish
diff --git a/code/game/area/area_color_correction.dm b/code/game/area/area_color_correction.dm
index 679598092d18c..63dd18fbda70d 100644
--- a/code/game/area/area_color_correction.dm
+++ b/code/game/area/area_color_correction.dm
@@ -8,7 +8,7 @@
var/current_correction
/datum/client_colour/area_color
- colour = ""
+ colour = list(rgb(255, 0, 0), rgb(0, 255, 0), rgb(0, 0, 255))
priority = PRIORITY_LOW
fade_in = 10 SECONDS
fade_out = 10 SECONDS
diff --git a/code/game/area/areas/holodeck.dm b/code/game/area/areas/holodeck.dm
index b8873b4e9d07e..f8e4e7feb0569 100644
--- a/code/game/area/areas/holodeck.dm
+++ b/code/game/area/areas/holodeck.dm
@@ -3,7 +3,7 @@
icon_state = "holodeck"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
flags_1 = NONE
- area_flags = VALID_TERRITORY | UNIQUE_AREA | HIDDEN_AREA
+ area_flags = HIDDEN_STASH_LOCATION | VALID_TERRITORY | UNIQUE_AREA | HIDDEN_AREA
sound_environment = SOUND_ENVIRONMENT_PADDED_CELL
var/obj/machinery/computer/holodeck/linked
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index e3a30b90c967b..3dc7447bccf82 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -429,7 +429,6 @@
* Otherwise it simply forceMoves the atom into this atom
*/
/atom/proc/CheckParts(list/parts_list, datum/crafting_recipe/R)
- SEND_SIGNAL(src, COMSIG_ATOM_CHECKPARTS, parts_list, R)
if(parts_list)
for(var/A in parts_list)
if(istype(A, /datum/reagent))
@@ -445,6 +444,7 @@
else
M.forceMove(src)
parts_list.Cut()
+ SEND_SIGNAL(src, COMSIG_ATOM_CHECKPARTS, parts_list, R)
///Take air from the passed in gas mixture datum
/atom/proc/assume_air(datum/gas_mixture/giver)
@@ -1625,6 +1625,10 @@
filter_data[name]["priority"] = new_priority
update_filters()
+/obj/item/update_filters()
+ . = ..()
+ update_action_buttons()
+
/atom/proc/get_filter(name)
if(filter_data && filter_data[name])
return filters[filter_data.Find(name)]
@@ -1810,4 +1814,3 @@
qdel(src)
return TRUE
return FALSE
-
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index b614606746325..b303c2908d74a 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -164,7 +164,7 @@
log_combat(AM, AM.pulledby, "pulled from", src)
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
pulling = AM
- AM.pulledby = src
+ AM.set_pulledby(src)
setGrabState(state)
if(ismob(AM))
var/mob/M = AM
@@ -177,19 +177,26 @@
/atom/movable/proc/stop_pulling()
if(pulling)
- pulling.pulledby = null
+ pulling.set_pulledby(null)
if(ismob(usr))
log_combat(usr, pulling, "has stopped pulling", addition = "at [AREACOORD(usr)]")
if(ismob(pulling))
log_combat(pulling, usr, "stopped being pulled by", addition = "at [AREACOORD(pulling)]")
var/mob/living/ex_pulled = pulling
+ setGrabState(GRAB_PASSIVE)
pulling = null
- setGrabState(0)
if(isliving(ex_pulled))
var/mob/living/L = ex_pulled
L.update_mobility()// mob gets up if it was lyng down in a chokehold
SEND_SIGNAL(ex_pulled, COMSIG_MOVABLE_NO_LONGER_PULLED)
+///Reports the event of the change in value of the pulledby variable.
+/atom/movable/proc/set_pulledby(new_pulledby)
+ if(new_pulledby == pulledby)
+ return FALSE //null signals there was a change, be sure to return FALSE if none happened here.
+ . = pulledby
+ pulledby = new_pulledby
+
/atom/movable/proc/Move_Pulled(atom/A)
if(!pulling)
return
@@ -1062,7 +1069,19 @@
/// Updates the grab state of the movable
/// This exists to act as a hook for behaviour
/atom/movable/proc/setGrabState(newstate)
+ if(newstate == grab_state)
+ return
+ SEND_SIGNAL(src, COMSIG_MOVABLE_SET_GRAB_STATE, newstate)
+ . = grab_state
grab_state = newstate
+ switch(.) //Previous state.
+ if(GRAB_PASSIVE, GRAB_AGGRESSIVE)
+ if(grab_state >= GRAB_NECK)
+ ADD_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
+ switch(grab_state) //Current state.
+ if(GRAB_PASSIVE, GRAB_AGGRESSIVE)
+ if(. >= GRAB_NECK)
+ REMOVE_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
/obj/item/proc/do_pickup_animation(atom/target)
set waitfor = FALSE
diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm
index f0c7dabdc45b8..db080a8a3d44f 100644
--- a/code/game/gamemodes/clown_ops/clown_weapons.dm
+++ b/code/game/gamemodes/clown_ops/clown_weapons.dm
@@ -119,7 +119,7 @@
/obj/item/melee/transforming/energy/sword/bananium/ignition_effect(atom/A, mob/user)
return ""
-/obj/item/melee/transforming/energy/sword/bananium/suicide_act(mob/user)
+/obj/item/melee/transforming/energy/sword/bananium/suicide_act(mob/living/user)
if(!active)
transform_weapon(user, TRUE)
user.visible_message("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku, but the blade slips off of [user.p_them()] harmlessly!")
@@ -213,11 +213,11 @@
. = ..()
QDEL_NULL(bomb)
-/obj/item/grown/bananapeel/bombanana/suicide_act(mob/user)
+/obj/item/grown/bananapeel/bombanana/suicide_act(mob/living/user)
user.visible_message("[user] is deliberately slipping on the [src.name]! It looks like \he's trying to commit suicide.")
playsound(loc, 'sound/misc/slip.ogg', 50, 1, -1)
bomb.preprime(user, 0, FALSE)
- return (BRUTELOSS)
+ return BRUTELOSS
//TEARSTACHE GRENADE
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
index d5032b56ff746..c8249413d7364 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
@@ -558,7 +558,7 @@
if (prob(meteorminutes/2))
wavetype = GLOB.meteors_catastrophic
- var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10)
+ var/ramp_up_final = clamp(round(meteorminutes/rampupdelta), 1, 10)
spawn_meteors(ramp_up_final, wavetype)
@@ -649,7 +649,7 @@
var/datum/team/incursion/incursion_team
/datum/dynamic_ruleset/roundstart/incursion/ready(population, forced = FALSE)
- required_candidates = CLAMP(get_antag_cap(population), CONFIG_GET(number/incursion_count_min), CONFIG_GET(number/incursion_count_max))
+ required_candidates = clamp(get_antag_cap(population), CONFIG_GET(number/incursion_count_min), CONFIG_GET(number/incursion_count_max))
return ..()
/datum/dynamic_ruleset/roundstart/incursion/pre_execute(population)
diff --git a/code/game/gamemodes/incursion/incursion.dm b/code/game/gamemodes/incursion/incursion.dm
index c66f7d2f0f69b..5f66a751c64f1 100644
--- a/code/game/gamemodes/incursion/incursion.dm
+++ b/code/game/gamemodes/incursion/incursion.dm
@@ -36,7 +36,7 @@
var/pop = GLOB.player_details.len
var/team_size = (2 * pop) / ((2 * cost_base) + ((pop - 1) * cost_increment))
log_game("Spawning [team_size] incursionists.")
- team_size = CLAMP(team_size, CONFIG_GET(number/incursion_count_min), CONFIG_GET(number/incursion_count_max))
+ team_size = clamp(team_size, CONFIG_GET(number/incursion_count_min), CONFIG_GET(number/incursion_count_max))
for(var/k = 1 to team_size)
var/datum/mind/incursion = antag_pick(antag_candidates, /datum/role_preference/antagonist/incursionist)
diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm
index 9ed3060b7165f..14dacc54017f0 100644
--- a/code/game/gamemodes/meteor/meteor.dm
+++ b/code/game/gamemodes/meteor/meteor.dm
@@ -27,7 +27,7 @@
if (prob(meteorminutes/2))
wavetype = GLOB.meteors_catastrophic
- var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10)
+ var/ramp_up_final = clamp(round(meteorminutes/rampupdelta), 1, 10)
spawn_meteors(ramp_up_final, wavetype)
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index c1159acd3941b..d637e46021bb4 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -172,7 +172,7 @@
r_pocket = /obj/item/tank/internals/emergency_oxygen/engi
internals_slot = ITEM_SLOT_RPOCKET
belt = /obj/item/storage/belt/military
- r_hand = /obj/item/gun/ballistic/shotgun/bulldog
+ r_hand = /obj/item/gun/ballistic/shotgun/automatic/bulldog
backpack_contents = list(/obj/item/storage/box/syndie=1,\
/obj/item/tank/jetpack/oxygen/harness=1,\
/obj/item/gun/ballistic/automatic/pistol=1,\
diff --git a/code/game/gamemodes/objectives/_objective.dm b/code/game/gamemodes/objectives/_objective.dm
index f4b78489db487..b4f0840a6cb80 100644
--- a/code/game/gamemodes/objectives/_objective.dm
+++ b/code/game/gamemodes/objectives/_objective.dm
@@ -224,20 +224,6 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list
switch (pick_weight(list("airlock" = 3)))
if("airlock")
atom_text = "An airlock"
- //Valid areas
- var/static/list/valid_areas = list(
- /area/medical,
- /area/commons,
- /area/crew_quarters,
- /area/service,
- /area/library,
- /area/maintenance,
- /area/hallway,
- /area/chapel,
- /area/hydroponics,
- /area/holodeck,
- /area/lawoffice,
- )
// If our airlock isn't accessible to these accesses, then we won't allow the item to spawn here
var/list/safe_access_list = list(ACCESS_CARGO, ACCESS_MAINT_TUNNELS, ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_JANITOR, ACCESS_CHAPEL_OFFICE, ACCESS_THEATRE, ACCESS_LAWYER, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING)
//Pick a valid airlock
@@ -248,12 +234,7 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list
continue
//Make sure its publicly accessible
var/area/area = get_area(A)
- var/valid = FALSE
- for(var/area_type in valid_areas)
- if(istype(area, area_type))
- valid = TRUE
- break
- if(!valid)
+ if (!(area.area_flags & HIDDEN_STASH_LOCATION))
continue
//This airlock is good for us
A.AddComponent(/datum/component/stash, receiver, secret_bag)
diff --git a/code/game/gamemodes/objectives/basic/steal.dm b/code/game/gamemodes/objectives/basic/steal.dm
index 987427736f4ba..bfbf85290dbf9 100644
--- a/code/game/gamemodes/objectives/basic/steal.dm
+++ b/code/game/gamemodes/objectives/basic/steal.dm
@@ -81,9 +81,12 @@ GLOBAL_LIST_EMPTY(possible_items)
if(!isliving(M.current))
continue
- var/list/all_items = M.current.GetAllContents() //this should get things in cheesewheels, books, etc.
+ var/list/all_items = M.current.GetAllContents(/obj/item) //this should get things in cheesewheels, books, etc.
- for(var/obj/I in all_items) //Check for items
+ for(var/mob/living/simple_animal/hostile/holoparasite/holopara as() in M.holoparasite_holder?.holoparasites)
+ all_items |= holopara.GetAllContents(/obj/item)
+
+ for(var/obj/I as() in all_items) //Check for items
if(istype(I, steal_target))
if(!targetinfo) //If there's no targetinfo, then that means it was a custom objective. At this point, we know you have the item, so return 1.
return TRUE
diff --git a/code/game/gamemodes/objectives/open/destroy_equipment.dm b/code/game/gamemodes/objectives/open/destroy_equipment.dm
index 3803d7315d76e..d586eeebd0f6c 100644
--- a/code/game/gamemodes/objectives/open/destroy_equipment.dm
+++ b/code/game/gamemodes/objectives/open/destroy_equipment.dm
@@ -8,7 +8,7 @@
"security" = list(/area/security),
"the cargo bay" = list(/area/quartermaster, /area/cargo),
"the bridge" = list(/area/bridge),
- "the communications relay" = list(/area/comms, /area/server),
+ "the communications relay" = list(/area/comms, /area/server, /area/tcommsat),
"the science lab" = list(/area/science),
"the research division server room" = list(/area/science/server),
// Anywhere monitored by the AI will do
diff --git a/code/game/gamemodes/objectives/open/explosion.dm b/code/game/gamemodes/objectives/open/explosion.dm
index fd99a977178f6..5f5cfe04fa983 100644
--- a/code/game/gamemodes/objectives/open/explosion.dm
+++ b/code/game/gamemodes/objectives/open/explosion.dm
@@ -9,7 +9,7 @@
"security" = list(/area/security),
"the cargo bay" = list(/area/quartermaster, /area/cargo),
"the bridge" = list(/area/bridge),
- "the communications relay" = list(/area/comms, /area/server),
+ "the communications relay" = list(/area/comms, /area/server, /area/tcommsat),
"the science lab" = list(/area/science),
"the research division server room" = list(/area/science/server),
// Anywhere monitored by the AI will do
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index 08d728282c5d1..707db1969de02 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -244,6 +244,20 @@ Class Procs:
var/datum/controller/subsystem/processing/subsystem = locate(subsystem_type) in Master.subsystems
STOP_PROCESSING(subsystem, src)
+/obj/machinery/LateInitialize()
+ . = ..()
+ power_change()
+ RegisterSignal(src, COMSIG_MOVABLE_ENTERED_AREA, PROC_REF(power_change))
+
+/obj/machinery/Destroy()
+ GLOB.machines.Remove(src)
+ if(datum_flags & DF_ISPROCESSING) // A sizeable portion of machines stops processing before qdel
+ end_processing()
+ dump_inventory_contents()
+ QDEL_LIST(component_parts)
+ QDEL_NULL(circuit)
+ return ..()
+
/obj/machinery/proc/locate_machinery()
return
@@ -901,6 +915,9 @@ Class Procs:
. = ..()
if (gone == occupant)
set_occupant(null)
+ if(gone == circuit)
+ LAZYREMOVE(component_parts, gone)
+ circuit = null
/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
var/md5 = rustg_hash_string(RUSTG_HASH_MD5, AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
diff --git a/code/game/machinery/airlock_cycle_control.dm b/code/game/machinery/airlock_cycle_control.dm
index d0fd454fe76ec..a9c06882e13b5 100644
--- a/code/game/machinery/airlock_cycle_control.dm
+++ b/code/game/machinery/airlock_cycle_control.dm
@@ -742,16 +742,16 @@
scan()
. = TRUE
if("interior_pressure")
- interior_pressure = CLAMP(text2num(params["pressure"]), 0, ONE_ATMOSPHERE)
+ interior_pressure = clamp(text2num(params["pressure"]), 0, ONE_ATMOSPHERE)
. = TRUE
if("exterior_pressure")
- exterior_pressure = CLAMP(text2num(params["pressure"]), 0, ONE_ATMOSPHERE)
+ exterior_pressure = clamp(text2num(params["pressure"]), 0, ONE_ATMOSPHERE)
. = TRUE
if("depressurization_margin")
- depressurization_margin = CLAMP(text2num(params["pressure"]), 0.15, 40)
+ depressurization_margin = clamp(text2num(params["pressure"]), 0.15, 40)
. = TRUE
if("skip_delay")
- skip_delay = CLAMP(text2num(params["skip_delay"]), 0, 1200)
+ skip_delay = clamp(text2num(params["skip_delay"]), 0, 1200)
. = TRUE
if(.)
diff --git a/code/game/machinery/bank_machine.dm b/code/game/machinery/bank_machine.dm
index 1b4c728fb9f9c..7229a190f2d4f 100644
--- a/code/game/machinery/bank_machine.dm
+++ b/code/game/machinery/bank_machine.dm
@@ -3,6 +3,10 @@
desc = "A machine used to deposit and withdraw station funds."
icon = 'goon/icons/obj/goon_terminals.dmi'
idle_power_usage = 100
+ base_icon_state = null // remove these 4 when we start using our own icon.
+ smoothing_flags = NONE
+ smoothing_groups = null
+ canSmoothWith = null
var/siphoning = FALSE
var/next_warning = 0
var/obj/item/radio/radio
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 6fd3f051fc198..3357092dd9e23 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -47,7 +47,6 @@
// Upgrades bitflag
var/upgrades = 0
- var/datum/component/empprotection/emp_component
var/internal_light = TRUE //Whether it can light up when an AI views it
@@ -130,7 +129,6 @@
LAZYREMOVE(myarea.cameras, src)
QDEL_NULL(alarm_manager)
QDEL_NULL(assembly_ref)
- QDEL_NULL(emp_component)
if(bug)
bug.bugged_cameras -= c_tag
if(bug.current == src)
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index e61f2bf717c4d..483767911f1ca 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -75,7 +75,7 @@
/obj/machinery/camera/proc/upgradeEmpProof(malf_upgrade, ignore_malf_upgrades)
if(isEmpProof(ignore_malf_upgrades)) //pass a malf upgrade to ignore_malf_upgrades so we can replace the malf module with the normal one
return //that way if someone tries to upgrade an already malf-upgraded camera, it'll just upgrade it to a normal version.
- emp_component = AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS)
+ AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS)
var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve()
if(malf_upgrade)
assembly.malf_emp_firmware_active = TRUE //don't add parts to drop, update icon, ect. reconstructing it will also retain the upgrade.
@@ -91,7 +91,7 @@
/obj/machinery/camera/proc/removeEmpProof(ignore_malf_upgrades)
if(ignore_malf_upgrades) //don't downgrade it if malf software is forced onto it.
return
- emp_component.RemoveComponent()
+ RemoveElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS)
upgrades &= ~CAMERA_UPGRADE_EMP_PROOF
diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm
index 539354d02050c..6c9a9abf01450 100644
--- a/code/game/machinery/computer/_computer.dm
+++ b/code/game/machinery/computer/_computer.dm
@@ -1,7 +1,11 @@
/obj/machinery/computer
name = "computer"
icon = 'icons/obj/computer.dmi'
- icon_state = "computer"
+ icon_state = "computer-0"
+ base_icon_state = "computer"
+ smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIRECTIONAL | SMOOTH_BITMASK_SKIP_CORNERS | SMOOTH_OBJ //SMOOTH_OBJ is needed because of narsie_act using initial() to restore
+ smoothing_groups = list(SMOOTH_GROUP_COMPUTERS)
+ canSmoothWith = list(SMOOTH_GROUP_COMPUTERS)
density = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 300
@@ -26,9 +30,14 @@
/obj/machinery/computer/Initialize(mapload)
. = ..()
-
+ QUEUE_SMOOTH(src)
+ QUEUE_SMOOTH_NEIGHBORS(src)
power_change()
+/obj/machinery/computer/Destroy()
+ QUEUE_SMOOTH_NEIGHBORS(src)
+ return ..()
+
/obj/machinery/computer/process()
if(machine_stat & (NOPOWER|BROKEN))
return 0
@@ -41,6 +50,9 @@
icon_keyboard = "ratvar_key[rand(1, 2)]"
icon_state = "ratvarcomputer"
broken_overlay_emissive = TRUE
+ smoothing_groups = null
+ QUEUE_SMOOTH_NEIGHBORS(src)
+ smoothing_flags = NONE
update_appearance()
/obj/machinery/computer/narsie_act()
@@ -48,8 +60,15 @@
clockwork = FALSE
icon_screen = initial(icon_screen)
icon_keyboard = initial(icon_keyboard)
- icon_state = initial(icon_state)
broken_overlay_emissive = initial(broken_overlay_emissive)
+ smoothing_flags = initial(smoothing_flags)
+ smoothing_groups = list(SMOOTH_GROUP_COMPUTERS)
+ canSmoothWith = list(SMOOTH_GROUP_COMPUTERS)
+ SET_BITFLAG_LIST(smoothing_groups)
+ SET_BITFLAG_LIST(canSmoothWith)
+ QUEUE_SMOOTH(src)
+ if(smoothing_flags)
+ QUEUE_SMOOTH_NEIGHBORS(src)
update_appearance()
/obj/machinery/computer/update_overlays()
@@ -125,6 +144,7 @@
var/obj/structure/frame/computer/A = new /obj/structure/frame/computer(src.loc)
A.setDir(dir)
A.circuit = circuit
+ // Circuit removal code is handled in /obj/machinery/Exited()
circuit.forceMove(A)
A.setAnchored(TRUE)
if(machine_stat & BROKEN)
@@ -141,7 +161,6 @@
to_chat(user, "You disconnect the monitor.")
A.state = 4
A.icon_state = "4"
- circuit = null
for(var/obj/C in src)
C.forceMove(loc)
qdel(src)
diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm
index eaee7d4e5d3f0..fee8f4cabb914 100644
--- a/code/game/machinery/computer/apc_control.dm
+++ b/code/game/machinery/computer/apc_control.dm
@@ -151,7 +151,7 @@
return
log_activity("changed greater than charge filter to \"[new_filter]\"")
if(new_filter)
- new_filter = CLAMP(new_filter, 0, 100)
+ new_filter = clamp(new_filter, 0, 100)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
result_filters["Charge Above"] = new_filter
if(href_list["below_filter"])
@@ -161,7 +161,7 @@
return
log_activity("changed lesser than charge filter to \"[new_filter]\"")
if(new_filter)
- new_filter = CLAMP(new_filter, 0, 100)
+ new_filter = clamp(new_filter, 0, 100)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
result_filters["Charge Below"] = new_filter
if(href_list["access_filter"])
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 15e29e7cc4546..d51c257609e22 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -71,11 +71,18 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
icon_state = "arcade"
icon_keyboard = "no_keyboard"
icon_screen = "invaders"
+
+ //these muthafuckas arent supposed to smooth
+ base_icon_state = null
+ smoothing_flags = null
+ smoothing_groups = null
+ canSmoothWith = null
+
clockwork = TRUE //it'd look weird
broken_overlay_emissive = TRUE
+ light_color = LIGHT_COLOR_GREEN
var/list/prize_override
var/prizeselect = /obj/item/coin/arcade_token
- light_color = LIGHT_COLOR_GREEN
/obj/machinery/computer/arcade/proc/Reset()
return
@@ -319,6 +326,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
temp = "You have been crushed! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff_exponent = 10)
if(obj_flags & EMAGGED)
+ usr.investigate_log("has been gibbed by an emagged Orion Trail game.", INVESTIGATE_DEATHS)
usr.gib()
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal")))
@@ -523,6 +531,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
if(obj_flags & EMAGGED)
to_chat(user, "You're never going to make it to Orion...")
+ user.investigate_log("has been killed by an emagged Orion Trail game.", INVESTIGATE_DEATHS)
user.death()
obj_flags &= ~EMAGGED //removes the emagged status after you lose
gameStatus = ORION_STATUS_START
@@ -730,6 +739,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
if(settlers.len == 0 || alive == 0)
say("The last crewmember [sheriff], shot themselves, GAME OVER!")
if(obj_flags & EMAGGED)
+ usr.investigate_log("has been killed by an emagged Orion Trail game.", INVESTIGATE_DEATHS)
usr.death(0)
obj_flags &= EMAGGED
gameStatus = ORION_STATUS_GAMEOVER
@@ -742,6 +752,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
else if(obj_flags & EMAGGED)
if(usr.name == sheriff)
say("The crew of the ship chose to kill [usr.name]!")
+ usr.investigate_log("has been killed by an emagged Orion Trail game.", INVESTIGATE_DEATHS)
usr.death(0)
if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm
index 1b0feb1bc5e6a..98ca8c0d0d025 100644
--- a/code/game/machinery/computer/atmos_alert.dm
+++ b/code/game/machinery/computer/atmos_alert.dm
@@ -2,8 +2,6 @@
name = "atmospheric alert console"
desc = "Used to monitor the station's air alarms."
circuit = /obj/item/circuitboard/computer/atmos_alert
-
-
icon_screen = "alert:0"
icon_keyboard = "atmos_key"
var/list/priority_alarms = list()
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index bf2627496eaea..9d968c7b3fefe 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -227,6 +227,13 @@
icon_state = "television"
icon_keyboard = "no_keyboard"
icon_screen = "detective_tv"
+
+ //these muthafuckas arent supposed to smooth
+ base_icon_state = null
+ smoothing_flags = null
+ smoothing_groups = null
+ canSmoothWith = null
+
clockwork = TRUE //it'd look weird
broken_overlay_emissive = TRUE
pass_flags = PASSTABLE
@@ -270,6 +277,13 @@
desc = "Used for watching an empty arena."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "telescreen"
+
+ //these muthafuckas arent supposed to smooth
+ base_icon_state = null
+ smoothing_flags = null
+ smoothing_groups = null
+ canSmoothWith = null
+
layer = SIGN_LAYER
network = list("thunder")
density = FALSE
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index 47ef94de0934b..37fc014ee75b4 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -16,7 +16,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
name = "identification console"
desc = "You can use this to manage jobs and ID access."
icon_screen = "id"
- icon_keyboard = "id_key"
+ icon_keyboard = "generic_key"
req_one_access = list(ACCESS_HEADS, ACCESS_CHANGE_IDS)
circuit = /obj/item/circuitboard/computer/card
var/mode = 0
diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm
index 6bee8ce4c83f5..17334db4e8ded 100644
--- a/code/game/machinery/computer/dna_console.dm
+++ b/code/game/machinery/computer/dna_console.dm
@@ -23,6 +23,27 @@
/// Flag for the mutation ref search system. Search will include advanced injector mutations
#define SEARCH_ADV_INJ 8
+/// Boilerplate define for whenever a cooldown is upgraded.
+/// This will recalculate the current timeout if the given cooldown is currently active.
+#define CALCULATE_UPGRADED_TIMEOUT(cd_index, to_index, new_length) \
+ do { \
+ var/_L = FLOOR(##new_length, 5 SECONDS); \
+ var/_CT = src.to_index##_timeout; \
+ if(!isnum_safe(_CT) || _CT <= 0) { \
+ src.cd_index##_cooldown = 0; \
+ src.to_index##_timeout = _L; \
+ break; \
+ } else if(_L >= _CT) { \
+ break; \
+ } \
+ src.to_index##_timeout = _L; \
+ var/_CD = src.cd_index##_cooldown; \
+ if(!isnum_safe(_CD) || world.time >= _CD) { \
+ break; \
+ } \
+ src.cd_index##_cooldown = FLOOR(_L * FLOOR((_CD - world.time) / _CT, 0.05), 1 SECONDS); \
+ } while(0)
+
/obj/machinery/computer/scan_consolenew
name = "\improper DNA scanner access console"
@@ -60,9 +81,28 @@
///the max instability of the advanced injector.
var/max_injector_instability = 40
- var/injectorready = 0 //world timer cooldown var
- var/jokerready = 0
- var/scrambleready = 0
+ /// Cooldown for dispensing injectors.
+ COOLDOWN_DECLARE(injector_cooldown)
+ /// Cooldown for scrambling DNA.
+ COOLDOWN_DECLARE(scramble_cooldown)
+ /// Cooldown for using the joker thingy.
+ COOLDOWN_DECLARE(joker_cooldown)
+ /// The timeout for dispensing DNA activators.
+ var/activator_timeout = INJECTOR_TIMEOUT
+ /// The timeout for dispensing DNA mutators.
+ var/mutator_timeout = INJECTOR_TIMEOUT * 5
+ /// The timeout for dispensing DNA nullifiers.
+ var/nullifier_timeout = INJECTOR_TIMEOUT * 3
+ /// The timeout for dispensing advanced DNA injectors.
+ var/advanced_timeout = INJECTOR_TIMEOUT * 8
+ /// The timeout for activating a gene on someone actually in the scanner.
+ var/activate_timeout = INJECTOR_TIMEOUT * 0.1
+ /// The timeout for mutating a gene on someone actually in the scanner.
+ var/mutate_timeout = INJECTOR_TIMEOUT * 0.5
+ /// The timeout for scrambling DNA.
+ var/scramble_timeout = SCRAMBLE_TIMEOUT
+ /// The timeout for joker.
+ var/joker_timeout = JOKER_TIMEOUT
var/current_screen = "mainmenu"
var/current_mutation //what block are we inspecting? only used when screen = "info"
var/current_storage //what storage block are we looking at?
@@ -73,7 +113,7 @@
/// Index of the enzyme being modified during delayed enzyme pulse operations
var/rad_pulse_index = 0
/// World time when the enzyme pulse should complete
- var/rad_pulse_timer = 0
+ COOLDOWN_DECLARE(rad_pulse_timer)
/// Used for setting tgui data - Whether the connected DNA Scanner is usable
var/can_use_scanner = FALSE
@@ -124,20 +164,14 @@
// This is for pulsing the UI element with radiation as part of genetic makeup
// If rad_pulse_index > 0 then it means we're attempting a rad pulse
- if((rad_pulse_index > 0) && (rad_pulse_timer <= world.time))
+ if((rad_pulse_index > 0) && !COOLDOWN_FINISHED(src, rad_pulse_timer))
rad_pulse()
return
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
- if (istype(I, /obj/item/disk/data)) //INSERT SOME DISKETTES
- if (!src.diskette)
- if (!user.transferItemToLoc(I,src))
- return
- src.diskette = I
- to_chat(user, "You insert [I].")
- src.updateUsrDialog()
- return
- if (istype(I, /obj/item/chromosome))
+ if(insert_disk(user, I)) //INSERT SOME DISKETTES
+ return
+ if(istype(I, /obj/item/chromosome))
if(LAZYLEN(stored_chromosomes) < max_chromosomes)
I.forceMove(src)
stored_chromosomes += I
@@ -148,14 +182,14 @@
if(istype(I, /obj/item/dnainjector/activator))
var/obj/item/dnainjector/activator/A = I
if(A.used)
- to_chat(user,"Recycled [I].")
+ to_chat(user, "Recycled [I].")
if(A.filled)
var/c_typepath = generate_chromosome()
var/obj/item/chromosome/CM = new c_typepath (drop_location())
if(LAZYLEN(stored_chromosomes) < max_chromosomes)
CM.forceMove(src)
stored_chromosomes += CM
- to_chat(user,"[capitalize(CM.name)] added to storage.")
+ to_chat(user, "[capitalize(CM.name)] added to storage.")
qdel(I)
return
@@ -172,9 +206,21 @@
// Make sure the user can interact with the machine.
if(!user.canUseTopic(src, !issilicon(user)))
return
-
eject_disk(user)
+/obj/machinery/computer/scan_consolenew/proc/calculate_timeouts()
+ if(!scanner_operational())
+ return
+ var/precision = max(1, connected_scanner.precision_coeff)
+ var/precise_injector_timeout = INJECTOR_TIMEOUT * (1 - 0.1 * precision)
+ CALCULATE_UPGRADED_TIMEOUT(injector, mutator, precise_injector_timeout * 5)
+ CALCULATE_UPGRADED_TIMEOUT(injector, activator, precise_injector_timeout)
+ CALCULATE_UPGRADED_TIMEOUT(injector, nullifier, precise_injector_timeout * 3)
+ CALCULATE_UPGRADED_TIMEOUT(injector, advanced, precise_injector_timeout * 8)
+ CALCULATE_UPGRADED_TIMEOUT(injector, activate, precise_injector_timeout * 0.1)
+ CALCULATE_UPGRADED_TIMEOUT(injector, mutate, precise_injector_timeout * 0.5)
+ CALCULATE_UPGRADED_TIMEOUT(joker, joker, JOKER_TIMEOUT - (JOKER_UPGRADE * (precision - 1)))
+
/obj/machinery/computer/scan_consolenew/proc/connect_to_scanner()
var/obj/machinery/dna_scannernew/test_scanner = null
var/obj/machinery/dna_scannernew/broken_scanner = null
@@ -189,8 +235,7 @@
if(test_scanner.is_operational)
connect_scanner(test_scanner)
return
- else
- broken_scanner = test_scanner
+ broken_scanner = test_scanner
// Ultimately, if we have a broken scanner, we'll attempt to connect to it as
// a fallback case, but the code above will prefer a working scanner
@@ -207,6 +252,7 @@
RegisterSignal(scanner, COMSIG_MACHINE_CLOSE, PROC_REF(on_scanner_close))
connected_scanner = scanner
+ calculate_timeouts()
/obj/machinery/computer/scan_consolenew/Initialize(mapload)
. = ..()
@@ -216,9 +262,9 @@
// Set the default tgui state
set_default_state()
- injectorready = world.time + INJECTOR_TIMEOUT
- scrambleready = world.time + SCRAMBLE_TIMEOUT
- jokerready = world.time + JOKER_TIMEOUT
+ COOLDOWN_START(src, injector_cooldown, INJECTOR_TIMEOUT)
+ COOLDOWN_START(src, scramble_cooldown, scramble_timeout)
+ COOLDOWN_START(src, joker_cooldown, joker_timeout)
stored_research = SSresearch.science_tech
@@ -250,17 +296,17 @@
build_genetic_makeup_list()
// Populate variables for passing to tgui interface
- is_scramble_ready = (scrambleready < world.time)
- time_to_scramble = round((scrambleready - world.time)/10)
+ is_scramble_ready = COOLDOWN_FINISHED(src, scramble_cooldown)
+ time_to_scramble = round(COOLDOWN_TIMELEFT(src, scramble_cooldown) / 10)
- is_joker_ready = (jokerready < world.time)
- time_to_joker = round((jokerready - world.time)/10)
+ is_injector_ready = COOLDOWN_FINISHED(src, injector_cooldown)
+ time_to_injector = round(COOLDOWN_TIMELEFT(src, injector_cooldown) / 10)
- is_injector_ready = (injectorready < world.time)
- time_to_injector = round((injectorready - world.time)/10)
+ is_joker_ready = COOLDOWN_FINISHED(src, joker_cooldown)
+ time_to_joker = round(COOLDOWN_TIMELEFT(src, joker_cooldown) / 10)
- is_pulsing_rads = ((rad_pulse_index > 0) && (rad_pulse_timer > world.time))
- time_to_pulse = round((rad_pulse_timer - world.time)/10)
+ is_pulsing_rads = ((rad_pulse_index > 0) && !COOLDOWN_FINISHED(src, rad_pulse_timer))
+ time_to_pulse = round(COOLDOWN_TIMELEFT(src, rad_pulse_timer) / 10)
// Attempt to update tgui ui, open and update if needed.
ui = SStgui.try_update_ui(user, src, ui)
@@ -271,10 +317,10 @@
/obj/machinery/computer/scan_consolenew/examine(mob/user)
. = ..()
- if(jokerready < world.time)
+ if(COOLDOWN_FINISHED(src, joker_cooldown))
. += "JOKER algorithm available."
else
- . += "JOKER algorithm available in about [round(0.00166666667 * (jokerready - world.time))] minutes."
+ . += "JOKER algorithm available in around [DisplayTimeText(round(COOLDOWN_TIMELEFT(src, joker_cooldown), 15 SECONDS))]."
/obj/machinery/computer/scan_consolenew/ui_assets()
. = ..() || list()
@@ -413,14 +459,14 @@
// GUARD CHECK - Can we genetically modify the occupant? Includes scanner
// operational guard checks.
// GUARD CHECK - Is scramble DNA actually ready?
- if(!can_modify_occupant() || !(scrambleready < world.time))
+ if(!can_modify_occupant() || !COOLDOWN_FINISHED(src, scramble_cooldown))
return
scanner_occupant.dna.remove_all_mutations(list(MUT_NORMAL, MUT_EXTRA))
scanner_occupant.dna.generate_dna_blocks()
- scrambleready = world.time + SCRAMBLE_TIMEOUT
- to_chat(usr,"DNA scrambled.")
- scanner_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER*50/(connected_scanner.damage_coeff ** 2)
+ COOLDOWN_START(src, scramble_cooldown, SCRAMBLE_TIMEOUT)
+ to_chat(usr, "DNA scrambled.")
+ scanner_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER * 50 / (connected_scanner.damage_coeff ** 2)
return
// Check whether a specific mutation is eligible for discovery within the
@@ -493,7 +539,7 @@
// GUARD CHECK - Is the occupant currently undergoing some form of
// transformation? If so, we don't want to be pulsing genes.
if(scanner_occupant.transformation_timer)
- to_chat(usr,"Gene pulse failed: The scanner occupant undergoing a transformation.")
+ to_chat(usr, "Gene pulse failed: The scanner occupant undergoing a transformation.")
return
// Resolve mutation's BYOND path from the alias
@@ -515,10 +561,10 @@
// If the new gene is J, this means we're dealing with a JOKER
// GUARD CHECK - Is JOKER actually ready?
- if((newgene == "J") && (jokerready < world.time))
+ if((newgene == "J") && COOLDOWN_FINISHED(src, joker_cooldown))
var/truegenes = GET_SEQUENCE(path)
newgene = truegenes[genepos]
- jokerready = world.time + JOKER_TIMEOUT - (JOKER_UPGRADE * (connected_scanner.precision_coeff-1))
+ COOLDOWN_START(src, joker_cooldown, joker_timeout)
// If the gene is an X, we want to update the default genes with the new
// X to allow highlighting logic to work on the tgui interface.
@@ -531,7 +577,7 @@
// we've increased the occupant rads
sequence = copytext_char(sequence, 1, genepos) + newgene + copytext_char(sequence, genepos + 1)
scanner_occupant.dna.mutation_index[path] = sequence
- scanner_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER/connected_scanner.damage_coeff
+ scanner_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER / connected_scanner.damage_coeff
scanner_occupant.domutcheck()
// GUARD CHECK - Modifying genetics can lead to edge cases where the
@@ -605,7 +651,7 @@
// identify mutations from big ol' lists
// GUARD CHECK - Is the injector actually ready?
- if(world.time < injectorready)
+ if(!COOLDOWN_FINISHED(src, injector_cooldown))
return
var/search_flags = 0
@@ -643,9 +689,9 @@
// printing nullifiers a lot wouldn't be good, so it has some cooldown
if(scanner_operational())
I.damage_coeff = connected_scanner.damage_coeff
- injectorready = world.time + INJECTOR_TIMEOUT * 3 * (1 - 0.1 * connected_scanner.precision_coeff)
+ COOLDOWN_START(src, injector_cooldown, nullifier_timeout)
else
- injectorready = world.time + INJECTOR_TIMEOUT * 3
+ COOLDOWN_START(src, injector_cooldown, initial(nullifier_timeout))
return
@@ -663,10 +709,10 @@
// If there's an operational connected scanner, we can use its upgrades
// to improve our injector's radiation generation
if(scanner_operational())
- I.damage_coeff = connected_scanner.damage_coeff*4
- injectorready = world.time + INJECTOR_TIMEOUT * (1 - 0.1 * connected_scanner.precision_coeff)
+ I.damage_coeff = connected_scanner.damage_coeff * 4
+ COOLDOWN_START(src, injector_cooldown, activator_timeout)
else
- injectorready = world.time + INJECTOR_TIMEOUT
+ COOLDOWN_START(src, injector_cooldown, initial(activator_timeout))
else
I.name = "DNA mutator"
I.desc = "Adds the current mutation on injection, at the cost of genetic stability."
@@ -675,9 +721,9 @@
// to improve our injector's radiation generation
if(scanner_operational())
I.damage_coeff = connected_scanner.damage_coeff
- injectorready = world.time + INJECTOR_TIMEOUT * 5 * (1 - 0.1 * connected_scanner.precision_coeff)
+ COOLDOWN_START(src, injector_cooldown, mutator_timeout)
else
- injectorready = world.time + INJECTOR_TIMEOUT * 5
+ COOLDOWN_START(src, injector_cooldown, initial(mutator_timeout))
return
@@ -695,11 +741,7 @@
scanner_occupant.dna.activate_mutation(HM)
log_game("[key_name(usr)] activated [HM] in [key_name(scanner_occupant)] [loc_name(usr)]")
-
- if(scanner_operational())
- injectorready = world.time + INJECTOR_TIMEOUT * 0.1 * (1 - 0.1 * connected_scanner.precision_coeff)
- else
- injectorready = world.time + INJECTOR_TIMEOUT * 0.1
+ COOLDOWN_START(src, injector_cooldown, scanner_operational() ? activate_timeout : initial(activate_timeout))
if(scanner_occupant?.client)
var/c_typepath = generate_chromosome()
@@ -707,7 +749,7 @@
if(LAZYLEN(stored_chromosomes) < max_chromosomes)
CM.forceMove(src)
stored_chromosomes += CM
- to_chat(usr,"[capitalize(CM.name)] added to storage.")
+ to_chat(usr, "[capitalize(CM.name)] added to storage.")
//Creates a new MUT_EXTRA mutation in subject
if("add_mutation")
@@ -732,10 +774,7 @@
else
scanner_occupant.dna.add_mutation(HM, MUT_EXTRA)
- if(scanner_operational())
- injectorready = world.time + INJECTOR_TIMEOUT * 0.5 * (1 - 0.1 * connected_scanner.precision_coeff)
- else
- injectorready = world.time + INJECTOR_TIMEOUT * 0.5
+ COOLDOWN_START(src, injector_cooldown, scanner_operational() ? mutate_timeout : initial(mutate_timeout))
log_game("[key_name(usr)] added [HM] to [key_name(scanner_occupant)] [loc_name(usr)]")
@@ -762,7 +801,7 @@
// GUARD CHECK - Is mutation storage full?
if(LAZYLEN(stored_mutations) >= max_storage)
- to_chat(usr,"Mutation storage is full.")
+ to_chat(usr, "Mutation storage is full.")
return
var/bref = params["mutref"]
@@ -775,7 +814,7 @@
var/datum/mutation/A = new HM.type()
A.copy_mutation(HM)
stored_mutations += A
- to_chat(usr,"Mutation successfully stored.")
+ to_chat(usr, "Mutation successfully stored.")
return
// Save a mutation to the diskette's storage buffer.
@@ -793,13 +832,13 @@
// GUARD CHECK - Make sure the disk is not full
if(LAZYLEN(diskette.mutations) >= diskette.max_mutations)
- to_chat(usr,"Disk storage is full.")
+ to_chat(usr, "Disk storage is full.")
return
// GUARD CHECK - Make sure the disk isn't set to read only, as we're
// attempting to write to it
if(diskette.read_only)
- to_chat(usr,"Disk is set to read only mode.")
+ to_chat(usr, "Disk is set to read only mode.")
return
var/search_flags = 0
@@ -825,7 +864,7 @@
var/datum/mutation/A = new HM.type()
A.copy_mutation(HM)
diskette.mutations += A
- to_chat(usr,"Mutation successfully stored to disk.")
+ to_chat(usr, "Mutation successfully stored to disk.")
return
// Completely removes a MUT_EXTRA mutation or mutation with corrupt gene
@@ -847,7 +886,7 @@
// GUARD CHECK - Nullify should only be used on scrambled or "extra"
// mutations.
- if(!HM.scrambled && !(HM.class == MUT_EXTRA))
+ if(!HM.scrambled && HM.class != MUT_EXTRA)
return
scanner_occupant.dna.remove_mutation(HM.type)
@@ -878,7 +917,7 @@
// GUARD CHECK - Make sure the disk isn't set to read only, as we're
// attempting to write to it (via deletion)
if(diskette.read_only)
- to_chat(usr,"Disk is set to read only mode.")
+ to_chat(usr, "Disk is set to read only mode.")
return
var/bref = params["mutref"]
@@ -914,7 +953,7 @@
// GUaRD CHECK - Make sure mutation storage isn't full. If it is, we won't
// be able to store the new combo mutation
if(LAZYLEN(stored_mutations) >= max_storage)
- to_chat(usr,"Mutation storage is full.")
+ to_chat(usr, "Mutation storage is full.")
return
// GUARD CHECK - We're running a research-type operation. If, for some
@@ -970,13 +1009,13 @@
// GUARD CHECK - Make sure the disk is not full.
if(LAZYLEN(diskette.mutations) >= diskette.max_mutations)
- to_chat(usr,"Disk storage is full.")
+ to_chat(usr, "Disk storage is full.")
return
// GUARD CHECK - Make sure the disk isn't set to read only, as we're
// attempting to write to it
if(diskette.read_only)
- to_chat(usr,"Disk is set to read only mode.")
+ to_chat(usr, "Disk is set to read only mode.")
return
// GUARD CHECK - We're running a research-type operation. If, for some
@@ -1050,7 +1089,7 @@
// GUARD CHECK - Make sure the disk isn't set to read only, as we're
// attempting to write to it
if(diskette.read_only)
- to_chat(usr,"Disk is set to read only mode.")
+ to_chat(usr, "Disk is set to read only mode.")
return
// Convert the index to a number and clamp within the array range
@@ -1099,7 +1138,7 @@
// GUARD CHECK - Make sure the disk isn't set to read only, as we're
// attempting to write (via deletion) to it
if(diskette.read_only)
- to_chat(usr,"Disk is set to read only mode.")
+ to_chat(usr, "Disk is set to read only mode.")
return
diskette.genetic_makeup_buffer.Cut()
@@ -1123,11 +1162,12 @@
// Set the new information
genetic_makeup_buffer[buffer_index] = list(
- "label"="Slot [buffer_index]:[scanner_occupant.real_name]",
- "UI"=scanner_occupant.dna.uni_identity,
- "UE"=scanner_occupant.dna.unique_enzymes,
- "name"=scanner_occupant.real_name,
- "blood_type"=scanner_occupant.dna.blood_type)
+ "name" = scanner_occupant.real_name,
+ "label" = "Slot [buffer_index]:[scanner_occupant.real_name]",
+ "UI" = scanner_occupant.dna.uni_identity,
+ "UE" = scanner_occupant.dna.unique_enzymes,
+ "blood_type" = scanner_occupant.dna.blood_type
+ )
return
@@ -1188,11 +1228,11 @@
// However, if this is the case, we can't make a complete injector and
// this catches that edge case
if(!buffer_slot["UI"])
- to_chat(usr,"Genetic data corrupted, unable to create injector.")
+ to_chat(usr, "Genetic data corrupted, unable to create injector.")
return
I = new /obj/item/dnainjector/timed(loc)
- I.fields = list("UI"=buffer_slot["UI"])
+ I.fields = list("UI" = buffer_slot["UI"])
// If there is a connected scanner, we can use its upgrades to reduce
// the radiation generated by this injector
@@ -1203,11 +1243,15 @@
// However, if this is the case, we can't make a complete injector and
// this catches that edge case
if(!buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"])
- to_chat(usr,"Genetic data corrupted, unable to create injector.")
+ to_chat(usr, "Genetic data corrupted, unable to create injector.")
return
I = new /obj/item/dnainjector/timed(loc)
- I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"])
+ I.fields = list(
+ "name" = buffer_slot["name"],
+ "UE" = buffer_slot["UE"],
+ "blood_type" = buffer_slot["blood_type"]
+ )
// If there is a connected scanner, we can use its upgrades to reduce
// the radiation generated by this injector
@@ -1218,11 +1262,16 @@
// However, if this is the case, we can't make a complete injector and
// this catches that edge case
if(!buffer_slot["UI"] || !buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"])
- to_chat(usr,"Genetic data corrupted, unable to create injector.")
+ to_chat(usr, "Genetic data corrupted, unable to create injector.")
return
I = new /obj/item/dnainjector/timed(loc)
- I.fields = list("UI"=buffer_slot["UI"],"name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"])
+ I.fields = list(
+ "name" = buffer_slot["name"],
+ "UI" = buffer_slot["UI"],
+ "UE" = buffer_slot["UE"],
+ "blood_type" = buffer_slot["blood_type"]
+ )
// If there is a connected scanner, we can use its upgrades to reduce
// the radiation generated by this injector
@@ -1232,7 +1281,7 @@
// If we successfully created an injector, don't forget to set the new
// ready timer.
if(I)
- injectorready = world.time + INJECTOR_TIMEOUT
+ COOLDOWN_START(src, injector_cooldown, mutator_timeout)
return
@@ -1316,8 +1365,8 @@
// Set the appropriate timer and index to pulse. This is then managed
// later on in process()
var/len = length_char(scanner_occupant.dna.uni_identity)
- rad_pulse_timer = world.time + (radduration*10)
- rad_pulse_index = WRAP(text2num(params["index"]), 1, len+1)
+ COOLDOWN_START(src, rad_pulse_timer, radduration * 10)
+ rad_pulse_index = WRAP(text2num(params["index"]), 1, len + 1)
START_PROCESSING(SSobj, src)
return
@@ -1377,7 +1426,7 @@
// identify mutations from big ol' lists.
// GUARD CHECK - Is the injector actually ready?
- if(world.time < injectorready)
+ if(!COOLDOWN_FINISHED(src, injector_cooldown))
return
var/inj_name = params["name"]
@@ -1405,9 +1454,9 @@
// to improve our injector's radiation generation
if(scanner_operational())
I.damage_coeff = connected_scanner.damage_coeff
- injectorready = world.time + INJECTOR_TIMEOUT * 8 * (1 - 0.1 * connected_scanner.precision_coeff)
+ COOLDOWN_START(src, injector_cooldown, advanced_timeout)
else
- injectorready = world.time + INJECTOR_TIMEOUT * 8
+ COOLDOWN_START(src, injector_cooldown, initial(advanced_timeout))
return
@@ -1432,7 +1481,7 @@
// GUARD CHECK - Make sure we limit the number of mutations appropriately
if(LAZYLEN(injector_selection[adv_inj]) >= max_injector_mutations)
- to_chat(usr,"Advanced injector mutation storage is full.")
+ to_chat(usr, "Advanced injector mutation storage is full.")
return
var/mut_source = params["source"]
@@ -1469,7 +1518,7 @@
// If this would take us over the max instability, we inform the user.
if(instability_total > max_injector_instability)
- to_chat(usr,"Extra mutation would make the advanced injector too instable.")
+ to_chat(usr, "Extra mutation would make the advanced injector too instable.")
return
// If we've got here, all our checks are passed and we can successfully
@@ -1477,7 +1526,7 @@
var/datum/mutation/A = new HM.type()
A.copy_mutation(HM)
injector_selection[adv_inj] += A
- to_chat(usr,"Mutation successfully added to advanced injector.")
+ to_chat(usr, "Mutation successfully added to advanced injector.")
return
// Deletes a mutation from an advanced injector
@@ -1530,7 +1579,7 @@
// Pre-calc the rad increase since we'll be using it in all the possible
// operations
- var/rad_increase = rand(100/(connected_scanner.damage_coeff ** 2),250/(connected_scanner.damage_coeff ** 2))
+ var/rad_increase = rand(100 / (connected_scanner.damage_coeff ** 2), 250 / (connected_scanner.damage_coeff ** 2))
switch(type)
if("ui")
@@ -1538,10 +1587,10 @@
// However, if this is the case, we can't make a complete injector and
// this catches that edge case
if(!buffer_slot["UI"])
- to_chat(usr,"Genetic data corrupted, unable to apply genetic data.")
+ to_chat(usr, "Genetic data corrupted, unable to apply genetic data.")
return FALSE
scanner_occupant.dna.uni_identity = buffer_slot["UI"]
- scanner_occupant.updateappearance(mutations_overlay_update=1)
+ scanner_occupant.updateappearance(mutations_overlay_update = 1)
scanner_occupant.radiation += rad_increase
scanner_occupant.domutcheck()
return TRUE
@@ -1550,7 +1599,7 @@
// However, if this is the case, we can't make a complete injector and
// this catches that edge case
if(!buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"])
- to_chat(usr,"Genetic data corrupted, unable to apply genetic data.")
+ to_chat(usr, "Genetic data corrupted, unable to apply genetic data.")
return FALSE
scanner_occupant.real_name = buffer_slot["name"]
scanner_occupant.name = buffer_slot["name"]
@@ -1564,10 +1613,10 @@
// However, if this is the case, we can't make a complete injector and
// this catches that edge case
if(!buffer_slot["UI"] || !buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"])
- to_chat(usr,"Genetic data corrupted, unable to apply genetic data.")
+ to_chat(usr, "Genetic data corrupted, unable to apply genetic data.")
return FALSE
scanner_occupant.dna.uni_identity = buffer_slot["UI"]
- scanner_occupant.updateappearance(mutations_overlay_update=1)
+ scanner_occupant.updateappearance(mutations_overlay_update = 1)
scanner_occupant.real_name = buffer_slot["name"]
scanner_occupant.name = buffer_slot["name"]
scanner_occupant.dna.unique_enzymes = buffer_slot["UE"]
@@ -1582,10 +1631,7 @@
* Checks if there is a connected DNA Scanner that is operational
*/
/obj/machinery/computer/scan_consolenew/proc/scanner_operational()
- if(!connected_scanner)
- return FALSE
-
- return (connected_scanner && connected_scanner.is_operational && !connected_scanner.wires.is_cut(WIRE_LIMIT))
+ return !QDELETED(connected_scanner) && connected_scanner.is_operational && !connected_scanner.wires?.is_cut(WIRE_LIMIT)
/**
* Checks if there is a valid DNA Scanner occupant for genetic modification
@@ -1654,7 +1700,7 @@
// If we had a radiation pulse action ongoing, we want to stop this.
// Imagine it being like a microwave stopping when you open the door.
rad_pulse_index = 0
- rad_pulse_timer = 0
+ COOLDOWN_RESET(src, rad_pulse_timer)
STOP_PROCESSING(SSobj, src)
scanner_occupant = null
@@ -2000,7 +2046,7 @@
*/
/obj/machinery/computer/scan_consolenew/proc/randomize_radiation_accuracy(position, radduration, number_of_blocks)
var/val = round(gaussian(0, RADIATION_ACCURACY_MULTIPLIER/radduration) + position, 1)
- return WRAP(val, 1, number_of_blocks+1)
+ return WRAP(val, 1, number_of_blocks + 1)
/**
* Scrambles an enzyme element value for the enzyme pulse functionality.
@@ -2013,14 +2059,15 @@
*/
/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs)
var/length = length(input)
- var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER)
- if(ran == 0)
- ran = pick(-1,1) //hacky, statistically should almost never happen. 0-chance makes people mad though
- else if(ran < 0)
- ran = round(ran) //negative, so floor it
- else
- ran = -round(-ran) //positive, so ceiling it
- return num2hex(WRAP(hex2num(input)+ran, 0, 16**length), length)
+ var/ran = gaussian(0, rs * RADIATION_STRENGTH_MULTIPLIER)
+ switch(ran)
+ if(0)
+ ran = pick(-1, 1) //hacky, statistically should almost never happen. 0-chance makes people mad though
+ if(-INFINITY to 0)
+ ran = round(ran) //negative, so floor it
+ else
+ ran = -round(-ran) //positive, so ceiling it
+ return num2hex(WRAP(hex2num(input) + ran, 0, 16 ** length), length)
/**
* Performs the enzyme radiation pulse.
@@ -2039,11 +2086,11 @@
var/len = length_char(scanner_occupant.dna.uni_identity)
var/num = randomize_radiation_accuracy(rad_pulse_index, radduration + (connected_scanner.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2 //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
- var/hex = copytext_char(scanner_occupant.dna.uni_identity, num, num+1)
+ var/hex = copytext_char(scanner_occupant.dna.uni_identity, num, num + 1)
hex = scramble(hex, radstrength, radduration)
scanner_occupant.dna.uni_identity = copytext_char(scanner_occupant.dna.uni_identity, 1, num) + hex + copytext_char(scanner_occupant.dna.uni_identity, num + 1)
- scanner_occupant.updateappearance(mutations_overlay_update=1)
+ scanner_occupant.updateappearance(mutations_overlay_update = 1)
rad_pulse_index = 0
STOP_PROCESSING(SSobj, src)
@@ -2058,6 +2105,24 @@
tgui_view_state["storageConsSubMode"] = "mutations"
tgui_view_state["storageDiskSubMode"] = "mutations"
+/obj/machinery/computer/scan_consolenew/proc/insert_disk(mob/living/user, obj/item/disk/data/diskie)
+ if(!QDELETED(diskette) || !istype(user) || !istype(diskie) || !user.transferItemToLoc(diskie, src))
+ return FALSE
+ diskette = diskie
+ to_chat(user, "You insert [diskie].")
+ if(stored_research)
+ var/list/upload_names
+ for(var/datum/mutation/upload in diskie.mutations)
+ var/path = upload.type
+ if(stored_research.discovered_mutations[path])
+ continue
+ stored_research.discovered_mutations[path] = TRUE
+ LAZYADD(upload_names, upload.name)
+ if(LAZYLEN(upload_names))
+ say("Successfully uploaded [english_list(upload_names)] from disk.")
+ updateUsrDialog()
+ return TRUE
+
/**
* Ejects the DNA Disk from the console.
*
@@ -2088,6 +2153,8 @@
to_chat(user, "You bypass [src]'s access requirements.")
/////////////////////////// DNA MACHINES
+
+#undef CALCULATE_UPGRADED_TIMEOUT
#undef INJECTOR_TIMEOUT
#undef NUMBER_OF_BUFFERS
#undef SCRAMBLE_TIMEOUT
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 3ab882a2eda29..51308b21e7b83 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -604,6 +604,13 @@
icon_state = "laptop"
icon_screen = "medlaptop"
icon_keyboard = "laptop_key"
+
+ //these muthafuckas arent supposed to smooth
+ base_icon_state = null
+ smoothing_flags = null
+ smoothing_groups = null
+ canSmoothWith = null
+
clockwork = TRUE //it'd look weird
broken_overlay_emissive = TRUE
pass_flags = PASSTABLE
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index 41a46cc5df31f..fc73d48a5caae 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -88,15 +88,15 @@
data["cyborgs"] += list(cyborg_data)
data["drones"] = list()
- for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
- if(D.hacked)
+ for(var/mob/living/simple_animal/drone/drone in GLOB.drones_list)
+ if(drone.hacked)
continue
- if(get_virtual_z_level() != (get_turf(D)).get_virtual_z_level())
+ if(get_virtual_z_level() != (get_turf(drone)).get_virtual_z_level())
continue
var/list/drone_data = list(
- name = D.name,
- status = D.stat,
- ref = REF(D)
+ name = drone.name,
+ status = drone.stat,
+ ref = REF(drone)
)
data["drones"] += list(drone_data)
@@ -168,6 +168,7 @@
s.set_up(3, TRUE, D)
s.start()
D.visible_message("\the [D] self-destructs!")
+ D.investigate_log("has been gibbed by a robotics console.", INVESTIGATE_DEATHS)
D.gib()
if("extract")
if(!GLOB.upload_code)
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index ff114675818b8..0393a4813d9d2 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -180,6 +180,13 @@
icon_state = "laptop"
icon_screen = "seclaptop"
icon_keyboard = "laptop_key"
+
+ //these muthafuckas arent supposed to smooth
+ base_icon_state = null
+ smoothing_flags = null
+ smoothing_groups = null
+ canSmoothWith = null
+
clockwork = TRUE //it'd look weird
broken_overlay_emissive = TRUE
pass_flags = PASSTABLE
@@ -583,7 +590,7 @@ What a mess.*/
default_description += "[c.crimeDetails]\n"
var/headerText = stripped_input(usr, "Please enter Poster Heading (Max 7 Chars):", "Print Wanted Poster", "WANTED", 8)
- var/posternum = CLAMP((input("Number of posters to print (Max 5):","Number:",1) as num|null), 1, 5)
+ var/posternum = clamp((input("Number of posters to print (Max 5):","Number:",1) as num|null), 1, 5)
var/info = stripped_multiline_input(usr, "Please input a description for the poster:", "Print Wanted Poster", default_description, null)
if(info)
printing = 1
@@ -602,7 +609,7 @@ What a mess.*/
var/default_description = "A poster declaring [missing_name] to be a missing individual, missed by Nanotrasen. Report any sightings to security immediately."
var/headerText = stripped_input(usr, "Please enter Poster Heading (Max 7 Chars):", "Print Missing Persons Poster", "MISSING", 8)
- var/posternum = CLAMP((input("Number of posters to print (Max 5):","Number:",1) as num|null), 1, 5)
+ var/posternum = clamp((input("Number of posters to print (Max 5):","Number:",1) as num|null), 1, 5)
var/info = stripped_multiline_input(usr, "Please input a description for the poster:", "Print Missing Persons Poster", default_description, null)
if(info)
printing = 1
diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm
index 70abe70b40292..05bf4d60f341f 100644
--- a/code/game/machinery/computer/teleporter.dm
+++ b/code/game/machinery/computer/teleporter.dm
@@ -37,6 +37,7 @@
for(var/direction in GLOB.cardinals)
power_station = locate(/obj/machinery/teleport/station, get_step(src, direction))
if(power_station)
+ power_station.link_console_and_hub()
break
ui_update()
return power_station
diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm
index 06670913cac59..f1931a655c929 100644
--- a/code/game/machinery/dna_scanner.dm
+++ b/code/game/machinery/dna_scanner.dm
@@ -35,6 +35,9 @@
precision_coeff = M.rating
for(var/obj/item/stock_parts/micro_laser/P in component_parts)
damage_coeff = P.rating
+ for(var/obj/machinery/computer/scan_consolenew/console in view(1))
+ if(console.connected_scanner == src)
+ console.calculate_timeouts()
/obj/machinery/dna_scannernew/examine(mob/user)
. = ..()
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 78f1e89468a66..9df5f25bcb8d8 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -383,7 +383,7 @@
update_icon()
/obj/machinery/door/airlock/Bumped(atom/movable/AM)
- if(operating || (obj_flags & EMAGGED))
+ if(operating)
return
if(ismecha(AM))
var/obj/mecha/mecha = AM
@@ -493,19 +493,20 @@
ui_update()
update_icon()
-/obj/machinery/door/airlock/proc/loseMainPower()
- if(secondsMainPowerLost <= 0)
+/obj/machinery/door/airlock/proc/loseMainPower(emagged_powerloss)
+ if(emagged_powerloss)
+ secondsMainPowerLost = 36000 //Ten hours, effectively indefinite - may be reset by power cycling the airlock with a multitool or wirecutters
+ secondsBackupPowerLost = 36000
+ else
secondsMainPowerLost = 60
- if(secondsBackupPowerLost < 10)
- secondsBackupPowerLost = 10
+ secondsBackupPowerLost = clamp(10, secondsBackupPowerLost, 60)
if(!spawnPowerRestoreRunning)
spawnPowerRestoreRunning = TRUE
handlePowerRestoreLoop()
update_icon()
/obj/machinery/door/airlock/proc/loseBackupPower()
- if(secondsBackupPowerLost < 60)
- secondsBackupPowerLost = 60
+ secondsBackupPowerLost = 60
if(!spawnPowerRestoreRunning)
spawnPowerRestoreRunning = TRUE
handlePowerRestoreLoop()
@@ -710,8 +711,6 @@
/obj/machinery/door/airlock/examine(mob/user)
. = ..()
- if(obj_flags & EMAGGED)
- . += "Its access panel is smoking slightly."
if(charge && !panel_open && in_range(user, src))
. += "The maintenance panel seems haphazardly fastened."
if(charge && panel_open)
@@ -758,9 +757,6 @@
return
else
to_chat(user, "Airlock AI control has been blocked with a firewall. Unable to hack.")
- if(obj_flags & EMAGGED)
- to_chat(user, "Unable to interface: Airlock is unresponsive.")
- return
if(detonated)
to_chat(user, "Unable to interface. Airlock control panel damaged.")
return
@@ -1047,8 +1043,6 @@
if(!panel_open || security_level)
to_chat(user, "The maintenance panel must be open to apply [C]!")
return
- if(obj_flags & EMAGGED)
- return
if(charge && !detonated)
to_chat(user, "There's already a charge hooked up to this door!")
return
@@ -1151,7 +1145,7 @@
charge.forceMove(get_turf(user))
charge = null
return
- if(!security_level && (beingcrowbarred && panel_open && ((obj_flags & EMAGGED) || (density && welded && !operating && !hasPower() && !locked))))
+ if(!security_level && (beingcrowbarred && panel_open && (density && welded && !operating && !hasPower() && !locked)))
user.visible_message("[user] removes the electronics from the airlock assembly.", \
"You start to remove electronics from the airlock assembly...")
if(I.use_tool(src, user, 40, volume=100))
@@ -1170,7 +1164,7 @@
INVOKE_ASYNC(src, (density ? PROC_REF(open) : PROC_REF(close)), 2)
-/obj/machinery/door/airlock/open(forced=0, ignore_emagged = FALSE)
+/obj/machinery/door/airlock/open(forced=0)
if( operating || welded || locked )
return FALSE
if(!forced)
@@ -1191,8 +1185,6 @@
H.apply_damage(40, BRUTE, BODY_ZONE_CHEST)
return
if(forced < 2)
- if(!ignore_emagged && (obj_flags & EMAGGED))
- return FALSE
if(!protected_door)
use_power(50)
playsound(src, doorOpen, 30, 1)
@@ -1243,8 +1235,6 @@
return
if(forced < 2)
- if(obj_flags & EMAGGED)
- return
if(!protected_door)
use_power(50)
playsound(src, doorClose, 30, TRUE)
@@ -1286,8 +1276,6 @@
return TRUE
/obj/machinery/door/airlock/proc/prison_open()
- if(obj_flags & EMAGGED)
- return
locked = FALSE
open()
locked = TRUE
@@ -1329,9 +1317,8 @@
//Airlock is passable if it is open (!density), bot has access, and is not bolted shut or powered off)
return !density || (check_access(ID) && !locked && hasPower())
+///This does not call parent because airlocks should be possible to emag multiple times. We only care that the door is closed, not protected and has power.
/obj/machinery/door/airlock/should_emag(mob/user)
- if(!..())
- return FALSE
if(protected_door)
to_chat(user, "[src] has no maintenance panel!")
return FALSE
@@ -1351,12 +1338,10 @@
if(QDELETED(src))
return
operating = FALSE
- if(!open(ignore_emagged = TRUE))
+ if(!open())
update_icon(AIRLOCK_CLOSED, 1)
- lights = FALSE
- locked = TRUE
- loseMainPower()
- loseBackupPower()
+ bolt()
+ loseMainPower(TRUE)
/obj/machinery/door/airlock/attack_alien(mob/living/carbon/alien/humanoid/user)
add_fingerprint(user)
@@ -1451,9 +1436,6 @@
if(!disassembled)
if(A)
A.obj_integrity = A.max_integrity * 0.5
- else if(obj_flags & EMAGGED)
- if(user)
- to_chat(user, "You discard the damaged electronics.")
else
if(user)
to_chat(user, "You remove the airlock electronics.")
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index c3087a4e3e4c4..39af859b4576a 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -93,7 +93,7 @@
/obj/machinery/door/Bumped(atom/movable/AM)
. = ..()
- if(operating || (obj_flags & EMAGGED))
+ if(operating)
return
if(ismob(AM))
var/mob/B = AM
@@ -148,7 +148,7 @@
/// Helper method for bumpopen() and try_to_activate_door(). Don't override.
/obj/machinery/door/proc/activate_door_base(mob/user, can_close_door)
add_fingerprint(user)
- if(operating || (obj_flags & EMAGGED))
+ if(operating)
return
// Cutting WIRE_IDSCAN disables normal entry
if(!id_scan_hacked() && allowed(user))
@@ -366,7 +366,7 @@
L.emote("roar")
else if(ishuman(L)) //For humans
var/armour = L.run_armor_check(BODY_ZONE_CHEST, MELEE)
- var/multiplier = CLAMP(1 - (armour * 0.01), 0, 1)
+ var/multiplier = clamp(1 - (armour * 0.01), 0, 1)
L.adjustBruteLoss(multiplier * DOOR_CRUSH_DAMAGE)
L.emote("scream")
if(!L.IsParalyzed())
diff --git a/code/game/machinery/fabricators/modular_fabricator.dm b/code/game/machinery/fabricators/modular_fabricator.dm
index 8bab13aaf825c..12debf92aa0b0 100644
--- a/code/game/machinery/fabricators/modular_fabricator.dm
+++ b/code/game/machinery/fabricators/modular_fabricator.dm
@@ -399,7 +399,7 @@
//Only items that can stack should be build en mass, since we now have queues.
if(is_stack)
multiplier = item_queue[requested_design_id]["amount"]
- multiplier = CLAMP(multiplier,1,50)
+ multiplier = clamp(multiplier,1,50)
/////////////////
diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm
index 5f53c27414d07..9a97a73531a14 100644
--- a/code/game/machinery/harvester.dm
+++ b/code/game/machinery/harvester.dm
@@ -4,6 +4,7 @@
density = TRUE
icon = 'icons/obj/machines/harvester.dmi'
icon_state = "harvester"
+ base_icon_state = "harvester"
verb_say = "states"
state_open = FALSE
idle_power_usage = 50
@@ -11,6 +12,7 @@
light_color = LIGHT_COLOR_BLUE
var/interval = 20
var/harvesting = FALSE
+ var/warming_up = FALSE
var/list/operation_order = list() //Order of which we harvest limbs.
var/allow_clothing = FALSE
var/allow_living = FALSE
@@ -27,21 +29,24 @@
max_time -= L.rating
interval = max(max_time,1)
-/obj/machinery/harvester/update_icon(warming_up)
- if(warming_up)
- icon_state = initial(icon_state)+"-charging"
- return
+/obj/machinery/harvester/update_icon_state()
if(state_open)
- icon_state = initial(icon_state)+"-open"
- else if(harvesting)
- icon_state = initial(icon_state)+"-active"
- else
- icon_state = initial(icon_state)
+ icon_state = "[base_icon_state]-open"
+ return ..()
+ if(warming_up)
+ icon_state = "[base_icon_state]-charging"
+ return ..()
+ if(harvesting)
+ icon_state = "[base_icon_state]-active"
+ return ..()
+ icon_state = base_icon_state
+ return ..()
/obj/machinery/harvester/open_machine(drop = TRUE)
if(panel_open)
return
. = ..()
+ warming_up = FALSE
harvesting = FALSE
/obj/machinery/harvester/attack_hand(mob/user)
@@ -84,14 +89,16 @@
return
var/mob/living/carbon/C = occupant
operation_order = reverseList(C.bodyparts) //Chest and head are first in bodyparts, so we invert it to make them suffer more
+ warming_up = TRUE
harvesting = TRUE
visible_message("The [name] begins warming up!")
say("Initializing harvest protocol.")
- update_icon(TRUE)
+ update_appearance()
addtimer(CALLBACK(src, PROC_REF(harvest)), interval)
/obj/machinery/harvester/proc/harvest()
- update_icon()
+ warming_up = FALSE
+ update_appearance()
if(!harvesting || state_open || !powered() || !occupant || !iscarbon(occupant))
return
playsound(src, 'sound/machines/juicer.ogg', 20, 1)
@@ -125,6 +132,7 @@
addtimer(CALLBACK(src, PROC_REF(harvest)), interval)
/obj/machinery/harvester/proc/end_harvesting()
+ warming_up = FALSE
harvesting = FALSE
open_machine()
say("Subject has been successfully harvested.")
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index f040c0b14fddb..3ee853795d291 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -259,15 +259,18 @@
can_convert = FALSE
/obj/machinery/iv_drip/saline/Initialize(mapload)
- . = ..()
- beaker = new /obj/item/reagent_containers/glass/saline(src)
+ . = ..()
+ beaker = new /obj/item/reagent_containers/glass/saline(src)
-/obj/machinery/iv_drip/saline/update_icon()
- return
+/obj/machinery/iv_drip/saline/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
/obj/machinery/iv_drip/saline/eject_beaker()
- return
+ return
+
/obj/machinery/iv_drip/saline/toggle_mode()
return
+
#undef IV_TAKING
#undef IV_INJECTING
diff --git a/code/game/machinery/newscaster/newspaper.dm b/code/game/machinery/newscaster/newspaper.dm
index 29da9452d0122..759aabbd55c2c 100644
--- a/code/game/machinery/newscaster/newspaper.dm
+++ b/code/game/machinery/newscaster/newspaper.dm
@@ -24,7 +24,7 @@ I am begging someone to remake this to be more like the paper UI, it's so bad.
var/wantedPhoto
var/creation_time
-/obj/item/newspaper/suicide_act(mob/user)
+/obj/item/newspaper/suicide_act(mob/living/user)
user.visible_message("[user] is focusing intently on [src]! It looks like [user.p_theyre()] trying to commit sudoku... until [user.p_their()] eyes light up with realization!")
user.say(";JOURNALISM IS MY CALLING! EVERYBODY APPRECIATES UNBIASED REPORTI-GLORF", forced="newspaper suicide")
var/mob/living/carbon/human/H = user
@@ -32,7 +32,6 @@ I am begging someone to remake this to be more like the paper UI, it's so bad.
playsound(H.loc, 'sound/items/drink.ogg', rand(10,50), TRUE)
W.reagents.trans_to(H, W.reagents.total_volume, transfered_by = user)
user.visible_message("[user] downs the contents of [W.name] in one gulp! Shoulda stuck to sudoku!")
-
return TOXLOSS
/obj/item/newspaper/attack_self(mob/user)
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 37caeb0d0bb21..66e32708181a7 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -176,7 +176,7 @@ Buildable meters
..()
T.flipped = flipped
-/obj/item/pipe/directional/suicide_act(mob/user)
+/obj/item/pipe/directional/suicide_act(mob/living/user)
user.visible_message("[user] shoves [src] in [user.p_their()] mouth and turns it on! It looks like [user.p_theyre()] trying to commit suicide!")
if(iscarbon(user))
var/mob/living/carbon/C = user
diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm
index b56efbce182ca..d14f2afab970c 100644
--- a/code/game/machinery/pipe/pipe_dispenser.dm
+++ b/code/game/machinery/pipe/pipe_dispenser.dm
@@ -55,9 +55,9 @@
new /obj/item/pipe_meter(loc)
wait = world.time + 15
if(href_list["layer_up"])
- piping_layer = CLAMP(++piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
+ piping_layer = clamp(++piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
if(href_list["layer_down"])
- piping_layer = CLAMP(--piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
+ piping_layer = clamp(--piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
return
/obj/machinery/pipedispenser/attackby(obj/item/W, mob/user, params)
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 93cb744a7e5ef..020917a6f0ffd 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -688,7 +688,7 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/porta_turret)
/obj/machinery/porta_turret/syndicate/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
+ AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
/obj/machinery/porta_turret/syndicate/setup()
return
@@ -805,7 +805,7 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/porta_turret)
/obj/machinery/porta_turret/centcom_shuttle/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
+ AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
/obj/machinery/porta_turret/centcom_shuttle/assess_perp(mob/living/carbon/human/perp)
return 0
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index f21c26c7a695a..b4822b0f07940 100755
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -50,11 +50,12 @@
START_PROCESSING(SSmachines, src)
update_use_power(ACTIVE_POWER_USE)
//finished_recharging = TRUE
- update_icon(scan = TRUE)
+ using_power = TRUE
+ update_appearance()
else
update_use_power(IDLE_POWER_USE)
- //using_power = FALSE
- update_icon()
+ using_power = FALSE
+ update_appearance()
/obj/machinery/recharger/attackby(obj/item/G, mob/user, params)
if(G.tool_behaviour == TOOL_WRENCH)
@@ -95,7 +96,8 @@
return 1
if(anchored && !charging)
- if(default_deconstruction_screwdriver(user, "rechargeropen", "recharger0", G))
+ if(default_deconstruction_screwdriver(user, "recharger", "recharger", G))
+ update_appearance()
return
if(panel_open && G.tool_behaviour == TOOL_CROWBAR)
@@ -117,10 +119,11 @@
setCharging(null)
/obj/machinery/recharger/attack_tk(mob/user)
- if(charging)
- charging.update_icon()
- charging.forceMove(drop_location())
- setCharging(null)
+ if(!charging)
+ return
+ charging.update_icon()
+ charging.forceMove(drop_location())
+ setCharging(null)
/obj/machinery/recharger/process(delta_time)
if(machine_stat & (NOPOWER|BROKEN) || !anchored)
@@ -163,20 +166,16 @@
B.cell.charge = 0
-/obj/machinery/recharger/update_icon(scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
+/obj/machinery/recharger/update_icon_state()
+ . = ..()
if(machine_stat & (NOPOWER|BROKEN) || !anchored)
icon_state = "rechargeroff"
- return
- if(scan)
- icon_state = "rechargeroff"
- return
- if(panel_open)
+ else if(panel_open)
icon_state = "rechargeropen"
- return
- if(charging)
+ else if(charging)
if(using_power)
icon_state = "recharger1"
else
icon_state = "recharger2"
- return
- icon_state = "recharger0"
+ else
+ icon_state = "recharger0"
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 2b31a902bbf6d..630854a3998d2 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -252,13 +252,13 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
to_department = GLOB.req_console_ckey_departments[to_department]
message = new_message
screen = REQ_SCREEN_AUTHENTICATE
- priority = CLAMP(text2num(href_list["priority"]), REQ_NORMAL_MESSAGE_PRIORITY, REQ_EXTREME_MESSAGE_PRIORITY)
+ priority = clamp(text2num(href_list["priority"]), REQ_NORMAL_MESSAGE_PRIORITY, REQ_EXTREME_MESSAGE_PRIORITY)
if(href_list["writeAnnouncement"])
var/new_message = reject_bad_text(stripped_input(usr, "Write your message:", "Awaiting Input", "", MAX_MESSAGE_LEN))
if(new_message)
message = new_message
- priority = CLAMP(text2num(href_list["priority"]) || REQ_NORMAL_MESSAGE_PRIORITY, REQ_NORMAL_MESSAGE_PRIORITY, REQ_EXTREME_MESSAGE_PRIORITY)
+ priority = clamp(text2num(href_list["priority"]) || REQ_NORMAL_MESSAGE_PRIORITY, REQ_NORMAL_MESSAGE_PRIORITY, REQ_EXTREME_MESSAGE_PRIORITY)
else
message = ""
announceAuth = FALSE
@@ -333,7 +333,7 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
//Handle screen switching
if(href_list["setScreen"])
- var/set_screen = CLAMP(text2num(href_list["setScreen"]) || 0, REQ_SCREEN_MAIN, REQ_SCREEN_ANNOUNCE)
+ var/set_screen = clamp(text2num(href_list["setScreen"]) || 0, REQ_SCREEN_MAIN, REQ_SCREEN_ANNOUNCE)
switch(set_screen)
if(REQ_SCREEN_MAIN)
to_department = ""
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index 31c48463f1326..8b78128888462 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -270,7 +270,7 @@
use_stored_power(50)
/obj/machinery/shieldwallgen/proc/use_stored_power(amount)
- power = CLAMP(power - amount, 0, maximum_stored_power)
+ power = clamp(power - amount, 0, maximum_stored_power)
update_activity()
/obj/machinery/shieldwallgen/proc/update_activity()
@@ -425,6 +425,7 @@
setDir(get_dir(gen_primary, gen_secondary))
for(var/mob/living/L in get_turf(src))
visible_message("\The [src] is suddenly occupying the same space as \the [L]!")
+ L.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS)
L.gib()
RegisterSignal(src, COMSIG_ATOM_SINGULARITY_TRY_MOVE, PROC_REF(block_singularity))
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 85633e6806a24..3f286fac82848 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -58,6 +58,10 @@
/// How fast it charges cells in a suit
var/charge_rate = 250
+/obj/machinery/suit_storage_unit/Initialize(mapload)
+ . = ..()
+ interaction_flags_machine |= INTERACT_MACHINE_OFFLINE
+
/obj/machinery/suit_storage_unit/standard_unit
suit_type = /obj/item/clothing/suit/space/eva
helmet_type = /obj/item/clothing/head/helmet/space/eva
@@ -71,6 +75,7 @@
/obj/machinery/suit_storage_unit/engine
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
mask_type = /obj/item/clothing/mask/breath
+ storage_type= /obj/item/clothing/shoes/magboots
/obj/machinery/suit_storage_unit/ce
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
@@ -164,43 +169,51 @@
if(storage_type)
storage = new storage_type(src)
RefreshParts()
- update_icon()
+ update_appearance()
/obj/machinery/suit_storage_unit/Destroy()
QDEL_NULL(wires)
dump_inventory_contents()
return ..()
-/obj/machinery/suit_storage_unit/update_icon()
- cut_overlays()
+/obj/machinery/suit_storage_unit/update_overlays()
+ . = ..()
if(uv)
if(uv_super || (obj_flags & EMAGGED))
- add_overlay("super")
- else if(occupant)
- add_overlay("uvhuman")
- else
- add_overlay("uv")
- else if(state_open)
+ . += "super"
+ return
+ if(occupant)
+ . += "uvhuman"
+ return
+
+ . += "uv"
+ return
+
+ if(state_open)
if(machine_stat & BROKEN)
- add_overlay("broken")
- else
- add_overlay("open")
- if(suit)
- add_overlay("suit")
- if(helmet)
- add_overlay("helm")
- if(storage)
- add_overlay("storage")
- else if(occupant)
- add_overlay("human")
+ . += "broken"
+ return
+
+ . += "open"
+ if(suit)
+ . += "suit"
+ if(helmet)
+ . += "helm"
+ if(storage)
+ . += "storage"
+ return
+
+ if(occupant)
+ . += "human"
+ return
/obj/machinery/suit_storage_unit/power_change()
. = ..()
if(!is_operational && state_open)
open_machine()
dump_inventory_contents()
- update_icon()
+ update_appearance()
/obj/machinery/suit_storage_unit/RefreshParts()
var/calculated_laser_rating = 0
@@ -240,6 +253,104 @@
component_parts.Cut()
qdel(src)
+/obj/machinery/suit_storage_unit/interact(mob/living/user)
+ var/static/list/items
+
+ if (!items)
+ items = list(
+ "suit" = create_silhouette_of(/obj/item/clothing/suit/space/eva),
+ "helmet" = create_silhouette_of(/obj/item/clothing/head/helmet/space/eva),
+ "mask" = create_silhouette_of(/obj/item/clothing/mask/breath),
+ "storage" = create_silhouette_of(/obj/item/tank/internals/oxygen),
+ )
+
+ . = ..()
+ if (.)
+ return
+
+ if (!check_interactable(user))
+ return
+
+ var/list/choices = list()
+
+ if (locked)
+ choices["unlock"] = icon('icons/mob/radial.dmi', "radial_unlock")
+ else if (state_open)
+ choices["close"] = icon('icons/mob/radial.dmi', "radial_close")
+
+ for (var/item_key in items)
+ var/item = vars[item_key]
+ if (item)
+ choices[item_key] = item
+ else
+ // If the item doesn't exist, put a silhouette in its place
+ choices[item_key] = items[item_key]
+ else
+ choices["open"] = icon('icons/mob/radial.dmi', "radial_open")
+ choices["disinfect"] = icon('icons/mob/radial.dmi', "radial_disinfect")
+ choices["lock"] = icon('icons/mob/radial.dmi', "radial_lock")
+
+ var/choice = show_radial_menu(
+ user,
+ src,
+ choices,
+ custom_check = CALLBACK(src, PROC_REF(check_interactable), user),
+ )
+
+ if (!choice)
+ return
+
+ switch (choice)
+ if ("open")
+ if (!state_open)
+ open_machine(drop = FALSE)
+ if (occupant)
+ dump_contents()
+ if ("close")
+ if (state_open)
+ close_machine()
+ if ("disinfect")
+ if (occupant && safeties)
+ return
+ else if (!helmet && !mask && !suit && !storage && !occupant)
+ return
+ else
+ if (occupant)
+ var/mob/living/mob_occupant = occupant
+ to_chat(mob_occupant, "[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!")
+ cook()
+ if ("lock", "unlock")
+ if (!state_open)
+ locked = !locked
+ else
+ var/obj/item/item_to_dispense = vars[choice]
+ if (item_to_dispense)
+ vars[choice] = null
+ user.put_in_hands(item_to_dispense)
+
+ interact(user)
+
+/obj/machinery/suit_storage_unit/proc/check_interactable(mob/user)
+ if (state_open && !powered())
+ return FALSE
+
+ if (!state_open && !can_interact(user))
+ return FALSE
+
+ if (panel_open)
+ return FALSE
+
+ if (uv)
+ return FALSE
+
+ return TRUE
+
+/obj/machinery/suit_storage_unit/proc/create_silhouette_of(atom/item)
+ var/image/image = image(initial(item.icon), initial(item.icon_state))
+ image.alpha = 128
+ image.color = COLOR_RED
+ return image
+
/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/living/user)
if(!istype(user) || user.stat || !Adjacent(user) || !Adjacent(A) || !isliving(A))
return
@@ -287,7 +398,7 @@
uv_cycles--
uv = TRUE
locked = TRUE
- update_icon()
+ update_appearance()
if(mob_occupant)
mob_occupant.adjustFireLoss(rand(burn_damage, burn_damage * 1.5))
mob_occupant.emote("scream")
@@ -435,8 +546,7 @@
storage = I
visible_message("[user] inserts [I] into [src]", "You load [I] into [src].")
- update_icon()
- ui_update()
+ update_appearance()
return
if(panel_open && is_wire_tool(I))
@@ -444,7 +554,6 @@
return
if(!state_open)
if(default_deconstruction_screwdriver(user, "panel", "close", I))
- ui_update() // Wires might've changed availability of decontaminate button
return
if(is_empty())
if(default_deconstruction_crowbar(I))
@@ -472,86 +581,3 @@
I.play_tool_sound(src, 50)
visible_message("[usr] pries open \the [src].", "You pry open \the [src].")
open_machine()
-
-
-/obj/machinery/suit_storage_unit/ui_state(mob/user)
- return GLOB.notcontained_state
-
-/obj/machinery/suit_storage_unit/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "SuitStorageUnit")
- ui.open()
-
-/obj/machinery/suit_storage_unit/ui_data()
- var/list/data = list()
- data["locked"] = locked
- data["open"] = state_open
- data["safeties"] = safeties
- data["uv_active"] = uv
- data["uv_super"] = uv_super
- if(helmet)
- data["helmet"] = helmet.name
- else
- data["helmet"] = null
- if(suit)
- data["suit"] = suit.name
- else
- data["suit"] = null
- if(mask)
- data["mask"] = mask.name
- else
- data["mask"] = null
- if(storage)
- data["storage"] = storage.name
- else
- data["storage"] = null
- if(occupant)
- data["occupied"] = TRUE
- else
- data["occupied"] = FALSE
- return data
-
-/obj/machinery/suit_storage_unit/ui_act(action, params)
- if(..() || uv)
- return
- switch(action)
- if("door")
- if(state_open)
- close_machine()
- else
- open_machine(0)
- if(occupant)
- dump_inventory_contents() // Dump out contents if someone is in there.
- . = TRUE
- if("lock")
- if(state_open)
- return
- locked = !locked
- . = TRUE
- if("uv")
- if(occupant && safeties)
- return
- else if(!helmet && !mask && !suit && !storage && !occupant)
- return
- else
- if(occupant)
- var/mob/living/mob_occupant = occupant
- to_chat(mob_occupant, "[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!")
- cook()
- . = TRUE
- if("dispense")
- if(!state_open)
- return
-
- var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
- var/item_name = params["item"]
- if(item_name in valid_items)
- var/obj/item/I = vars[item_name]
- vars[item_name] = null
- if(I)
- I.forceMove(loc)
- . = TRUE
-
- if(.)
- update_icon()
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index 9823acd3d2360..3e21586a9863a 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -221,7 +221,7 @@
/obj/machinery/syndicatebomb/proc/settings(mob/user)
var/new_timer = input(user, "Please set the timer.", "Timer", "[timer_set]") as num
if(in_range(src, user) && isliving(user)) //No running off and setting bombs from across the station
- timer_set = CLAMP(new_timer, minimum_timer, maximum_timer)
+ timer_set = clamp(new_timer, minimum_timer, maximum_timer)
loc.visible_message("[icon2html(src, viewers(src))] timer set for [timer_set] seconds.")
if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && in_range(src, user) && isliving(user))
if(active)
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index b88c15bb69f28..f703c91d3107c 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -44,6 +44,7 @@
for(var/direction in GLOB.cardinals)
power_station = locate(/obj/machinery/teleport/station, get_step(src, direction))
if(power_station)
+ power_station.link_console_and_hub()
break
return power_station
@@ -136,7 +137,7 @@
if(!panel_open)
. += "The panel is screwed in, obstructing the linking device and wiring panel."
else
- . += "The linking device is now able to be scanned with a multitool.
The wiring can be connected to a nearby console and hub with a pair of wirecutters."
+ . += "The linking device is now able to be scanned with a multitool."
if(in_range(user, src) || isobserver(user))
. += "The status display reads: This station can be linked to [efficiency] other station(s)."
@@ -173,12 +174,6 @@
else if(default_deconstruction_crowbar(W))
return
-
- else if(W.tool_behaviour == TOOL_WIRECUTTER)
- if(panel_open)
- link_console_and_hub()
- to_chat(user, "You reconnect the station to nearby machinery.")
- return
else
return ..()
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index c85426593c0cf..f391abebf6e9c 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -228,6 +228,7 @@ GLOBAL_LIST_INIT(dye_registry, list(
/mob/living/simple_animal/pet/machine_wash(obj/machinery/washing_machine/WM)
WM.bloody_mess = TRUE
+ investigate_log("has been gibbed by a washing machine.", INVESTIGATE_DEATHS)
gib()
/obj/item/machine_wash(obj/machinery/washing_machine/WM)
diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm
index ccbc3991466fb..44b98a94ed8e5 100644
--- a/code/game/mecha/equipment/tools/mining_tools.dm
+++ b/code/game/mecha/equipment/tools/mining_tools.dm
@@ -121,6 +121,7 @@
var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.Butcher(chassis, target)
else
+ investigate_log("has been gibbed by [src] (attached to [chassis]).", INVESTIGATE_DEATHS)
target.gib()
else
//drill makes a hole
diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm
index 2c644a494fe29..162c0427098fa 100644
--- a/code/game/mecha/mech_bay.dm
+++ b/code/game/mecha/mech_bay.dm
@@ -153,11 +153,11 @@
else
recharge_port = null
-/obj/machinery/computer/mech_bay_power_console/update_icon()
- ..()
+/obj/machinery/computer/mech_bay_power_console/update_overlays()
+ . = ..()
if(!recharge_port || !recharge_port.recharging_mech || !recharge_port.recharging_mech.cell || !(recharge_port.recharging_mech.cell.charge < recharge_port.recharging_mech.cell.maxcharge) || machine_stat & (NOPOWER|BROKEN))
return
- add_overlay("recharge_comp_on")
+ . += "recharge_comp_on"
/obj/machinery/computer/mech_bay_power_console/Initialize(mapload)
. = ..()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index a5bedff3ee04c..c5dd1f1e15b36 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -151,10 +151,10 @@
become_hearing_sensitive(trait_source = ROUNDSTART_TRAIT)
update_step_speed()
-/obj/mecha/update_icon()
- if (silicon_pilot && silicon_icon_state)
+/obj/mecha/update_icon_state()
+ if(silicon_pilot && silicon_icon_state)
icon_state = silicon_icon_state
- . = ..()
+ return ..()
/obj/mecha/get_cell()
return cell
@@ -167,11 +167,11 @@
if(occupant)
occupant.SetSleeping(destruction_sleep_duration)
go_out()
- var/mob/living/silicon/ai/AI
+ var/mob/living/silicon/ai/ai
for(var/mob/M in src) //Let's just be ultra sure
if(isAI(M))
occupant = null
- AI = M //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. They can be recovered with an AI card from the wreck.
+ ai = M //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. They can be recovered with an AI card from the wreck.
else
M.forceMove(loc)
for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
@@ -185,8 +185,9 @@
qdel(capacitor)
if(internal_tank)
qdel(internal_tank)
- if(AI)
- AI.gib() //No wreck, no AI to recover
+ if(ai)
+ ai.investigate_log("has been gibbed by having their mech destroyed.", INVESTIGATE_DEATHS)
+ ai.gib() //No wreck, no AI to recover
STOP_PROCESSING(SSobj, src)
equipment.Cut()
cell = null
@@ -1055,6 +1056,7 @@
var/mob/living/silicon/ai/AI = occupant
if(forced)//This should only happen if there are multiple AIs in a round, and at least one is Malf.
RemoveActions(occupant)
+ occupant.investigate_log("has been gibbed by being forced out of their mech by another AI.", INVESTIGATE_DEATHS)
occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
occupant = null
silicon_pilot = FALSE
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 35850c15dd97c..c04ae0e93bc7f 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -51,16 +51,6 @@
..()
update_icon()
-/obj/mecha/working/ripley/update_icon()
- ..()
- var/datum/component/armor_plate/C = GetComponent(/datum/component/armor_plate)
- if (C.amount)
- cut_overlays()
- if(C.amount < 3)
- add_overlay(occupant ? "ripley-g" : "ripley-g-open")
- else
- add_overlay(occupant ? "ripley-g-full" : "ripley-g-full-open")
-
/obj/mecha/working/ripley/check_for_internal_damage(list/possible_int_damage,ignore_threshold=null)
if (!enclosed)
possible_int_damage -= (MECHA_INT_TEMP_CONTROL + MECHA_INT_TANK_BREACH) //if we don't even have an air tank, these two doesn't make a ton of sense.
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index 6ff54ceb0814e..1434c998ed1e5 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -99,7 +99,7 @@
M.forceMove(loc)
M.buckling = null
- M.buckled = src
+ M.set_buckled(src)
M.setDir(dir)
buckled_mobs |= M
M.update_mobility()
@@ -127,7 +127,7 @@
/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force=FALSE)
if(istype(buckled_mob) && buckled_mob.buckled == src && (buckled_mob.can_unbuckle() || force))
. = buckled_mob
- buckled_mob.buckled = null
+ buckled_mob.set_buckled(null)
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_mobility()
buckled_mob.clear_alert("buckled")
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index 5c252eb8f402c..2b9436c9c8970 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -116,7 +116,7 @@
/obj/item/reagent_containers/food/snacks/salad/aesirsalad)
var/mains = list(
/obj/item/reagent_containers/food/snacks/bearsteak,
- /obj/item/reagent_containers/food/snacks/enchiladas,
+ /obj/item/food/enchiladas,
/obj/item/reagent_containers/food/snacks/stewedsoymeat,
/obj/item/food/burger/bigbite,
/obj/item/food/burger/superbite,
diff --git a/code/game/objects/effects/spawners/vending.dm b/code/game/objects/effects/spawners/vending.dm
index b3730d2af3035..5f793269430c8 100644
--- a/code/game/objects/effects/spawners/vending.dm
+++ b/code/game/objects/effects/spawners/vending.dm
@@ -1,12 +1,16 @@
-/obj/effect/spawner/randomsnackvend
+/obj/effect/spawner/randomvend
icon = 'icons/obj/vending.dmi'
+ name = "spawn random vending machine"// THIS IS A PARENT, only use the subtype vendors
+ desc = "Automagically transforms into a random vendor. If you see this while in a shift, please create a bug report."
+ ///whether it hacks the vendor on spawn currently used only by stinky mapedits
+ var/hacked = FALSE
+
+/obj/effect/spawner/randomvend/snack
icon_state = "random_snack"
name = "spawn random snack vending machine"
desc = "Automagically transforms into a random snack vendor. If you see this while in a shift, please create a bug report."
- ///whether it hacks the vendor on spawn currently used only by stinky mapedits
- var/hacked = FALSE
-/obj/effect/spawner/randomsnackvend/Initialize(mapload)
+/obj/effect/spawner/randomvend/snack/Initialize(mapload)
..()
var/random_vendor = pick(subtypesof(/obj/machinery/vending/snack))
@@ -16,15 +20,12 @@
return INITIALIZE_HINT_QDEL
-/obj/effect/spawner/randomcolavend
- icon = 'icons/obj/vending.dmi'
+/obj/effect/spawner/randomvend/cola
icon_state = "random_cola"
name = "spawn random cola vending machine"
desc = "Automagically transforms into a random cola vendor. If you see this while in a shift, please create a bug report."
- ///whether it hacks the vendor on spawn currently used only by stinky mapedits
- var/hacked = FALSE
-/obj/effect/spawner/randomcolavend/Initialize(mapload)
+/obj/effect/spawner/randomvend/cola/Initialize(mapload)
..()
var/random_vendor = pick(subtypesof(/obj/machinery/vending/cola))
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 26c999cccb39c..ba0804b0e383f 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -145,10 +145,6 @@
/obj/effect/temp_visual/dir_setting/curse/hand
icon_state = "cursehand"
-/obj/effect/temp_visual/dir_setting/curse/hand/Initialize(mapload, set_dir, handedness)
- . = ..()
- update_icon()
-
/obj/effect/temp_visual/bsa_splash
name = "\improper Bluespace energy wave"
desc = "A massive, rippling wave of bluepace energy, all rapidly exhausting itself the moment it leaves the concentrated beam of light."
@@ -497,16 +493,20 @@
else
update_icon()
-/obj/effect/constructing_effect/update_icon()
+/obj/effect/constructing_effect/update_icon_state()
icon_state = "rcd"
if (delay < 10)
icon_state += "_shortest"
+ return ..()
else if (delay < 20)
icon_state += "_shorter"
+ return ..()
else if (delay < 37)
icon_state += "_short"
+ return ..()
if (status == RCD_DECONSTRUCT)
icon_state += "_reverse"
+ return ..()
/obj/effect/constructing_effect/proc/end_animation()
if (status == RCD_DECONSTRUCT)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 2740ed4653b32..0d4c8a5600d43 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -305,7 +305,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
//TOXLOSS = 4
//OXYLOSS = 8
//Output a creative message and then return the damagetype done
-/obj/item/proc/suicide_act(mob/user)
+/obj/item/proc/suicide_act(mob/living/user)
return
/obj/item/set_greyscale(list/colors, new_config, new_worn_config, new_inhand_left, new_inhand_right)
@@ -1357,6 +1357,17 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
#undef MAX_MATS_PER_BITE
+/**
+ * Updates all action buttons associated with this item
+ *
+ * Arguments:
+ * * status_only - Update only current availability status of the buttons to show if they are ready or not to use
+ * * force - Force buttons update even if the given button icon state has not changed
+ */
+/obj/item/proc/update_action_buttons(status_only = FALSE, force = FALSE)
+ for(var/datum/action/current_action as anything in actions)
+ current_action.UpdateButtonIcon(status_only, force)
+
/**
* * An interrupt for offering an item to other people, called mainly from [/mob/living/carbon/proc/give], in case you want to run your own offer behavior instead.
*
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index 074992b8f980f..98614edca7ccb 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -207,9 +207,9 @@ RLD
/// Integrated airlock electronics for setting access to a newly built airlocks
var/obj/item/electronics/airlock/airlock_electronics
-/obj/item/construction/rcd/suicide_act(mob/user)
+/obj/item/construction/rcd/suicide_act(mob/living/user)
user.visible_message("[user] sets the RCD to 'Wall' and points it down [user.p_their()] throat! It looks like [user.p_theyre()] trying to commit suicide..")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/construction/rcd/verb/toggle_window_type_verb()
set name = "RCD : Toggle Window Type"
@@ -529,12 +529,11 @@ RLD
explosion(src, 0, 0, 3, 1, flame_range = 1)
qdel(src)
-/obj/item/construction/rcd/update_icon()
- ..()
+/obj/item/construction/rcd/update_overlays()
+ . = ..()
if(has_ammobar)
var/ratio = CEILING((matter / max_matter) * ammo_sections, 1)
- cut_overlays() //To prevent infinite stacking of overlays
- add_overlay("[icon_state]_charge[ratio]")
+ . += "[icon_state]_charge[ratio]"
/obj/item/construction/rcd/Initialize(mapload)
. = ..()
@@ -664,11 +663,10 @@ RLD
else
..()
-/obj/item/construction/rld/update_icon()
+/obj/item/construction/rld/update_icon_state()
// "infinite matter/35" from a debug tool will give a big number, but "rld-5" is the maximum
icon_state = "rld-[min(round(matter/35), 5)]"
- ..()
-
+ return ..()
/obj/item/construction/rld/attack_self(mob/user)
..()
diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm
index 02bfbbe5ac92d..02a23725a2abe 100644
--- a/code/game/objects/items/RCL.dm
+++ b/code/game/objects/items/RCL.dm
@@ -31,6 +31,7 @@
/obj/item/rcl/ComponentInitialize()
. = ..()
AddComponent(/datum/component/two_handed)
+ AddElement(/datum/element/update_icon_updates_onmob)
/// triggered on wield of two handed item
/obj/item/rcl/proc/on_wield(obj/item/source, mob/user)
@@ -112,11 +113,11 @@
QDEL_NULL(wiring_gui_menu)
return ..()
-/obj/item/rcl/update_icon()
+/obj/item/rcl/update_icon_state()
if(!loaded)
icon_state = "rcl-0"
item_state = "rcl-0"
- return
+ return ..()
switch(loaded.amount)
if(61 to INFINITY)
icon_state = "rcl-30"
@@ -130,6 +131,7 @@
else
icon_state = "rcl-0"
item_state = "rcl-0"
+ return ..()
/obj/item/rcl/proc/is_empty(mob/user, loud = 1)
update_icon()
@@ -331,11 +333,11 @@
name = "makeshift rapid cable layer"
ghetto = TRUE
-/obj/item/rcl/ghetto/update_icon()
+/obj/item/rcl/ghetto/update_icon_state()
if(!loaded)
icon_state = "rclg-0"
item_state = "rclg-0"
- return
+ return ..()
switch(loaded.amount)
if(1 to INFINITY)
icon_state = "rclg-1"
@@ -343,3 +345,4 @@
else
icon_state = "rclg-1"
item_state = "rclg-1"
+ return ..()
diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm
index a2dccf179b13d..2a62669454c7d 100644
--- a/code/game/objects/items/RPD.dm
+++ b/code/game/objects/items/RPD.dm
@@ -324,11 +324,11 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE)
qdel(rpd_up)
-/obj/item/pipe_dispenser/suicide_act(mob/user)
+/obj/item/pipe_dispenser/suicide_act(mob/living/user)
user.visible_message("[user] points the end of the RPD down [user.p_their()] throat and presses a button! It looks like [user.p_theyre()] trying to commit suicide...")
playsound(get_turf(user), 'sound/machines/click.ogg', 50, 1)
playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1)
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/pipe_dispenser/ui_assets(mob/user)
return list(
diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm
index 5cfdfa871e43c..2067ebffecb85 100644
--- a/code/game/objects/items/airlock_painter.dm
+++ b/code/game/objects/items/airlock_painter.dm
@@ -89,7 +89,7 @@
else
return TRUE
-/obj/item/airlock_painter/suicide_act(mob/user)
+/obj/item/airlock_painter/suicide_act(mob/living/user)
var/obj/item/organ/lungs/L = user.getorganslot(ORGAN_SLOT_LUNGS)
if(can_use(user) && L)
diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm
index 7b7e7d0ef13d5..e3ddb05a1c219 100644
--- a/code/game/objects/items/candle.dm
+++ b/code/game/objects/items/candle.dm
@@ -20,8 +20,9 @@
if(start_lit)
light()
-/obj/item/candle/update_icon()
+/obj/item/candle/update_icon_state()
icon_state = "candle[(wax > 800) ? ((wax > 1500) ? 1 : 2) : 3][lit ? "_lit" : ""]"
+ return ..()
/obj/item/candle/attackby(obj/item/W, mob/user, params)
var/msg = W.ignition_effect(src, user)
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index 6398a7c817689..671667baf0184 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -41,13 +41,13 @@
.=..()
update_icon()
-/obj/item/card/data/update_icon()
- cut_overlays()
+/obj/item/card/data/update_overlays()
+ . = ..()
if(detail_color == COLOR_FLOORTILE_GRAY)
return
var/mutable_appearance/detail_overlay = mutable_appearance('icons/obj/card.dmi', "[icon_state]-color")
detail_overlay.color = detail_color
- add_overlay(detail_overlay)
+ . += detail_overlay
/obj/item/card/data/full_color
desc = "A plastic magstripe card for simple and speedy data storage and transfer. This one has the entire card colored."
@@ -180,6 +180,7 @@
. = ..()
if(mapload && access_txt)
access = text2access(access_txt)
+ //RegisterSignal(src, COMSIG_ATOM_UPDATED_ICON, PROC_REFupdate_in_wallet))
/obj/item/card/id/Destroy()
if (registered_account)
@@ -396,6 +397,18 @@
/obj/item/card/id/RemoveID()
return src
+/*
+/// Called on COMSIG_ATOM_UPDATED_ICON. Updates the visuals of the wallet this card is in.
+/obj/item/card/id/proc/update_in_wallet()
+ SIGNAL_HANDLER
+
+ if(istype(loc, /obj/item/storage/wallet))
+ var/obj/item/storage/wallet/powergaming = loc
+ if(powergaming.front_id == src)
+ powergaming.update_label()
+ powergaming.update_appearance()
+*/
+
/*
Usage:
update_label()
diff --git a/code/game/objects/items/chainsaw.dm b/code/game/objects/items/chainsaw.dm
index a3ced95701ef9..ca68817e888aa 100644
--- a/code/game/objects/items/chainsaw.dm
+++ b/code/game/objects/items/chainsaw.dm
@@ -44,7 +44,7 @@
else
user.visible_message("[user] smashes [src] into [user.p_their()] neck, destroying [user.p_their()] esophagus! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(src, 'sound/weapons/genhit1.ogg', 100, TRUE)
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/chainsaw/attack_self(mob/user)
on = !on
@@ -62,9 +62,7 @@
if(src == user.get_active_held_item()) //update inhands
user.update_inv_hands()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
// DOOMGUY CHAINSAW
/obj/item/chainsaw/doomslayer
@@ -124,9 +122,7 @@
if(src == user.get_active_held_item())
user.update_inv_hands()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
// DOOMGUY ENERGY CHAINSAW
/obj/item/chainsaw/energy/doom
diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm
index 4de67383e30d0..5b317ac9ab2c9 100644
--- a/code/game/objects/items/chrono_eraser.dm
+++ b/code/game/objects/items/chrono_eraser.dm
@@ -65,8 +65,9 @@
TED = new(src.loc)
return INITIALIZE_HINT_QDEL
-/obj/item/gun/energy/chrono_gun/update_icon()
- return
+/obj/item/gun/energy/chrono_gun/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
if(field)
@@ -207,7 +208,7 @@
/obj/structure/chrono_field/update_icon()
var/ttk_frame = 1 - (timetokill / initial(timetokill))
- ttk_frame = CLAMP(CEILING(ttk_frame * CHRONO_FRAME_COUNT, 1), 1, CHRONO_FRAME_COUNT)
+ ttk_frame = clamp(CEILING(ttk_frame * CHRONO_FRAME_COUNT, 1), 1, CHRONO_FRAME_COUNT)
if(ttk_frame != RPpos)
RPpos = ttk_frame
underlays -= mob_underlay
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 2e116884d0da8..dfdd563230ced 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -143,7 +143,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
var/smoke_all = FALSE /// Should we smoke all of the chems in the cig before it runs out. Splits each puff to take a portion of the overall chems so by the end you'll always have consumed all of the chems inside.
var/list/list_reagents = list(/datum/reagent/drug/nicotine = 15)
-/obj/item/clothing/mask/cigarette/suicide_act(mob/user)
+/obj/item/clothing/mask/cigarette/suicide_act(mob/living/user)
user.visible_message("[user] is huffing [src] as quickly as [user.p_they()] can! It looks like [user.p_theyre()] trying to give [user.p_them()]self cancer.")
return (TOXLOSS|OXYLOSS)
@@ -629,11 +629,16 @@ CIGARETTE PACKETS ARE IN FANCY.DM
user.visible_message("[user] begins whacking [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
return BRUTELOSS
-/obj/item/lighter/update_icon()
- cut_overlays()
- var/mutable_appearance/lighter_overlay = mutable_appearance(icon,"lighter_overlay_[overlay_state][lit ? "-on" : ""]")
+/obj/item/lighter/update_overlays()
+ . = ..()
+ . += create_lighter_overlay()
+
+/obj/item/lighter/update_icon_state()
icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
- add_overlay(lighter_overlay)
+ return ..()
+
+/obj/item/lighter/proc/create_lighter_overlay()
+ return mutable_appearance(icon, "lighter_overlay_[overlay_state][lit ? "-on" : ""]")
/obj/item/lighter/ignition_effect(atom/A, mob/user)
if(is_hot())
@@ -772,12 +777,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
lighter_color = pick(color_list)
update_icon()
-/obj/item/lighter/greyscale/update_icon()
- cut_overlays()
- var/mutable_appearance/lighter_overlay = mutable_appearance(icon,"lighter_overlay_[overlay_state][lit ? "-on" : ""]")
- icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
+/obj/item/lighter/greyscale/create_lighter_overlay()
+ var/mutable_appearance/lighter_overlay = ..()
lighter_overlay.color = lighter_color
- add_overlay(lighter_overlay)
+ return lighter_overlay
/obj/item/lighter/greyscale/ignition_effect(atom/A, mob/user)
if(is_hot())
@@ -840,7 +843,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
var/screw = FALSE // kinky
var/super = FALSE //for the fattest vapes dude.
-/obj/item/clothing/mask/vape/suicide_act(mob/user)
+/obj/item/clothing/mask/vape/suicide_act(mob/living/user)
user.visible_message("[user] is puffin hard on dat vape, [user.p_they()] trying to join the vape life on a whole notha plane!")//it doesn't give you cancer, it is cancer
return (TOXLOSS|OXYLOSS)
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 1b38f839ce94e..c976427405fe9 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -945,7 +945,7 @@
var/new_cloud = input("Set the public nanite chamber's Cloud ID (1-100).", "Cloud ID", cloud_id) as num|null
if(new_cloud == null)
return
- cloud_id = CLAMP(round(new_cloud, 1), 1, 100)
+ cloud_id = clamp(round(new_cloud, 1), 1, 100)
/obj/item/circuitboard/machine/public_nanite_chamber/examine(mob/user)
. = ..()
diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm
index ce20d2bc87112..8a9c55e2c1610 100644
--- a/code/game/objects/items/clown_items.dm
+++ b/code/game/objects/items/clown_items.dm
@@ -72,11 +72,11 @@
icon_state = "soapsyndie"
cleanspeed = 5 //faster than mop so it is useful for traitors who want to clean crime scenes
-/obj/item/soap/suicide_act(mob/user)
+/obj/item/soap/suicide_act(mob/living/user)
user.say(";FFFFFFFFFFFFFFFFUUUUUUUDGE!!", forced="soap suicide")
user.visible_message("[user] lifts [src] to [user.p_their()] mouth and gnaws on it furiously, producing a thick froth! [user.p_they(TRUE)]'ll never get that BB gun now!")
new /obj/effect/particle_effect/foam(loc)
- return (TOXLOSS)
+ return TOXLOSS
/obj/item/soap/proc/decreaseUses(mob/user)
uses--
@@ -168,10 +168,10 @@
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "honk", /datum/mood_event/honk)
return ..()
-/obj/item/bikehorn/suicide_act(mob/user)
+/obj/item/bikehorn/suicide_act(mob/living/user)
user.visible_message("[user] solemnly points [src] at [user.p_their()] temple! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(src, 'sound/items/bikehorn.ogg', 50, TRUE)
- return (BRUTELOSS)
+ return BRUTELOSS
//air horn
/obj/item/bikehorn/airhorn
diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm
index 1b19b16310f5b..1690f6e9a1957 100644
--- a/code/game/objects/items/cosmetics.dm
+++ b/code/game/objects/items/cosmetics.dm
@@ -254,9 +254,9 @@
var/extended_throwforce = 7
var/extended_icon_state = "straightrazor_open"
-/obj/item/razor/straightrazor/suicide_act(mob/user)
+/obj/item/razor/straightrazor/suicide_act(mob/living/user)
user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/razor/attack(mob/M, mob/user)
. = ..()
diff --git a/code/game/objects/items/courtroom.dm b/code/game/objects/items/courtroom.dm
index 11c1a521db790..516360f38ae8b 100644
--- a/code/game/objects/items/courtroom.dm
+++ b/code/game/objects/items/courtroom.dm
@@ -13,10 +13,10 @@
attack_verb = list("bashed", "battered", "judged", "whacked")
resistance_flags = FLAMMABLE
-/obj/item/gavelhammer/suicide_act(mob/user)
+/obj/item/gavelhammer/suicide_act(mob/living/user)
user.visible_message("[user] has sentenced [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/gavelblock
name = "gavel block"
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 45f1329e95136..98c3b1454b9c4 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -74,7 +74,7 @@
/obj/item/toy/crayon/proc/isValidSurface(surface)
return istype(surface, /turf/open/floor)
-/obj/item/toy/crayon/suicide_act(mob/user)
+/obj/item/toy/crayon/suicide_act(mob/living/user)
user.visible_message("[user] is jamming [src] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide!")
return (BRUTELOSS|OXYLOSS)
@@ -540,10 +540,10 @@
new /obj/item/toy/crayon/black(src)
update_icon()
-/obj/item/storage/crayons/update_icon()
- cut_overlays()
+/obj/item/storage/crayons/update_overlays()
+ . = ..()
for(var/obj/item/toy/crayon/crayon in contents)
- add_overlay(mutable_appearance('icons/obj/crayons.dmi', crayon.crayon_color))
+ . += mutable_appearance('icons/obj/crayons.dmi', crayon.crayon_color)
/obj/item/storage/crayons/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/toy/crayon))
@@ -613,7 +613,7 @@
return (istype(surface, /turf/open/floor) || istype(surface, /turf/closed/wall))
-/obj/item/toy/crayon/spraycan/suicide_act(mob/user)
+/obj/item/toy/crayon/spraycan/suicide_act(mob/living/user)
var/mob/living/carbon/human/H = user
if(is_capped || !actually_paints)
user.visible_message("[user] shakes up [src] with a rattle and lifts it to [user.p_their()] mouth, but nothing happens!")
@@ -635,8 +635,7 @@
var/fraction = min(1, used / reagents.maximum_volume)
reagents.reaction(user, VAPOR, fraction * volume_multiplier)
reagents.trans_to(user, used, volume_multiplier, transfered_by = user)
-
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/toy/crayon/spraycan/Initialize(mapload)
. = ..()
@@ -736,13 +735,16 @@
. = ..()
-/obj/item/toy/crayon/spraycan/update_icon()
+/obj/item/toy/crayon/spraycan/update_icon_state()
icon_state = is_capped ? icon_capped : icon_uncapped
+ return ..()
+
+/obj/item/toy/crayon/spraycan/update_overlays()
+ . = ..()
if(use_overlays)
- cut_overlays()
var/mutable_appearance/spray_overlay = mutable_appearance('icons/obj/crayons.dmi', "[is_capped ? "spraycan_cap_colors" : "spraycan_colors"]")
spray_overlay.color = paint_color
- add_overlay(spray_overlay)
+ . += spray_overlay
/obj/item/toy/crayon/spraycan/borg
name = "cyborg spraycan"
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index 906943f790834..e4561d4fac963 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -32,14 +32,14 @@
/obj/item/defibrillator/Initialize(mapload) //starts without a cell for rnd
. = ..()
paddles = make_paddles()
- update_icon()
+ update_power()
return
/obj/item/defibrillator/loaded/Initialize(mapload) //starts with hicap
. = ..()
paddles = make_paddles()
cell = new(src)
- update_icon()
+ update_power()
return
/obj/item/defibrillator/fire_act(exposed_temperature, exposed_volume)
@@ -52,9 +52,7 @@
if(paddles?.loc == src)
paddles.extinguish()
-/obj/item/defibrillator/update_overlays()
- . = ..()
-
+/obj/item/defibrillator/proc/update_power()
if(!QDELETED(cell))
if(QDELETED(paddles) || cell.charge < paddles.revivecost)
powered = FALSE
@@ -62,6 +60,12 @@
powered = TRUE
else
powered = FALSE
+ update_appearance()
+ if(istype(loc, /obj/machinery/defibrillator_mount))
+ loc.update_appearance()
+
+/obj/item/defibrillator/update_overlays()
+ . = ..()
if(!on)
. += "[initial(icon_state)]-paddles"
@@ -78,7 +82,7 @@
/obj/item/defibrillator/CheckParts(list/parts_list)
..()
cell = locate(/obj/item/stock_parts/cell) in contents
- update_icon()
+ update_power()
/obj/item/defibrillator/ui_action_click()
toggle_paddles()
@@ -125,15 +129,14 @@
return
cell = W
to_chat(user, "You install a cell in [src].")
- update_icon()
-
+ update_power()
else if(W.tool_behaviour == TOOL_SCREWDRIVER)
if(cell)
- cell.update_icon()
+ cell.update_appearance()
cell.forceMove(get_turf(src))
cell = null
to_chat(user, "You remove the cell from [src].")
- update_icon()
+ update_power()
else
return ..()
@@ -148,7 +151,7 @@
else
safety = TRUE
to_chat(user, "You silently enable [src]'s safety protocols with the cryptographic sequencer.")
- update_icon()
+ update_power()
/obj/item/defibrillator/emp_act(severity)
. = ..()
@@ -156,15 +159,16 @@
deductcharge(1000 / severity)
if (. & EMP_PROTECT_SELF)
return
+
if(safety)
safety = FALSE
visible_message("[src] beeps: Safety protocols disabled!")
- playsound(src, 'sound/machines/defib_saftyOff.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_saftyOff.ogg', 50, FALSE)
else
safety = TRUE
visible_message("[src] beeps: Safety protocols enabled!")
- playsound(src, 'sound/machines/defib_saftyOn.ogg', 50, 0)
- update_icon()
+ playsound(src, 'sound/machines/defib_saftyOn.ogg', 50, FALSE)
+ update_power()
/obj/item/defibrillator/proc/toggle_paddles()
set name = "Toggle Paddles"
@@ -177,16 +181,14 @@
if(!usr.put_in_hands(paddles))
on = FALSE
to_chat(user, "You need a free hand to hold the paddles!")
- update_icon()
+ update_power()
return
else
//Remove from their hands and back onto the defib unit
remove_paddles(user)
update_icon()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/defibrillator/proc/make_paddles()
return new paddle_type(src)
@@ -195,7 +197,7 @@
..()
if((slot_flags == ITEM_SLOT_BACK && slot != ITEM_SLOT_BACK) || (slot_flags == ITEM_SLOT_BELT && slot != ITEM_SLOT_BELT))
remove_paddles(user)
- update_icon()
+ update_power()
/obj/item/defibrillator/item_action_slot_check(slot, mob/user)
if(slot == user.getBackSlot())
@@ -212,19 +214,18 @@
var/M = get(paddles, /mob)
remove_paddles(M)
QDEL_NULL(paddles)
+ QDEL_NULL(cell)
. = ..()
- update_icon()
/obj/item/defibrillator/proc/deductcharge(chrgdeductamt)
if(cell)
if(cell.charge < (paddles.revivecost+chrgdeductamt))
powered = FALSE
- update_icon()
+ update_power()
if(cell.use(chrgdeductamt))
- update_icon()
+ update_power()
return TRUE
else
- update_icon()
return FALSE
@@ -240,8 +241,8 @@
visible_message("[src] beeps: Charge depleted.")
playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
paddles.cooldown = FALSE
- paddles.update_icon()
- update_icon()
+ paddles.update_appearance()
+ update_power()
/obj/item/defibrillator/compact
name = "compact defibrillator"
@@ -260,7 +261,7 @@
. = ..()
paddles = make_paddles()
cell = new(src)
- update_icon()
+ update_power()
/obj/item/defibrillator/compact/combat
name = "combat defibrillator"
@@ -274,12 +275,11 @@
. = ..()
paddles = make_paddles()
cell = new /obj/item/stock_parts/cell/infinite(src)
- update_icon()
+ update_power()
/obj/item/defibrillator/compact/combat/loaded/attackby(obj/item/W, mob/user, params)
if(W == paddles)
toggle_paddles()
- update_icon()
return
//paddles
@@ -319,6 +319,7 @@
/obj/item/shockpaddles/ComponentInitialize()
. = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
AddComponent(/datum/component/two_handed, force_unwielded=8, force_wielded=12)
/obj/item/shockpaddles/Destroy()
@@ -362,13 +363,13 @@
if(req_defib || !time)
return
cooldown = TRUE
- update_icon()
+ update_appearance()
sleep(time)
var/turf/T = get_turf(src)
T.audible_message("[src] beeps: Unit is recharged.")
- playsound(src, 'sound/machines/defib_ready.ogg', 50, 0)
+ playsound(src, 'sound/machines/defib_ready.ogg', 50, FALSE)
cooldown = FALSE
- update_icon()
+ update_appearance()
/obj/item/shockpaddles/Initialize(mapload)
. = ..()
@@ -379,24 +380,22 @@
return INITIALIZE_HINT_QDEL
defib = loc
busy = FALSE
- update_icon()
+ update_appearance()
-/obj/item/shockpaddles/update_icon()
+/obj/item/shockpaddles/update_icon_state()
var/wielded = ISWIELDED(src)
- icon_state = "defibpaddles[wielded]"
- item_state = "defibpaddles[wielded]"
+ icon_state = "[base_icon_state][wielded]"
+ item_state = icon_state
if(cooldown)
- icon_state = "defibpaddles[wielded]_cooldown"
- if(iscarbon(loc))
- var/mob/living/carbon/C = loc
- C.update_inv_hands()
+ icon_state = "[base_icon_state][wielded]_cooldown"
+ return ..()
-/obj/item/shockpaddles/suicide_act(mob/user)
+/obj/item/shockpaddles/suicide_act(mob/living/user)
user.visible_message("[user] is putting the live paddles on [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide!")
if(req_defib)
defib.deductcharge(revivecost)
playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1)
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/shockpaddles/dropped(mob/user)
..()
@@ -431,7 +430,7 @@
defib.on = FALSE
listeningTo = null
- defib.update_icon()
+ defib.update_power()
/obj/item/shockpaddles/attack(mob/M, mob/user)
if(busy)
diff --git a/code/game/objects/items/deployable/barricade.dm b/code/game/objects/items/deployable/barricade.dm
index 9ce3325dfbb4e..ee8c46727a671 100644
--- a/code/game/objects/items/deployable/barricade.dm
+++ b/code/game/objects/items/deployable/barricade.dm
@@ -60,7 +60,7 @@
to_chat(user, "You begin repairing [src]...")
if(I.use_tool(src, user, 40, volume=40))
- obj_integrity = CLAMP(obj_integrity + 20, 0, max_integrity)
+ obj_integrity = clamp(obj_integrity + 20, 0, max_integrity)
else if(I.GetID() && initial(locked_down))
if(allowed(user))
diff --git a/code/game/objects/items/deployable/bodybag.dm b/code/game/objects/items/deployable/bodybag.dm
index 33f95d7a962bc..8a5f5ff822bad 100644
--- a/code/game/objects/items/deployable/bodybag.dm
+++ b/code/game/objects/items/deployable/bodybag.dm
@@ -10,7 +10,7 @@
. = ..()
AddComponent(/datum/component/deployable, bag_type)
-/obj/item/bodybag/suicide_act(mob/user)
+/obj/item/bodybag/suicide_act(mob/living/user)
if(isopenturf(user.loc))
user.visible_message("[user] is crawling into [src]! It looks like [user.p_theyre()] trying to commit suicide!")
SEND_SIGNAL(src, COMSIG_DEPLOYABLE_FORCE_DEPLOY, user.loc)
@@ -20,8 +20,7 @@
qdel(user)
return OXYLOSS
user.forceMove(R)
- return (OXYLOSS)
- ..()
+ return OXYLOSS
// Bluespace bodybag
diff --git a/code/game/objects/items/devices/desynchronizer.dm b/code/game/objects/items/devices/desynchronizer.dm
index 74b8786802d8c..02c49cac0485d 100644
--- a/code/game/objects/items/devices/desynchronizer.dm
+++ b/code/game/objects/items/devices/desynchronizer.dm
@@ -37,7 +37,7 @@
var/new_duration = input(user, "Set the duration (5-300):", "Desynchronizer", duration / 10) as null|num
if(new_duration)
new_duration = new_duration SECONDS
- new_duration = CLAMP(new_duration, 50, max_duration)
+ new_duration = clamp(new_duration, 50, max_duration)
duration = new_duration
to_chat(user, "You set the duration to [DisplayTimeText(duration)].")
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 463878c0e7dea..0a1f423d445d1 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -44,9 +44,7 @@
/obj/item/flashlight/attack_self(mob/user)
on = !on
update_brightness(user)
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
return 1
/obj/item/flashlight/suicide_act(mob/living/carbon/human/user)
@@ -54,7 +52,7 @@
user.visible_message("[user] is putting [src] close to [user.p_their()] eyes and turning it on... but [user.p_theyre()] blind!")
return SHAME
user.visible_message("[user] is putting [src] close to [user.p_their()] eyes and turning it on! It looks like [user.p_theyre()] trying to commit suicide!")
- return (FIRELOSS)
+ return FIRELOSS
/obj/item/flashlight/attack(mob/living/carbon/M, mob/living/carbon/human/user)
add_fingerprint(user)
@@ -516,7 +514,7 @@
return SHAME
user.visible_message("[user] is squirting [src]'s fluids into [user.p_their()] eyes! It looks like [user.p_theyre()] trying to commit suicide!")
fuel = 0
- return (FIRELOSS)
+ return FIRELOSS
/obj/item/flashlight/glowstick/red
name = "red glowstick"
diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm
index ba318e4d61c6f..dc19c9b0e74fe 100644
--- a/code/game/objects/items/devices/geiger_counter.dm
+++ b/code/game/objects/items/devices/geiger_counter.dm
@@ -79,13 +79,14 @@
. += "The last radiation amount detected was [last_tick_amount]"
-/obj/item/geiger_counter/update_icon()
+/obj/item/geiger_counter/update_icon_state()
if(!scanning)
icon_state = "geiger_off"
- return 1
- if(obj_flags & EMAGGED)
+ return ..()
+ else if(obj_flags & EMAGGED)
icon_state = "geiger_on_emag"
- return 1
+ return ..()
+
switch(radiation_count)
if(-INFINITY to RAD_LEVEL_NORMAL)
icon_state = "geiger_on_1"
@@ -99,7 +100,7 @@
icon_state = "geiger_on_4"
if(RAD_LEVEL_CRITICAL + 1 to INFINITY)
icon_state = "geiger_on_5"
- ..()
+ return ..()
/obj/item/geiger_counter/proc/update_sound()
var/datum/looping_sound/geiger/loop = soundloop
diff --git a/code/game/objects/items/devices/glue.dm b/code/game/objects/items/devices/glue.dm
index 09d80523efd49..308f7af67ee22 100644
--- a/code/game/objects/items/devices/glue.dm
+++ b/code/game/objects/items/devices/glue.dm
@@ -10,7 +10,7 @@
/obj/item/syndie_glue/suicide_act(mob/living/M)
M.visible_message("[M] is drinking the whole bottle of glue! It looks like [M.p_theyre()] trying to commit suicide!")
- return (OXYLOSS) // read the warning n00b
+ return OXYLOSS // read the warning n00b
/obj/item/syndie_glue/afterattack(atom/target, mob/user, proximity)
. = ..()
diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm
index c06342e3ebdae..22839c4067bbc 100644
--- a/code/game/objects/items/devices/lightreplacer.dm
+++ b/code/game/objects/items/devices/lightreplacer.dm
@@ -159,8 +159,9 @@
ReplaceLight(target, user)
to_chat(user, status_string())
-/obj/item/lightreplacer/update_icon()
+/obj/item/lightreplacer/update_icon_state()
icon_state = "lightreplacer[(obj_flags & EMAGGED ? 1 : 0)]"
+ return ..()
/obj/item/lightreplacer/proc/status_string()
return "It has [uses] light\s remaining (plus [bulb_shards] fragment\s)."
@@ -172,7 +173,7 @@
// Negative numbers will subtract
/obj/item/lightreplacer/proc/AddUses(amount = 1)
- uses = CLAMP(uses + amount, 0, max_uses)
+ uses = clamp(uses + amount, 0, max_uses)
/obj/item/lightreplacer/proc/AddShards(amount = 1, user)
bulb_shards += amount
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index d630c66c41207..aa3c1e2ff42b8 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -27,7 +27,7 @@
var/obj/structure/cable/attached // the attached cable
item_flags = NO_PIXEL_RANDOM_DROP
-/obj/item/powersink/update_icon()
+/obj/item/powersink/update_icon_state()
icon_state = "powersink[mode == OPERATING]"
return ..()
diff --git a/code/game/objects/items/devices/quantum_keycard.dm b/code/game/objects/items/devices/quantum_keycard.dm
index fc9ccddaf9e15..86051885c65cc 100644
--- a/code/game/objects/items/devices/quantum_keycard.dm
+++ b/code/game/objects/items/devices/quantum_keycard.dm
@@ -25,8 +25,6 @@
to_chat(user, "The keycard beeps twice and disconnects the quantum link.")
qpad = null
-/obj/item/quantum_keycard/update_icon()
- if(qpad)
- icon_state = "quantum_keycard_on"
- else
- icon_state = initial(icon_state)
+/obj/item/quantum_keycard/update_icon_state()
+ icon_state = qpad ? "quantum_keycard_on" : initial(icon_state)
+ return ..()
diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm
index e4e62ae722c8d..ba2f41a689bb9 100644
--- a/code/game/objects/items/devices/radio/electropack.dm
+++ b/code/game/objects/items/devices/radio/electropack.dm
@@ -24,9 +24,9 @@
SSradio.remove_object(src, frequency)
return ..()
-/obj/item/electropack/suicide_act(mob/user)
+/obj/item/electropack/suicide_act(mob/living/user)
user.visible_message("[user] hooks [user.p_them()]self to the electropack and spams the trigger! It looks like [user.p_theyre()] trying to commit suicide!")
- return (FIRELOSS)
+ return FIRELOSS
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/electropack/attack_hand(mob/user)
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 7eb65c58fa70c..b7cfcc6de2c19 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -110,7 +110,7 @@
/obj/item/radio/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
+ AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES)
/obj/item/radio/AltClick(mob/user)
if(headset)
diff --git a/code/game/objects/items/devices/reverse_bear_trap.dm b/code/game/objects/items/devices/reverse_bear_trap.dm
index 2597bea3b625f..296bc9981a0df 100644
--- a/code/game/objects/items/devices/reverse_bear_trap.dm
+++ b/code/game/objects/items/devices/reverse_bear_trap.dm
@@ -112,6 +112,7 @@
playsound(src, 'sound/effects/snap.ogg', 75, TRUE, frequency = 0.5)
playsound(src, 'sound/effects/splat.ogg', 50, TRUE, frequency = 0.5)
jill.apply_damage(9999, BRUTE, BODY_ZONE_HEAD)
+ jill.investigate_log("has been killed by [src].", INVESTIGATE_DEATHS)
jill.death() //just in case, for some reason, they're still alive
flash_color(jill, flash_color = "#FF0000", flash_time = 100)
diff --git a/code/game/objects/items/devices/swapper.dm b/code/game/objects/items/devices/swapper.dm
index ccb5fa00f3475..a2fb41bba6de7 100644
--- a/code/game/objects/items/devices/swapper.dm
+++ b/code/game/objects/items/devices/swapper.dm
@@ -16,16 +16,13 @@
/obj/item/swapper/Destroy()
if(linked_swapper)
linked_swapper.linked_swapper = null //*inception music*
- linked_swapper.update_icon()
+ linked_swapper.update_appearance()
linked_swapper = null
return ..()
-/obj/item/swapper/update_icon()
- if(linked_swapper)
- icon_state = "swapper-linked"
- else
- icon_state = "swapper"
- ..()
+/obj/item/swapper/update_icon_state()
+ icon_state = "swapper[linked_swapper ? "-linked" : null]"
+ return ..()
/obj/item/swapper/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/swapper))
@@ -39,8 +36,8 @@
to_chat(user, "You establish a quantum link between the two devices.")
linked_swapper = other_swapper
other_swapper.linked_swapper = src
- update_icon()
- linked_swapper.update_icon()
+ update_appearance()
+ linked_swapper.update_appearance()
else
return ..()
@@ -75,9 +72,9 @@
to_chat(user, "You break the current quantum link.")
if(!QDELETED(linked_swapper))
linked_swapper.linked_swapper = null
- linked_swapper.update_icon()
+ linked_swapper.update_appearance()
linked_swapper = null
- update_icon()
+ update_appearance()
//Gets the topmost teleportable container
/obj/item/swapper/proc/get_teleportable_container()
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index b2b614e4d0489..6e63f012d6634 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -88,15 +88,18 @@
eject(usr)
-/obj/item/taperecorder/update_icon()
+/obj/item/taperecorder/update_icon_state()
if(!mytape)
icon_state = "taperecorder_empty"
- else if(recording)
+ return ..()
+ if(recording)
icon_state = "taperecorder_recording"
- else if(playing)
+ return ..()
+ if(playing)
icon_state = "taperecorder_playing"
- else
- icon_state = "taperecorder_idle"
+ return ..()
+ icon_state = "taperecorder_idle"
+ return ..()
/obj/item/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, list/message_mods = list())
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 6705e9c977078..c9c0d8de64791 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -248,7 +248,7 @@ effective or pretty fucking useless.
charge = max(0, charge - 12.5 * delta_time)//Quick decrease in light
else
charge = min(max_charge,charge + 25 * delta_time) //Charge in the dark
- animate(user,alpha = CLAMP(255 - charge,0,255),time = 10)
+ animate(user,alpha = clamp(255 - charge,0,255),time = 10)
/obj/item/shadowcloak/magician
name = "magician's cape"
diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm
index 02bb4c26e617a..c78c84c598f45 100644
--- a/code/game/objects/items/dice.dm
+++ b/code/game/objects/items/dice.dm
@@ -31,9 +31,9 @@
if(special_die == "100")
new /obj/item/dice/d100(src)
-/obj/item/storage/pill_bottle/dice/suicide_act(mob/user)
+/obj/item/storage/pill_bottle/dice/suicide_act(mob/living/user)
user.visible_message("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!")
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/storage/pill_bottle/dice_cup
name = "dice cup"
@@ -72,9 +72,9 @@
. = ..()
. += "[result] is face up."
-/obj/item/dice/suicide_act(mob/user)
+/obj/item/dice/suicide_act(mob/living/user)
user.visible_message("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!")
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/dice/d1
name = "d1"
@@ -155,8 +155,9 @@
w_class = WEIGHT_CLASS_SMALL
sides = 100
-/obj/item/dice/d100/update_icon()
- return
+/obj/item/dice/d100/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
/obj/item/dice/eightbd20
name = "strange d20"
@@ -165,8 +166,9 @@
sides = 20
special_faces = list("It is certain","It is decidedly so","Without a doubt","Yes, definitely","You may rely on it","As I see it, yes","Most likely","Outlook good","Yes","Signs point to yes","Reply hazy try again","Ask again later","Better not tell you now","Cannot predict now","Concentrate and ask again","Don't count on it","My reply is no","My sources say no","Outlook not so good","Very doubtful")
-/obj/item/dice/eightbd20/update_icon()
- return
+/obj/item/dice/eightbd20/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
/obj/item/dice/fourdd6
name = "4d d6"
@@ -175,8 +177,9 @@
sides = 48
special_faces = list("Cube-Side: 1-1","Cube-Side: 1-2","Cube-Side: 1-3","Cube-Side: 1-4","Cube-Side: 1-5","Cube-Side: 1-6","Cube-Side: 2-1","Cube-Side: 2-2","Cube-Side: 2-3","Cube-Side: 2-4","Cube-Side: 2-5","Cube-Side: 2-6","Cube-Side: 3-1","Cube-Side: 3-2","Cube-Side: 3-3","Cube-Side: 3-4","Cube-Side: 3-5","Cube-Side: 3-6","Cube-Side: 4-1","Cube-Side: 4-2","Cube-Side: 4-3","Cube-Side: 4-4","Cube-Side: 4-5","Cube-Side: 4-6","Cube-Side: 5-1","Cube-Side: 5-2","Cube-Side: 5-3","Cube-Side: 5-4","Cube-Side: 5-5","Cube-Side: 5-6","Cube-Side: 6-1","Cube-Side: 6-2","Cube-Side: 6-3","Cube-Side: 6-4","Cube-Side: 6-5","Cube-Side: 6-6","Cube-Side: 7-1","Cube-Side: 7-2","Cube-Side: 7-3","Cube-Side: 7-4","Cube-Side: 7-5","Cube-Side: 7-6","Cube-Side: 8-1","Cube-Side: 8-2","Cube-Side: 8-3","Cube-Side: 8-4","Cube-Side: 8-5","Cube-Side: 8-6")
-/obj/item/dice/fourdd6/update_icon()
- return
+/obj/item/dice/fourdd6/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
/obj/item/dice/attack_self(mob/user)
diceroll(user)
@@ -190,7 +193,7 @@
/obj/item/dice/proc/diceroll(mob/user)
result = roll(sides)
if(rigged != DICE_NOT_RIGGED && result != rigged_value)
- if(rigged == DICE_BASICALLY_RIGGED && prob(CLAMP(1/(sides - 1) * 100, 25, 80)))
+ if(rigged == DICE_BASICALLY_RIGGED && prob(clamp(1/(sides - 1) * 100, 25, 80)))
result = rigged_value
else if(rigged == DICE_TOTALLY_RIGGED)
result = rigged_value
@@ -215,9 +218,9 @@
else if(!src.throwing) //Dice was thrown and is coming to rest
visible_message("[src] rolls to a stop, landing on [result]. [comment]")
-/obj/item/dice/update_icon()
- cut_overlays()
- add_overlay("[src.icon_state]-[src.result]")
+/obj/item/dice/update_overlays()
+ . = ..()
+ . += "[icon_state]-[result]"
/obj/item/dice/microwave_act(obj/machinery/microwave/M)
if(microwave_riggable)
diff --git a/code/game/objects/items/etherealdiscoball.dm b/code/game/objects/items/etherealdiscoball.dm
index 0052b8b139f2f..9bb1a5195e072 100644
--- a/code/game/objects/items/etherealdiscoball.dm
+++ b/code/game/objects/items/etherealdiscoball.dm
@@ -64,9 +64,12 @@
update_icon()
TimerID = addtimer(CALLBACK(src, PROC_REF(DiscoFever)), 5, TIMER_STOPPABLE) //Call ourselves every 0.5 seconds to change colors
-/obj/structure/etherealball/update_icon()
- cut_overlays()
+/obj/structure/etherealball/update_icon_state()
icon_state = "ethdisco_head_[TurnedOn]"
+ return ..()
+
+/obj/structure/etherealball/update_overlays()
+ . = ..()
var/mutable_appearance/base_overlay = mutable_appearance(icon, "ethdisco_base")
base_overlay.appearance_flags = RESET_COLOR
- add_overlay(base_overlay)
+ . += base_overlay
diff --git a/code/game/objects/items/fireaxe.dm b/code/game/objects/items/fireaxe.dm
index accd29957222a..2023b63f773f3 100644
--- a/code/game/objects/items/fireaxe.dm
+++ b/code/game/objects/items/fireaxe.dm
@@ -33,9 +33,9 @@
icon_state = "[icon_prefix]0"
..()
-/obj/item/fireaxe/suicide_act(mob/user)
+/obj/item/fireaxe/suicide_act(mob/living/user)
user.visible_message("[user] axes [user.p_them()]self from head to toe! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/fireaxe/afterattack(atom/A, mob/user, proximity)
. = ..()
diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm
index e48e1674f9d45..d23d1efddf076 100644
--- a/code/game/objects/items/flamethrower.dm
+++ b/code/game/objects/items/flamethrower.dm
@@ -33,6 +33,10 @@
var/igniter_type = /obj/item/assembly/igniter
trigger_guard = TRIGGER_GUARD_NORMAL
+/obj/item/flamethrower/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+
/obj/item/flamethrower/Destroy()
if(weldtool)
qdel(weldtool)
@@ -55,21 +59,18 @@
igniter.flamethrower_process(location)
-/obj/item/flamethrower/update_icon()
- cut_overlays()
+/obj/item/flamethrower/update_icon_state()
+ item_state = "flamethrower_[lit]"
+ return ..()
+
+/obj/item/flamethrower/update_overlays()
+ . = ..()
if(igniter)
- add_overlay("+igniter[status]")
+ . += "+igniter[status]"
if(ptank)
- add_overlay("+ptank")
+ . += "+ptank"
if(lit)
- add_overlay("+lit")
- item_state = "flamethrower_1"
- else
- item_state = "flamethrower_0"
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_hands()
- return
+ . += "+lit"
/obj/item/flamethrower/afterattack(atom/target, mob/user, flag)
. = ..()
diff --git a/code/game/objects/items/food/dough.dm b/code/game/objects/items/food/dough.dm
new file mode 100644
index 0000000000000..12fe92f56d52d
--- /dev/null
+++ b/code/game/objects/items/food/dough.dm
@@ -0,0 +1,151 @@
+
+
+/////////////////// Dough Ingredients ////////////////////////
+
+/obj/item/food/dough
+ name = "dough"
+ desc = "A piece of dough."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "dough"
+ microwaved_type = /obj/item/food/bread/plain
+ food_reagents = list(/datum/reagent/consumable/nutriment = 6)
+ tastes = list("dough" = 1)
+ foodtypes = GRAIN
+
+/*
+/obj/item/food/dough/make_microwaveable()
+ AddElement(/datum/element/microwavable, /obj/item/food/bread/plain)
+*/
+
+// Dough + rolling pin = flat dough
+/obj/item/food/dough/make_processable()
+ AddElement(/datum/element/processable, TOOL_ROLLINGPIN, /obj/item/food/flatdough, 1, 3 SECONDS, table_required = TRUE, /*screentip_verb = "Flatten"*/)
+
+/obj/item/food/flatdough
+ name = "flat dough"
+ desc = "A flattened dough."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "flat dough"
+ microwaved_type = /obj/item/food/pizzabread
+ food_reagents = list(/datum/reagent/consumable/nutriment = 6)
+ tastes = list("dough" = 1)
+ foodtypes = GRAIN
+
+/*
+/obj/item/food/flatdough/make_microwaveable()
+ AddElement(/datum/element/microwavable, /obj/item/food/pizzabread)
+*/
+
+// sliceable into 3xdoughslices
+/obj/item/food/flatdough/make_processable()
+ AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/doughslice, 3, 3 SECONDS, table_required = TRUE, /*screentip_verb = "Slice"*/)
+
+/obj/item/food/pizzabread
+ name = "pizza bread"
+ desc = "Add ingredients to make a pizza."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "pizzabread"
+ food_reagents = list(/datum/reagent/consumable/nutriment = 7)
+ tastes = list("bread" = 1)
+ foodtypes = GRAIN
+
+/*
+/obj/item/food/pizzabread/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/customizable_reagent_holder, /obj/item/food/pizza/margherita, CUSTOM_INGREDIENT_ICON_SCATTER, max_ingredients = 12)
+*/
+
+/obj/item/food/doughslice
+ name = "dough slice"
+ desc = "A slice of dough. Can be cooked into a bun."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "doughslice"
+ microwaved_type = /obj/item/food/bun
+ food_reagents = list(/datum/reagent/consumable/nutriment = 2)
+ w_class = WEIGHT_CLASS_SMALL
+ tastes = list("dough" = 1)
+ foodtypes = GRAIN
+
+/*
+/obj/item/food/doughslice/make_microwaveable()
+ AddElement(/datum/element/microwavable, /obj/item/food/bun)
+*/
+
+/obj/item/food/bun
+ name = "bun"
+ desc = "A base for any self-respecting burger."
+ icon = 'icons/obj/food/burgerbread.dmi'
+ icon_state = "bun"
+ food_reagents = list(/datum/reagent/consumable/nutriment = 3)
+ w_class = WEIGHT_CLASS_SMALL
+ tastes = list("bun" = 1) // the bun tastes of bun.
+ foodtypes = GRAIN
+
+/*
+/obj/item/food/bun/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/customizable_reagent_holder, /obj/item/food/burger/empty, CUSTOM_INGREDIENT_ICON_STACKPLUSTOP)
+*/
+
+/obj/item/food/cakebatter
+ name = "cake batter"
+ desc = "Bake it to get a cake."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "cakebatter"
+ microwaved_type = /obj/item/food/cake/plain
+ food_reagents = list(/datum/reagent/consumable/nutriment = 9)
+ tastes = list("batter" = 1)
+ foodtypes = GRAIN | DAIRY
+
+/*
+/obj/item/food/cakebatter/make_microwaveable()
+ AddElement(/datum/element/microwavable, /obj/item/food/cake/plain)
+*/
+
+// Cake batter + rolling pin = pie dough
+/obj/item/food/cakebatter/make_processable()
+ AddElement(/datum/element/processable, TOOL_ROLLINGPIN, /obj/item/food/piedough, 1, 3 SECONDS, table_required = TRUE, /*screentip_verb = "Flatten"*/)
+
+/obj/item/food/piedough
+ name = "pie dough"
+ desc = "Cook it to get a pie."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "piedough"
+ microwaved_type = /obj/item/reagent_containers/food/snacks/pie/plain
+ food_reagents = list(/datum/reagent/consumable/nutriment = 9)
+ tastes = list("dough" = 1)
+ foodtypes = GRAIN | DAIRY
+
+/*
+/obj/item/food/piedough/make_microwaveable()
+ AddElement(/datum/element/microwavable, /obj/item/food/pie/plain)
+*/
+
+/obj/item/food/piedough/make_processable()
+ AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/rawpastrybase, 6, 3 SECONDS, table_required = TRUE, /*screentip_verb = "Slice"*/)
+
+/obj/item/food/rawpastrybase
+ name = "raw pastry base"
+ desc = "Must be cooked before use."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "rawpastrybase"
+ microwaved_type = /obj/item/food/pastrybase
+ food_reagents = list(/datum/reagent/consumable/nutriment = 2)
+ w_class = WEIGHT_CLASS_SMALL
+ tastes = list("raw pastry" = 1)
+ foodtypes = GRAIN | DAIRY
+
+/*
+/obj/item/food/rawpastrybase/make_microwaveable()
+ AddElement(/datum/element/microwavable, /obj/item/food/pastrybase)
+*/
+
+/obj/item/food/pastrybase
+ name = "pastry base"
+ desc = "A base for any self-respecting pastry."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "pastrybase"
+ food_reagents = list(/datum/reagent/consumable/nutriment = 3)
+ w_class = WEIGHT_CLASS_SMALL
+ tastes = list("pastry" = 1)
+ foodtypes = GRAIN | DAIRY
diff --git a/code/game/objects/items/food/mexican.dm b/code/game/objects/items/food/mexican.dm
new file mode 100644
index 0000000000000..2bb7967fe262f
--- /dev/null
+++ b/code/game/objects/items/food/mexican.dm
@@ -0,0 +1,164 @@
+/obj/item/food/tortilla
+ name = "tortilla"
+ desc = "The base for all your burritos."
+ icon = 'icons/obj/food/food_ingredients.dmi'
+ icon_state = "tortilla"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 3,
+ /datum/reagent/consumable/nutriment/vitamin = 1,
+ )
+ tastes = list("tortilla" = 1)
+ foodtypes = GRAIN
+ w_class = WEIGHT_CLASS_TINY
+
+/obj/item/food/burrito
+ name = "burrito"
+ desc = "Tortilla wrapped goodness."
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "burrito"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 2,
+ /datum/reagent/consumable/nutriment/vitamin = 1,
+ )
+ tastes = list("tortilla" = 2, "beans" = 3)
+ foodtypes = GRAIN
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/cheesyburrito
+ name = "cheesy burrito"
+ desc = "It's a burrito filled with cheese."
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "cheesyburrito"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 3,
+ /datum/reagent/consumable/nutriment/vitamin = 2,
+ )
+ tastes = list("tortilla" = 2, "beans" = 3, "cheese" = 1)
+ foodtypes = GRAIN | DAIRY
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/carneburrito
+ name = "carne asada burrito"
+ desc = "The best burrito for meat lovers."
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "carneburrito"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 2,
+ /datum/reagent/consumable/nutriment/protein = 6,
+ /datum/reagent/consumable/nutriment/vitamin = 1,
+ )
+ tastes = list("tortilla" = 2, "meat" = 4)
+ foodtypes = GRAIN | MEAT
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/fuegoburrito
+ name = "fuego plasma burrito"
+ desc = "A super spicy burrito."
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "fuegoburrito"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 3,
+ /datum/reagent/consumable/nutriment/protein = 2,
+ /datum/reagent/consumable/capsaicin = 5,
+ /datum/reagent/consumable/nutriment/vitamin = 3,
+ )
+ tastes = list("tortilla" = 2, "beans" = 3, "hot peppers" = 1)
+ foodtypes = GRAIN
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/nachos
+ name = "nachos"
+ desc = "Chips from Space Mexico."
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "nachos"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 6,
+ /datum/reagent/consumable/nutriment/vitamin = 2,
+ )
+ tastes = list("nachos" = 1)
+ foodtypes = GRAIN | FRIED
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/cheesynachos
+ name = "cheesy nachos"
+ desc = "The delicious combination of nachos and melting cheese."
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "cheesynachos"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 6,
+ /datum/reagent/consumable/nutriment/protein = 1,
+ /datum/reagent/consumable/nutriment/vitamin = 3,
+ )
+ tastes = list("nachos" = 2, "cheese" = 1)
+ foodtypes = GRAIN | FRIED | DAIRY
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/cubannachos
+ name = "Cuban nachos"
+ desc = "That's some dangerously spicy nachos."
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "cubannachos"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 7,
+ /datum/reagent/consumable/capsaicin = 8,
+ /datum/reagent/consumable/nutriment/vitamin = 4,
+ )
+ tastes = list("nachos" = 2, "hot pepper" = 1)
+ foodtypes = VEGETABLES | FRIED | DAIRY
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/taco
+ name = "classic taco"
+ desc = "A traditional taco with meat, cheese, and lettuce."
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "taco"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 2,
+ /datum/reagent/consumable/nutriment/protein = 3,
+ /datum/reagent/consumable/nutriment/vitamin = 2,
+ )
+ tastes = list("taco" = 4, "meat" = 2, "cheese" = 2, "lettuce" = 1)
+ foodtypes = MEAT | DAIRY | GRAIN | VEGETABLES
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/taco/plain
+ name = "plain taco"
+ desc = "A traditional taco with meat and cheese, minus the rabbit food."
+ icon_state = "taco_plain"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 2,
+ /datum/reagent/consumable/nutriment/protein = 2,
+ /datum/reagent/consumable/nutriment/vitamin = 1,
+ )
+ tastes = list("taco" = 4, "meat" = 2, "cheese" = 2)
+ foodtypes = MEAT | DAIRY | GRAIN
+
+/obj/item/food/enchiladas
+ name = "enchiladas"
+ desc = "Viva La Mexico!"
+ icon = 'icons/obj/food/mexican.dmi'
+ icon_state = "enchiladas"
+ bite_consumption = 4
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 4,
+ /datum/reagent/consumable/nutriment/protein = 7,
+ /datum/reagent/consumable/capsaicin = 6,
+ /datum/reagent/consumable/nutriment/vitamin = 2
+ )
+ tastes = list("hot peppers" = 1, "meat" = 3, "cheese" = 1, "sour cream" = 1)
+ foodtypes = MEAT | GRAIN
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/stuffedlegion
+ name = "stuffed legion"
+ desc = "The former skull of a damned human, filled with goliath meat. It has a decorative lava pool made of ketchup and hotsauce."
+ icon_state = "stuffed_legion"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 2,
+ /datum/reagent/consumable/nutriment/protein = 5,
+ /datum/reagent/consumable/nutriment/vitamin = 5,
+ /datum/reagent/consumable/capsaicin = 2,
+ )
+ tastes = list("death" = 2, "rock" = 1, "meat" = 1, "hot peppers" = 1)
+ foodtypes = MEAT
+ w_class = WEIGHT_CLASS_SMALL
diff --git a/code/game/objects/items/food/pizza.dm b/code/game/objects/items/food/pizza.dm
index 00489fbb6e176..afddd4b3c03ae 100644
--- a/code/game/objects/items/food/pizza.dm
+++ b/code/game/objects/items/food/pizza.dm
@@ -244,6 +244,7 @@
/obj/item/food/proc/i_kill_you(obj/item/I, mob/user)
if(istype(I, /obj/item/reagent_containers/food/snacks/pineappleslice))
to_chat(user, "If you want something crazy like pineapple, I'll kill you.") //this is in bigger text because it's hard to spam something that gibs you, and so that you're perfectly aware of the reason why you died
+ user.investigate_log("has been gibbed by putting pineapple on an arnold pizza.", INVESTIGATE_DEATHS)
user.gib() //if you want something crazy like pineapple, i'll kill you
else if(istype(I, /obj/item/reagent_containers/food/snacks/grown/mushroom) && iscarbon(user))
to_chat(user, "So, if you want mushroom, shut up.") //not as large as the pineapple text, because you could in theory spam it
diff --git a/code/game/objects/items/gift.dm b/code/game/objects/items/gift.dm
index e15249f791e01..569e622ad49cb 100644
--- a/code/game/objects/items/gift.dm
+++ b/code/game/objects/items/gift.dm
@@ -28,9 +28,9 @@ GLOBAL_LIST_EMPTY(possible_gifts)
contains_type = get_gift_type()
-/obj/item/a_gift/suicide_act(mob/user)
+/obj/item/a_gift/suicide_act(mob/living/user)
user.visible_message("[user] peeks inside [src] and cries [user.p_them()]self to death! It looks like [user.p_they()] [user.p_were()] on the naughty list...")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/a_gift/examine(mob/M)
. = ..()
diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm
index 4d6f0f2b9b64a..114822d13d90d 100644
--- a/code/game/objects/items/grenades/chem_grenade.dm
+++ b/code/game/objects/items/grenades/chem_grenade.dm
@@ -18,7 +18,7 @@
/obj/item/grenade/chem_grenade/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
+ AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES)
/obj/item/grenade/chem_grenade/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm
index a2a0374933e11..0d7efe7c2aa12 100644
--- a/code/game/objects/items/grenades/plastic.dm
+++ b/code/game/objects/items/grenades/plastic.dm
@@ -31,7 +31,7 @@
/obj/item/grenade/plastic/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
+ AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES)
/obj/item/grenade/plastic/Destroy()
qdel(nadeassembly)
@@ -106,7 +106,7 @@
return
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
if(user.get_active_held_item() == src)
- newtime = CLAMP(newtime, 10, 60000)
+ newtime = clamp(newtime, 10, 60000)
det_time = newtime
to_chat(user, "Timer set for [det_time] seconds.")
@@ -165,7 +165,7 @@
message_say = "VIVA LA REVOLUTION!"
M.say(message_say, forced="C4 suicide")
-/obj/item/grenade/plastic/suicide_act(mob/user)
+/obj/item/grenade/plastic/suicide_act(mob/living/user)
message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [src] at [ADMIN_VERBOSEJMP(user)]")
log_game("[key_name(user)] suicided with [src] at [AREACOORD(user)]")
user.visible_message("[user] activates [src] and holds it above [user.p_their()] head! It looks like [user.p_theyre()] going out with a bang!")
@@ -201,7 +201,7 @@
target = null
return ..()
-/obj/item/grenade/plastic/c4/suicide_act(mob/user)
+/obj/item/grenade/plastic/c4/suicide_act(mob/living/user)
user.visible_message("[user] activates the [src.name] and holds it above [user.p_their()] head! It looks like [user.p_theyre()] going out with a bang!")
shout_syndicate_crap(user)
target = user
diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm
index cf5478cfbd15b..4cd68a1414652 100644
--- a/code/game/objects/items/handcuffs.dm
+++ b/code/game/objects/items/handcuffs.dm
@@ -4,7 +4,7 @@
/obj/item/restraints/suicide_act(mob/living/carbon/user)
user.visible_message("[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return(OXYLOSS)
+ return OXYLOSS
/obj/item/restraints/Destroy()
if(iscarbon(loc))
@@ -230,24 +230,25 @@
)
AddElement(/datum/element/connect_loc, loc_connections)
-/obj/item/restraints/legcuffs/beartrap/update_icon()
+/obj/item/restraints/legcuffs/beartrap/update_icon_state()
icon_state = "[initial(icon_state)][armed]"
+ return ..()
-/obj/item/restraints/legcuffs/beartrap/suicide_act(mob/user)
+/obj/item/restraints/legcuffs/beartrap/suicide_act(mob/living/user)
user.visible_message("[user] is sticking [user.p_their()] head in the [src.name]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/restraints/legcuffs/beartrap/attack_self(mob/user)
..()
if(ishuman(user) && !user.stat && !user.restrained())
armed = !armed
- update_icon()
+ update_appearance()
to_chat(user, "[src] is now [armed ? "armed" : "disarmed"]")
/obj/item/restraints/legcuffs/beartrap/proc/close_trap()
armed = FALSE
- update_icon()
+ update_appearance()
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
/obj/item/restraints/legcuffs/beartrap/proc/spring_trap(datum/source, AM as mob|obj)
diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/his_grace.dm
index e302a94a462a0..c47136f77d836 100644
--- a/code/game/objects/items/his_grace.dm
+++ b/code/game/objects/items/his_grace.dm
@@ -201,9 +201,9 @@
/obj/item/his_grace/proc/adjust_bloodthirst(amt)
prev_bloodthirst = bloodthirst
if(prev_bloodthirst < HIS_GRACE_CONSUME_OWNER && !ascended)
- bloodthirst = CLAMP(bloodthirst + amt, HIS_GRACE_SATIATED, HIS_GRACE_CONSUME_OWNER)
+ bloodthirst = clamp(bloodthirst + amt, HIS_GRACE_SATIATED, HIS_GRACE_CONSUME_OWNER)
else if(!ascended)
- bloodthirst = CLAMP(bloodthirst + amt, HIS_GRACE_CONSUME_OWNER, HIS_GRACE_FALL_ASLEEP)
+ bloodthirst = clamp(bloodthirst + amt, HIS_GRACE_CONSUME_OWNER, HIS_GRACE_FALL_ASLEEP)
update_stats()
/obj/item/his_grace/proc/update_stats()
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 39d03f44ab1e4..7cdd4c7c48c8f 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -298,7 +298,7 @@
on_clear_callback = CALLBACK(src, PROC_REF(on_cult_rune_removed)), \
effects_we_clear = list(/obj/effect/rune, /obj/effect/heretic_rune))
-/obj/item/nullrod/suicide_act(mob/user)
+/obj/item/nullrod/suicide_act(mob/living/user)
user.visible_message("[user] is killing [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to get closer to god!")
return (BRUTELOSS|FIRELOSS)
diff --git a/code/game/objects/items/hot_potato.dm b/code/game/objects/items/hot_potato.dm
index a2633f5870fd5..9d05a23523b47 100644
--- a/code/game/objects/items/hot_potato.dm
+++ b/code/game/objects/items/hot_potato.dm
@@ -77,7 +77,7 @@
L.SetImmobilized(0)
L.SetParalyzed(0)
L.SetUnconscious(0)
- L.reagents.add_reagent(/datum/reagent/medicine/muscle_stimulant, CLAMP(5 - L.reagents.get_reagent_amount(/datum/reagent/medicine/muscle_stimulant), 0, 5)) //If you don't have legs or get bola'd, tough luck!
+ L.reagents.add_reagent(/datum/reagent/medicine/muscle_stimulant, clamp(5 - L.reagents.get_reagent_amount(/datum/reagent/medicine/muscle_stimulant), 0, 5)) //If you don't have legs or get bola'd, tough luck!
colorize(L)
/obj/item/hot_potato/examine(mob/user)
@@ -157,8 +157,9 @@
colorize(null)
active = FALSE
-/obj/item/hot_potato/update_icon()
- icon_state = active? icon_on : icon_off
+/obj/item/hot_potato/update_icon_state()
+ icon_state = active ? icon_on : icon_off
+ return ..()
/obj/item/hot_potato/syndicate
detonate_light_range = 4
diff --git a/code/game/objects/items/hourglass.dm b/code/game/objects/items/hourglass.dm
index 7451142356fd7..e62d7d8d5c792 100644
--- a/code/game/objects/items/hourglass.dm
+++ b/code/game/objects/items/hourglass.dm
@@ -29,11 +29,9 @@
to_chat(user,"You stop the [src].") //Sand magically flows back because that's more convinient to use.
stop()
-/obj/item/hourglass/update_icon()
- if(timing_id)
- icon_state = "hourglass_active"
- else
- icon_state = "hourglass_idle"
+/obj/item/hourglass/update_icon_state()
+ icon_state = "hourglass_[timing_id ? "active" : "idle"]"
+ return ..()
/obj/item/hourglass/proc/start()
finish_time = world.time + time
diff --git a/code/game/objects/items/implants/implant_explosive.dm b/code/game/objects/items/implants/implant_explosive.dm
index be032cd839c2d..ee76e644aa2b7 100644
--- a/code/game/objects/items/implants/implant_explosive.dm
+++ b/code/game/objects/items/implants/implant_explosive.dm
@@ -47,7 +47,8 @@
if(delay <= 7)
explosion(src,heavy,medium,weak,weak, flame_range = weak)
if(imp_in)
- imp_in.gib(1)
+ imp_in.investigate_log("has been gibbed by an explosive implant.", INVESTIGATE_DEATHS)
+ imp_in.gib(TRUE)
qdel(src)
return TRUE
timed_explosion()
@@ -80,7 +81,8 @@
sleep(delay*0.25)
explosion(src,heavy,medium,weak,weak, flame_range = weak)
if(imp_in)
- imp_in.gib(1)
+ imp_in.investigate_log("has been gibbed by an explosive implant.", INVESTIGATE_DEATHS)
+ imp_in.gib(TRUE)
qdel(src)
/obj/item/implant/explosive/macro
diff --git a/code/game/objects/items/implants/implantcase.dm b/code/game/objects/items/implants/implantcase.dm
index 8999086d185fc..69004904a9516 100644
--- a/code/game/objects/items/implants/implantcase.dm
+++ b/code/game/objects/items/implants/implantcase.dm
@@ -14,49 +14,40 @@
var/imp_type
-/obj/item/implantcase/update_icon()
- if(imp)
- icon_state = "implantcase-[imp.implant_color]"
- reagents = imp.reagents
- else
- icon_state = "implantcase-0"
- reagents = null
-
+/obj/item/implantcase/update_icon_state()
+ icon_state = "implantcase-[imp ? imp.implant_color : 0]"
+ return ..()
-/obj/item/implantcase/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/pen))
+/obj/item/implantcase/attackby(obj/item/used_item, mob/living/user, params)
+ if(istype(used_item, /obj/item/pen))
if(!user.is_literate())
to_chat(user, "You scribble illegibly on the side of [src]!")
return
- var/t = stripped_input(user, "What would you like the label to be?", name, null)
- if(user.get_active_held_item() != W)
+ var/new_name = stripped_input(user, "What would you like the label to be?", name, null)
+ if(user.get_active_held_item() != used_item)
return
if(!user.canUseTopic(src, BE_CLOSE))
return
- if(t)
- name = "implant case - '[t]'"
+ if(new_name)
+ name = "implant case - '[new_name]'"
else
name = "implant case"
- else if(istype(W, /obj/item/implanter))
- var/obj/item/implanter/I = W
- if(I.imp)
- if(imp || I.imp.imp_in)
- return
- I.imp.forceMove(src)
- imp = I.imp
- I.imp = null
- update_icon()
- I.update_icon()
- else
- if(imp)
- if(I.imp)
- return
- imp.forceMove(I)
- I.imp = imp
- imp = null
- update_icon()
- I.update_icon()
-
+ else if(istype(used_item, /obj/item/implanter))
+ var/obj/item/implanter/used_implanter = used_item
+ if(used_implanter.imp && !imp)
+ used_implanter.imp.forceMove(src)
+ imp = used_implanter.imp
+ used_implanter.imp = null
+ update_appearance()
+ reagents = imp.reagents
+ used_implanter.update_appearance()
+ else if(!used_implanter.imp && imp)
+ imp.forceMove(used_implanter)
+ used_implanter.imp = imp
+ imp = null
+ reagents = null
+ update_appearance()
+ used_implanter.update_appearance()
else
return ..()
@@ -64,7 +55,9 @@
. = ..()
if(imp_type)
imp = new imp_type(src)
- update_icon()
+ update_appearance()
+ if(imp)
+ reagents = imp.reagents
/obj/item/implantcase/tracking
diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm
index 4c8ad227a2ff5..132b29b719923 100644
--- a/code/game/objects/items/implants/implantchair.dm
+++ b/code/game/objects/items/implants/implantchair.dm
@@ -96,16 +96,18 @@
visible_message("[M] has been implanted by [src].")
return TRUE
-/obj/machinery/implantchair/update_icon()
+/obj/machinery/implantchair/update_icon_state()
icon_state = initial(icon_state)
if(state_open)
icon_state += "_open"
if(occupant)
icon_state += "_occupied"
+ return ..()
+
+/obj/machinery/implantchair/update_overlays()
+ . = ..()
if(ready)
- add_overlay("ready")
- else
- cut_overlays()
+ . += "ready"
/obj/machinery/implantchair/proc/replenish()
if(ready_implants < max_implants)
diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm
index bfa06589c23cd..9991c55150a68 100644
--- a/code/game/objects/items/implants/implanter.dm
+++ b/code/game/objects/items/implants/implanter.dm
@@ -13,17 +13,14 @@
var/obj/item/implant/imp = null
var/imp_type = null
-
-/obj/item/implanter/update_icon()
- if(imp)
- icon_state = "implanter1"
- else
- icon_state = "implanter0"
-
+/obj/item/implanter/update_icon_state()
+ icon_state = "implanter[imp ? 1 : 0]"
+ return ..()
/obj/item/implanter/attack(mob/living/M, mob/user)
if(!istype(M))
return
+
if(user && imp)
if(M != user)
M.visible_message("[user] is attempting to implant [M].", \
diff --git a/code/game/objects/items/implants/implantpad.dm b/code/game/objects/items/implants/implantpad.dm
index 82fdf8131cb98..800f589742e5f 100644
--- a/code/game/objects/items/implants/implantpad.dm
+++ b/code/game/objects/items/implants/implantpad.dm
@@ -11,8 +11,9 @@
w_class = WEIGHT_CLASS_SMALL
var/obj/item/implantcase/case = null
-/obj/item/implantpad/update_icon()
+/obj/item/implantpad/update_icon_state()
icon_state = "implantpad-[!QDELETED(case)]"
+ return ..()
/obj/item/implantpad/examine(mob/user)
. = ..()
diff --git a/code/game/objects/items/inducer.dm b/code/game/objects/items/inducer.dm
index f0d32cf422051..c56fd8b8574e7 100644
--- a/code/game/objects/items/inducer.dm
+++ b/code/game/objects/items/inducer.dm
@@ -176,13 +176,13 @@
if(opened)
. += "Its battery compartment is open."
-/obj/item/inducer/update_icon()
- cut_overlays()
+/obj/item/inducer/update_overlays()
+ . = ..()
if(opened)
if(!cell)
- add_overlay("inducer-nobat")
+ . += "inducer-nobat"
else
- add_overlay("inducer-bat")
+ . += "inducer-bat"
///Starts empty for engineering protolathe
/obj/item/inducer/eng
diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/knives.dm
index 12561ce5fe64e..81203389c7a6f 100644
--- a/code/game/objects/items/knives.dm
+++ b/code/game/objects/items/knives.dm
@@ -42,11 +42,11 @@
/obj/item/knife/proc/set_butchering()
AddComponent(/datum/component/butchering, 8 SECONDS - force, 100, force - 10) //bonus chance increases depending on force
-/obj/item/knife/suicide_act(mob/user)
+/obj/item/knife/suicide_act(mob/living/user)
user.visible_message(pick("[user] is slitting [user.p_their()] wrists with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.", \
"[user] is slitting [user.p_their()] throat with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.", \
"[user] is slitting [user.p_their()] stomach open with the [src.name]! It looks like [user.p_theyre()] trying to commit seppuku."))
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/knife/ritual
name = "ritual knife"
@@ -174,6 +174,6 @@
embedding = list("embedded_pain_multiplier" = 6, "embed_chance" = 40, "embedded_fall_chance" = 5, "armour_block" = 30) // Incentive to disengage/stop chasing when stuck
attack_verb = list("stuck", "shanked")
-/obj/item/knife/shank/suicide_act(mob/user)
+/obj/item/knife/shank/suicide_act(mob/living/user)
user.visible_message("[user] is slitting [user.p_their()] [pick("wrists", "throat")] with the shank! It looks like [user.p_theyre()] trying to commit suicide.")
- return (BRUTELOSS)
+ return BRUTELOSS
diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm
index 968ce6317c124..07dfcc1e840b8 100644
--- a/code/game/objects/items/manuals.dm
+++ b/code/game/objects/items/manuals.dm
@@ -409,7 +409,7 @@
title = "Toxins or: How I Learned to Stop Worrying and Love the Maxcap"
page_link = "Guide_to_toxins"
-/obj/item/book/manual/wiki/toxins/suicide_act(mob/user)
+/obj/item/book/manual/wiki/toxins/suicide_act(mob/living/user)
var/mob/living/carbon/human/H = user
user.visible_message("[user] starts dancing to the Rhumba Beat! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/effects/spray.ogg', 10, 1, -3)
@@ -428,7 +428,7 @@
H.spawn_gibs()
H.spill_organs()
H.spread_bodyparts()
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/book/manual/wiki/plumbing
name = "Chemical Factories Without Narcotics"
@@ -443,3 +443,52 @@
author = "Phillippe French"
title = "Xenoarchaeology Fieldguide"
page_link = "Guide_to_Artifacts"
+
+/obj/item/book/manual/wiki/sopcommand
+ name = "Command Standard Operating Procedures"
+ icon_state ="sop1"
+ author = "Nanotrasen Department of Employee Resources"
+ title = "Command Standard Operating Procedures"
+ page_link = "Department_Standard_Operating_Procedure:_Command"
+
+/obj/item/book/manual/wiki/sopsecurity
+ name = "Security Standard Operating Procedures"
+ icon_state ="sop2"
+ author = "Nanotrasen Department of Employee Resources"
+ title = "Security Standard Operating Procedures"
+ page_link = "Department_Standard_Operating_Procedure:_Security"
+
+/obj/item/book/manual/wiki/sopengineering
+ name = "Engineering Standard Operating Procedures"
+ icon_state ="sop3"
+ author = "Nanotrasen Department of Employee Resources"
+ title = "Engineering Standard Operating Procedures"
+ page_link = "Department_Standard_Operating_Procedure:_Engineering"
+
+/obj/item/book/manual/wiki/sopsupply
+ name = "Supply Standard Operating Procedures"
+ icon_state ="sop4"
+ author = "Nanotrasen Department of Employee Resources"
+ title = "Supply Standard Operating Procedures"
+ page_link = "Department_Standard_Operating_Procedure:_Supply"
+
+/obj/item/book/manual/wiki/sopscience
+ name = "Science Standard Operating Procedures"
+ icon_state ="sop5"
+ author = "Nanotrasen Department of Employee Resources"
+ title = "Science Standard Operating Procedures"
+ page_link = "Department_Standard_Operating_Procedure:_Science"
+
+/obj/item/book/manual/wiki/sopmedical
+ name = "Medical Standard Operating Procedures"
+ icon_state ="sop6"
+ author = "Nanotrasen Department of Employee Resources"
+ title = "Medical Standard Operating Procedures"
+ page_link = "Department_Standard_Operating_Procedure:_Medical"
+
+/obj/item/book/manual/wiki/sopservice
+ name = "Service Standard Operating Procedures"
+ icon_state ="sop7"
+ author = "Nanotrasen Department of Employee Resources"
+ title = "Service Standard Operating Procedures"
+ page_link = "Department_Standard_Operating_Procedure:_Service"
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index ba3b679c356fe..f74a0cb7d1734 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -20,7 +20,7 @@
STOP_PROCESSING(SSobj, src)
return ..()
-/obj/item/melee/transforming/energy/suicide_act(mob/user)
+/obj/item/melee/transforming/energy/suicide_act(mob/living/user)
if(!active)
transform_weapon(user, TRUE)
user.visible_message("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku!")
@@ -84,7 +84,7 @@
attack_verb_on = list()
light_color = "#40ceff"
-/obj/item/melee/transforming/energy/axe/suicide_act(mob/user)
+/obj/item/melee/transforming/energy/axe/suicide_act(mob/living/user)
user.visible_message("[user] swings [src] towards [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!")
return (BRUTELOSS|FIRELOSS)
@@ -135,6 +135,7 @@
w_class = WEIGHT_CLASS_NORMAL
sharpness = IS_SHARP
light_color = "#40ceff"
+ tool_behaviour = TOOL_SAW
toolspeed = 0.7 //faster as a saw
/obj/item/melee/transforming/energy/sword/cyborg
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 4cb503ea7afe9..6777799073f26 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -25,9 +25,9 @@
hitsound = 'sound/weapons/chainhit.ogg'
materials = list(/datum/material/iron = 1000)
-/obj/item/melee/chainofcommand/suicide_act(mob/user)
+/obj/item/melee/chainofcommand/suicide_act(mob/living/user)
user.visible_message("[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/melee/synthetic_arm_blade
name = "synthetic arm blade"
@@ -355,7 +355,7 @@
return ..()
return 0
-/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
+/obj/item/melee/classic_baton/telescopic/suicide_act(mob/living/user)
var/mob/living/carbon/human/H = user
var/obj/item/organ/brain/B = H.getorgan(/obj/item/organ/brain)
@@ -371,7 +371,7 @@
H.internal_organs -= B
qdel(B)
new /obj/effect/gibspawner/generic(H.drop_location(), H)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/melee/classic_baton/police/telescopic/attack_self(mob/user)
on = !on
@@ -662,7 +662,7 @@
consume_everything(P)
return BULLET_ACT_HIT
-/obj/item/melee/supermatter_sword/suicide_act(mob/user)
+/obj/item/melee/supermatter_sword/suicide_act(mob/living/user)
user.visible_message("[user] touches [src]'s blade. It looks like [user.p_theyre()] tired of waiting for the radiation to kill [user.p_them()]!")
user.dropItemToGround(src, TRUE)
shard.Bumped(user)
@@ -798,12 +798,10 @@
held_sausage = null
update_icon()
-/obj/item/melee/roastingstick/update_icon()
+/obj/item/melee/roastingstick/update_overlays()
. = ..()
- cut_overlays()
if (held_sausage)
- var/mutable_appearance/sausage = mutable_appearance(icon, "roastingstick_sausage")
- add_overlay(sausage)
+ . += mutable_appearance(icon, "roastingstick_sausage")
/obj/item/melee/roastingstick/proc/extend(user)
to_chat(user, "You extend [src].")
diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm
index 5efe3a176391e..a7e7cfefec59a 100644
--- a/code/game/objects/items/pet_carrier.dm
+++ b/code/game/objects/items/pet_carrier.dm
@@ -6,6 +6,7 @@
name = "pet carrier"
desc = "A big white-and-blue pet carrier. Good for carrying meat to the chef cute animals around."
icon = 'icons/obj/pet_carrier.dmi'
+ base_icon_state = "pet_carrier"
icon_state = "pet_carrier_open"
item_state = "pet_carrier"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
@@ -142,14 +143,17 @@
update_icon()
remove_occupant(user)
-/obj/item/pet_carrier/update_icon()
- cut_overlay("unlocked")
- cut_overlay("locked")
+/obj/item/pet_carrier/update_icon_state()
if(open)
icon_state = initial(icon_state)
- else
- icon_state = "pet_carrier_[!occupants.len ? "closed" : "occupied"]"
- add_overlay("[locked ? "" : "un"]locked")
+ return ..()
+ icon_state = "[base_icon_state]_[!occupants.len ? "closed" : "occupied"]"
+ return ..()
+
+/obj/item/pet_carrier/update_overlays()
+ . = ..()
+ if(!open)
+ . += "[locked ? "" : "un"]locked"
/obj/item/pet_carrier/MouseDrop(atom/over_atom)
. = ..()
diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm
index b1e27989383b0..14e9596a6f145 100644
--- a/code/game/objects/items/pinpointer.dm
+++ b/code/game/objects/items/pinpointer.dm
@@ -75,12 +75,12 @@
/obj/item/pinpointer/proc/scan_for_target()
return
-/obj/item/pinpointer/update_icon()
- cut_overlays()
+/obj/item/pinpointer/update_overlays()
+ . = ..()
if(!active)
return
if(!target || (!isnull(jamming_resistance) && src.is_jammed(jamming_resistance)))
- add_overlay("pinon[alert ? "alert" : ""]null[icon_suffix]")
+ . += "pinon[alert ? "alert" : ""]null[icon_suffix]"
return
var/turf/here = get_turf(src)
var/turf/there = get_turf(target)
@@ -101,15 +101,15 @@
if(pin_z_result)
var/result = compare_z(here_zlevel, there_zlevel)
if(isnull(result)) // null: no good to track z levels
- add_overlay("pinon[alert ? "alert" : ""]null[icon_suffix]")
+ . += "pinon[alert ? "alert" : ""]null[icon_suffix]"
return
else if(!result) // FALSE: z-levels are in different groups. (i.e. Station v.s. Lavaland)
if(!tracks_grand_z)
- add_overlay("pinon[alert ? "alert" : ""]null[icon_suffix]")
+ . += "pinon[alert ? "alert" : ""]null[icon_suffix]"
return
else
z_level_direction = "located at [SSorbits.get_orbital_map_name_from_z(there_zlevel) || scramble_message_replace_chars("???????", replaceprob=85)]"
- add_overlay("pinon[alert ? "alert" : ""]z[icon_suffix]")
+ . += "pinon[alert ? "alert" : ""]z[icon_suffix]"
return
else // TRUE: z-levels are in the same group (i.e. multi-floored station)
z_level_direction = "located [abs(there_zlevel - here_zlevel)] floors [pin_z_result]"
@@ -131,13 +131,13 @@
// building overlays with sprite components
- add_overlay(alert ? "pincomp_base_alert[icon_suffix]" : "pincomp_base[icon_suffix]")
+ . += alert ? "pincomp_base_alert[icon_suffix]" : "pincomp_base[icon_suffix]"
if(pin_z_result)
- add_overlay("pincomp_z_[pin_z_result][icon_suffix]")
- add_overlay("pincomp_arrow_[pin_xy_result][icon_suffix]")
+ . += "pincomp_z_[pin_z_result][icon_suffix]"
+ . += "pincomp_arrow_[pin_xy_result][icon_suffix]"
if(alert)
pin_xy_result = pin_xy_result=="direct" ? "direct_" : ""
- add_overlay("pincomp_arrow_[pin_xy_result]alert[icon_suffix]")
+ . += "pincomp_arrow_[pin_xy_result]alert[icon_suffix]"
/obj/item/pinpointer/proc/trackable(atom/target)
return checks_trackable_core(src, target, tracks_grand_z, jamming_resistance)
diff --git a/code/game/objects/items/pitchfork.dm b/code/game/objects/items/pitchfork.dm
index 462111bd1a808..41f97943791cb 100644
--- a/code/game/objects/items/pitchfork.dm
+++ b/code/game/objects/items/pitchfork.dm
@@ -55,9 +55,9 @@
. = ..()
AddComponent(/datum/component/two_handed, force_unwielded=100, force_wielded=500000) // Kills you DEAD
-/obj/item/pitchfork/suicide_act(mob/user)
+/obj/item/pitchfork/suicide_act(mob/living/user)
user.visible_message("[user] impales [user.p_them()]self in [user.p_their()] abdomen with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/pitchfork/demonic/pickup(mob/living/user)
. = ..()
diff --git a/code/game/objects/items/pneumaticCannon.dm b/code/game/objects/items/pneumaticCannon.dm
index 61a115980ad44..81914cd9ba3d3 100644
--- a/code/game/objects/items/pneumaticCannon.dm
+++ b/code/game/objects/items/pneumaticCannon.dm
@@ -206,8 +206,8 @@
return target
var/x_o = (target.x - starting.x)
var/y_o = (target.y - starting.y)
- var/new_x = CLAMP((starting.x + (x_o * range_multiplier)), 0, world.maxx)
- var/new_y = CLAMP((starting.y + (y_o * range_multiplier)), 0, world.maxy)
+ var/new_x = clamp((starting.x + (x_o * range_multiplier)), 0, world.maxx)
+ var/new_y = clamp((starting.y + (y_o * range_multiplier)), 0, world.maxy)
var/turf/newtarget = locate(new_x, new_y, starting.z)
return newtarget
@@ -247,11 +247,11 @@
tank = thetank
update_icon()
-/obj/item/pneumatic_cannon/update_icon()
- cut_overlays()
+/obj/item/pneumatic_cannon/update_overlays()
+ . = ..()
if(!tank)
return
- add_overlay(tank.icon_state)
+ . += tank.icon_state
/obj/item/pneumatic_cannon/proc/fill_with_type(type, amount)
if(!ispath(type, /obj) && !ispath(type, /mob))
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 1b959715ec7d7..e902adef54df6 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -160,9 +160,9 @@
var/static/list/charge_machines = typecacheof(list(/obj/machinery/cell_charger, /obj/machinery/recharger, /obj/machinery/recharge_station, /obj/machinery/mech_bay_recharge_port))
var/static/list/charge_items = typecacheof(list(/obj/item/stock_parts/cell, /obj/item/gun/energy))
-/obj/item/borg/charger/update_icon()
- ..()
+/obj/item/borg/charger/update_icon_state()
icon_state = "charger_[mode]"
+ return ..()
/obj/item/borg/charger/attack_self(mob/user)
if(mode == MODE_DRAW)
@@ -170,7 +170,7 @@
else
mode = MODE_DRAW
balloon_alert(user, "You toggle [src] to [mode] mode")
- update_icon()
+ update_appearance()
/obj/item/borg/charger/afterattack(obj/item/target, mob/living/silicon/robot/user, proximity_flag)
. = ..()
@@ -684,11 +684,12 @@
to_chat(user, "[src]'s safety cutoff prevents you from activating it due to living beings being ontop of you!")
else
deactivate_field()
- update_icon()
+ update_appearance()
to_chat(user, "You [active? "activate":"deactivate"] [src].")
-/obj/item/borg/projectile_dampen/update_icon()
+/obj/item/borg/projectile_dampen/update_icon_state()
icon_state = "[initial(icon_state)][active]"
+ return ..()
/obj/item/borg/projectile_dampen/proc/activate_field()
if(istype(dampening_field))
@@ -747,7 +748,7 @@
continue
usage += projectile_tick_speed_ecost * delta_time
usage += (tracked[I] * projectile_damage_tick_ecost_coefficient * delta_time)
- energy = CLAMP(energy - usage, 0, maxenergy)
+ energy = clamp(energy - usage, 0, maxenergy)
if(energy <= 0)
deactivate_field()
visible_message("[src] blinks \"ENERGY DEPLETED\".")
@@ -757,7 +758,7 @@
if(iscyborg(host.loc))
host = host.loc
else
- energy = CLAMP(energy + energy_recharge * delta_time, 0, maxenergy)
+ energy = clamp(energy + energy_recharge * delta_time, 0, maxenergy)
return
if(host.cell && (host.cell.charge >= (host.cell.maxcharge * cyborg_cell_critical_percentage)) && (energy < maxenergy))
host.cell.use(energy_recharge * delta_time * energy_recharge_cyborg_drain_coefficient)
@@ -955,23 +956,22 @@
. += "Nothing."
. += "Alt-click will drop the currently stored [stored]."
-/obj/item/borg/apparatus/beaker/update_icon()
- cut_overlays()
+/obj/item/borg/apparatus/beaker/update_overlays()
+ . = ..()
+ var/mutable_appearance/arm = mutable_appearance(icon = icon, icon_state = "borg_beaker_apparatus_arm")
if(stored)
COMPILE_OVERLAYS(stored)
stored.pixel_x = 0
stored.pixel_y = 0
- var/image/img = image("icon"=stored, "layer"=FLOAT_LAYER)
- var/image/arm = image("icon"="borg_beaker_apparatus_arm", "layer"=FLOAT_LAYER)
+ var/mutable_appearance/stored_copy = new /mutable_appearance(stored)
if(istype(stored, /obj/item/reagent_containers/glass/beaker))
arm.pixel_y = arm.pixel_y - 3
- img.plane = FLOAT_PLANE
- add_overlay(img)
- add_overlay(arm)
+ stored_copy.layer = FLOAT_LAYER
+ stored_copy.plane = FLOAT_PLANE
+ . += stored_copy
else
- var/image/arm = image("icon"="borg_beaker_apparatus_arm", "layer"=FLOAT_LAYER)
arm.pixel_y = arm.pixel_y - 5
- add_overlay(arm)
+ . += arm
/obj/item/borg/apparatus/beaker/attack_self(mob/living/silicon/robot/user)
if(stored && !user.client?.keys_held["Alt"] && user.a_intent != "help")
@@ -1000,24 +1000,20 @@
. = ..()
update_icon()
-/obj/item/borg/apparatus/circuit/update_icon()
- cut_overlays()
+/obj/item/borg/apparatus/circuit/update_overlays()
+ . = ..()
+ var/mutable_appearance/arm = mutable_appearance(icon, "borg_hardware_apparatus_arm1")
if(stored)
COMPILE_OVERLAYS(stored)
stored.pixel_x = -3
stored.pixel_y = 0
- var/image/arm
- if(istype(stored, /obj/item/circuitboard))
- arm = image("icon"="borg_hardware_apparatus_arm1", "layer"=FLOAT_LAYER)
- else
- arm = image("icon"="borg_hardware_apparatus_arm2", "layer"=FLOAT_LAYER)
- var/image/img = image("icon"=stored, "layer"=FLOAT_LAYER)
- img.plane = FLOAT_PLANE
- add_overlay(arm)
- add_overlay(img)
- else
- var/image/arm = image("icon"="borg_hardware_apparatus_arm1", "layer"=FLOAT_LAYER)
- add_overlay(arm)
+ if(!istype(stored, /obj/item/circuitboard))
+ arm.icon_state = "borg_hardware_apparatus_arm2"
+ var/mutable_appearance/stored_copy = new /mutable_appearance(stored)
+ stored_copy.layer = FLOAT_LAYER
+ stored_copy.plane = FLOAT_PLANE
+ . += stored_copy
+ . += arm
/obj/item/borg/apparatus/circuit/examine()
. = ..()
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index ea09a028e6856..d593e23866fdd 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -40,20 +40,20 @@
chest.cell = new /obj/item/stock_parts/cell/high/plus(chest)
update_icon()
-/obj/item/robot_suit/update_icon()
- cut_overlays()
+/obj/item/robot_suit/update_overlays()
+ . = ..()
if(l_arm)
- add_overlay("[l_arm.icon_state]+o")
+ . += "[l_arm.icon_state]+o"
if(r_arm)
- add_overlay("[r_arm.icon_state]+o")
+ . += "[r_arm.icon_state]+o"
if(chest)
- add_overlay("[chest.icon_state]+o")
+ . += "[chest.icon_state]+o"
if(l_leg)
- add_overlay("[l_leg.icon_state]+o")
+ . += "[l_leg.icon_state]+o"
if(r_leg)
- add_overlay("[r_leg.icon_state]+o")
+ . += "[r_leg.icon_state]+o"
if(head)
- add_overlay("[head.icon_state]+o")
+ . += "[head.icon_state]+o"
/obj/item/robot_suit/proc/check_completion()
if(src.l_arm && src.r_arm)
@@ -327,8 +327,7 @@
O.robot_suit = src
if(!locomotion)
- O.lockcharge = TRUE
- O.update_mobility()
+ O.set_lockcharge(TRUE)
to_chat(O, "Error: Servo motors unresponsive.")
else
@@ -369,8 +368,7 @@
forceMove(O)
O.robot_suit = src
if(!locomotion)
- O.lockcharge = TRUE
- O.update_mobility()
+ O.set_lockcharge(TRUE)
else if(istype(W, /obj/item/pen))
to_chat(user, "You need to use a multitool to name [src]!")
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 10f26f65e92f3..9094c2668aa7e 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -384,22 +384,20 @@
playsound(cyborg.loc, 'sound/effects/turbolift/turbolift-close.ogg', 90)
to_chat(cyborg, "You deactivate the self-repair module.")
STOP_PROCESSING(SSobj, src)
- update_icon()
+ update_appearance()
-/obj/item/borg/upgrade/selfrepair/update_icon()
+/obj/item/borg/upgrade/selfrepair/update_icon_state()
if(cyborg)
icon_state = "selfrepair_[on ? "on" : "off"]"
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
else
icon_state = "cyborg_upgrade5"
+ return ..()
/obj/item/borg/upgrade/selfrepair/proc/deactivate_sr()
playsound(cyborg.loc, 'sound/effects/turbolift/turbolift-close.ogg', 90)
STOP_PROCESSING(SSobj, src)
on = FALSE
- update_icon()
+ update_appearance()
/obj/item/borg/upgrade/selfrepair/process()
if(world.time < next_repair)
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index 4bb85d92ddfba..f70000d5dbb90 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -193,6 +193,10 @@
. = ..()
embedded_flash = new(src)
+/obj/item/shield/riot/flash/ComponentInitialize()
+ . = .. ()
+ AddElement(/datum/element/update_icon_updates_onmob)
+
/obj/item/shield/riot/flash/attack(mob/living/M, mob/user)
. = embedded_flash.attack(M, user)
update_icon()
@@ -232,13 +236,14 @@
embedded_flash.emp_act(severity)
update_icon()
-/obj/item/shield/riot/flash/update_icon()
+/obj/item/shield/riot/flash/update_icon_state()
if(!embedded_flash || embedded_flash.burnt_out)
icon_state = "riot"
item_state = "riot"
else
icon_state = "flashshield"
item_state = "flashshield"
+ return ..()
/obj/item/shield/riot/flash/examine(mob/user)
. = ..()
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 988b1341f3313..71d41d697e3cd 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -95,7 +95,7 @@
user.visible_message("[user] starts to apply [src] on [user.p_them()]self...", "You begin applying [src] on yourself...")
if(!do_after(user, self_delay, M))
return
- //After the do_mob to ensure metabolites have had time to process at least one tick.
+ //After the do_mob to ensure metabolites have had time to process at least one tick.
if(reagent && (C.reagents.get_reagent_amount(/datum/reagent/metabolite/medicine/styptic_powder) || C.reagents.get_reagent_amount(/datum/reagent/metabolite/medicine/silver_sulfadiazine)))
to_chat(user, "That stuff really hurt! You'll need to wait for the pain to go away before you can apply [src] to your wounds again, maybe someone else can help put it on for you.")
return
@@ -125,9 +125,9 @@
/obj/item/stack/medical/bruise_pack/one
amount = 1
-/obj/item/stack/medical/bruise_pack/suicide_act(mob/user)
+/obj/item/stack/medical/bruise_pack/suicide_act(mob/living/user)
user.visible_message("[user] is bludgeoning [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/stack/medical/ointment
name = "ointment"
diff --git a/code/game/objects/items/stacks/rods/rods.dm b/code/game/objects/items/stacks/rods/rods.dm
index c4740895e710c..3376a344309fe 100644
--- a/code/game/objects/items/stacks/rods/rods.dm
+++ b/code/game/objects/items/stacks/rods/rods.dm
@@ -37,9 +37,10 @@
if(proximity_flag)
target.attackby(src, user, click_parameters)
-/obj/item/stack/rods/update_icon()
+/obj/item/stack/rods/update_icon_state()
+ . = ..()
var/amount = get_amount()
- if((amount <= 5) && (amount > 0))
+ if(amount <= 5)
icon_state = "rods-[amount]"
else
icon_state = "rods"
diff --git a/code/game/objects/items/stacks/rods/rods_recipes.dm b/code/game/objects/items/stacks/rods/rods_recipes.dm
index bf94b9308c076..39e5a34cc6ce5 100644
--- a/code/game/objects/items/stacks/rods/rods_recipes.dm
+++ b/code/game/objects/items/stacks/rods/rods_recipes.dm
@@ -12,7 +12,8 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
is_cyborg = 1
cost = 250
-/obj/item/stack/rods/cyborg/update_icon()
- return
+/obj/item/stack/rods/cyborg/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
STACKSIZE_MACRO(/obj/item/stack/rods)
diff --git a/code/game/objects/items/stacks/sheets/mineral/glass.dm b/code/game/objects/items/stacks/sheets/mineral/glass.dm
index accee2d559f84..7acb5fb24fc6d 100644
--- a/code/game/objects/items/stacks/sheets/mineral/glass.dm
+++ b/code/game/objects/items/stacks/sheets/mineral/glass.dm
@@ -206,9 +206,9 @@
embedding = list("embed_chance" = 65)
-/obj/item/shard/suicide_act(mob/user)
+/obj/item/shard/suicide_act(mob/living/user)
user.visible_message("[user] is slitting [user.p_their()] [pick("wrists", "throat")] with the shard of glass! It looks like [user.p_theyre()] trying to commit suicide.")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/shard/Initialize(mapload)
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index e51845d150755..177985ea11379 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -85,21 +85,22 @@
/obj/item/stack/proc/update_weight()
if(amount <= (max_amount * (1/3)))
- w_class = CLAMP(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class)
+ w_class = clamp(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class)
else if(amount <= (max_amount * (2/3)))
- w_class = CLAMP(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class)
+ w_class = clamp(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class)
else
w_class = full_w_class
-/obj/item/stack/update_icon()
+/obj/item/stack/update_icon_state()
if(novariants)
- return ..()
+ return
if(amount <= (max_amount * (1/3)))
icon_state = initial(icon_state)
- else if(amount <= (max_amount * (2/3)))
+ return ..()
+ if(amount <= (max_amount * (2/3)))
icon_state = "[initial(icon_state)]_2"
- else
- icon_state = "[initial(icon_state)]_3"
+ return ..()
+ icon_state = "[initial(icon_state)]_3"
return ..()
/obj/item/stack/examine(mob/user)
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 9ade0c512a85d..2395c65aef8ad 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -66,6 +66,7 @@
user.Stun(100, ignore_canstun = TRUE)
sleep(20)
playsound(src, "rustle", 50, 1, -5)
+ user.suicide_log()
qdel(user)
/obj/item/storage/backpack/holding/singularity_act(current_size)
@@ -110,9 +111,9 @@
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 60
-/obj/item/storage/backpack/santabag/suicide_act(mob/user)
+/obj/item/storage/backpack/santabag/suicide_act(mob/living/user)
user.visible_message("[user] places [src] over [user.p_their()] head and pulls it tight! It looks like [user.p_they()] [user.p_are()]n't in the Christmas spirit...")
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/storage/backpack/santabag/proc/regenerate_presents()
addtimer(CALLBACK(src, PROC_REF(regenerate_presents)), 30 SECONDS)
@@ -581,7 +582,7 @@
desc = "A large duffel bag containing a Bulldog, some drums, and a pair of thermal imaging glasses."
/obj/item/storage/backpack/duffelbag/syndie/bulldogbundle/PopulateContents()
- new /obj/item/gun/ballistic/shotgun/bulldog(src)
+ new /obj/item/gun/ballistic/shotgun/automatic/bulldog(src)
new /obj/item/ammo_box/magazine/m12g(src)
new /obj/item/ammo_box/magazine/m12g(src)
new /obj/item/clothing/glasses/thermal/syndi(src)
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index 129bb471d4a1c..cddcee9523247 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -52,19 +52,22 @@
STR.cant_hold = typecacheof(list(/obj/item/disk/nuclear))
STR.can_be_opened = FALSE //Have to dump a trash bag out to look at its contents
-/obj/item/storage/bag/trash/suicide_act(mob/user)
+/obj/item/storage/bag/trash/suicide_act(mob/living/user)
user.visible_message("[user] puts [src] over [user.p_their()] head and starts chomping at the insides! Disgusting!")
playsound(loc, 'sound/items/eatfood.ogg', 50, 1, -1)
- return (TOXLOSS)
-
-/obj/item/storage/bag/trash/update_icon()
- if(contents.len == 0)
- icon_state = "[initial(icon_state)]"
- else if(contents.len < 12)
- icon_state = "[initial(icon_state)]1"
- else if(contents.len < 21)
- icon_state = "[initial(icon_state)]2"
- else icon_state = "[initial(icon_state)]3"
+ return TOXLOSS
+
+/obj/item/storage/bag/trash/update_icon_state()
+ switch(contents.len)
+ if(20 to INFINITY)
+ icon_state = "[initial(icon_state)]3"
+ if(11 to 20)
+ icon_state = "[initial(icon_state)]2"
+ if(1 to 11)
+ icon_state = "[initial(icon_state)]1"
+ else
+ icon_state = "[initial(icon_state)]"
+ return ..()
/obj/item/storage/bag/trash/cyborg
insertable = FALSE
@@ -364,10 +367,13 @@
source.lifetime = count * new_delay
source.delay = new_delay
-/obj/item/storage/bag/tray/update_icon()
- cut_overlays()
+/obj/item/storage/bag/tray/update_overlays()
+ . = ..()
for(var/obj/item/I in contents)
- add_overlay(new /mutable_appearance(I))
+ var/mutable_appearance/I_copy = new(I)
+ I_copy.plane = FLOAT_PLANE
+ I_copy.layer = FLOAT_LAYER
+ . += I_copy
/obj/item/storage/bag/tray/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
. = ..()
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 91ee8cce36fcb..e409ed4788fe3 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -16,13 +16,11 @@
user.visible_message("[user] begins belting [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
return BRUTELOSS
-/obj/item/storage/belt/update_icon()
- cut_overlays()
+/obj/item/storage/belt/update_overlays()
+ . = ..()
if(content_overlays)
for(var/obj/item/I in contents)
- var/mutable_appearance/M = I.get_belt_overlay()
- add_overlay(M)
- ..()
+ . += I.get_belt_overlay()
/obj/item/storage/belt/Initialize(mapload)
. = ..()
@@ -541,9 +539,9 @@
/obj/item/reagent_containers/food/snacks/syndicake,
/obj/item/reagent_containers/food/snacks/spacetwinkie,
/obj/item/reagent_containers/food/snacks/cheesiehonkers,
- /obj/item/reagent_containers/food/snacks/nachos,
- /obj/item/reagent_containers/food/snacks/cheesynachos,
- /obj/item/reagent_containers/food/snacks/cubannachos,
+ /obj/item/food/nachos,
+ /obj/item/food/cheesynachos,
+ /obj/item/food/cubannachos,
/obj/item/reagent_containers/food/snacks/nugget,
/obj/item/food/spaghetti/pastatomato,
/obj/item/reagent_containers/food/snacks/rofflewaffles,
@@ -836,6 +834,7 @@
/obj/item/storage/belt/sabre/ComponentInitialize()
. = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 1
STR.rustle_sound = FALSE
@@ -857,11 +856,11 @@
var/obj/item/I = contents[1]
user.visible_message("[user] takes [I] out of [src].", "You take [I] out of [src].")
user.put_in_hands(I)
- update_icon()
+ update_appearance()
else
to_chat(user, "[src] is empty.")
-/obj/item/storage/belt/sabre/update_icon()
+/obj/item/storage/belt/sabre/update_icon_state()
icon_state = initial(icon_state)
item_state = initial(item_state)
worn_icon_state = initial(worn_icon_state)
@@ -869,14 +868,11 @@
icon_state += "-sabre"
item_state += "-sabre"
worn_icon_state += "-sabre"
- if(loc && isliving(loc))
- var/mob/living/L = loc
- L.regenerate_icons()
- ..()
+ return ..()
/obj/item/storage/belt/sabre/PopulateContents()
new /obj/item/melee/sabre(src)
- update_icon()
+ update_appearance()
/obj/item/storage/belt/sabre/mime
name = "Baguette"
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index ca57ac8d7251d..838735bb692ab 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -40,9 +40,9 @@
. = ..()
AddComponent(/datum/component/anti_magic, FALSE, TRUE, _allowed_slots = ITEM_SLOT_HANDS)
-/obj/item/storage/book/bible/suicide_act(mob/user)
+/obj/item/storage/book/bible/suicide_act(mob/living/user)
user.visible_message("[user] is offering [user.p_them()]self to [deity_name]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/storage/book/bible/attack_self(mob/living/carbon/human/H)
if(!istype(H))
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index ce233af042a19..3221b2eb8b2ed 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -50,11 +50,10 @@
user.visible_message("[user] beating [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
return BRUTELOSS
-/obj/item/storage/box/update_icon()
+/obj/item/storage/box/update_overlays()
. = ..()
if(illustration)
- cut_overlays()
- add_overlay(illustration)
+ . += illustration
/obj/item/storage/box/attack_self(mob/user)
..()
@@ -834,9 +833,9 @@
illustration = "heart"
foldable = null
-/obj/item/storage/box/hug/suicide_act(mob/user)
+/obj/item/storage/box/hug/suicide_act(mob/living/user)
user.visible_message("[user] clamps the box of hugs on [user.p_their()] jugular! Guess it wasn't such a hugbox after all..")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/storage/box/hug/attack_self(mob/user)
..()
@@ -960,10 +959,12 @@
foldable = null
var/design = NODESIGN
-/obj/item/storage/box/papersack/update_icon()
+/obj/item/storage/box/papersack/update_icon_state()
if(contents.len == 0)
icon_state = "[item_state]"
- else icon_state = "[item_state]_closed"
+ else
+ icon_state = "[item_state]_closed"
+ return ..()
/obj/item/storage/box/papersack/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/pen))
@@ -1052,7 +1053,7 @@
theme_name = "fiesta"
/obj/item/storage/box/ingredients/fiesta/PopulateContents()
- new /obj/item/reagent_containers/food/snacks/tortilla(src)
+ new /obj/item/food/tortilla(src)
for(var/i in 1 to 2)
new /obj/item/reagent_containers/food/snacks/grown/corn(src)
new /obj/item/reagent_containers/food/snacks/grown/soybeans(src)
diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm
index 6086e37c675f4..02596917bc03d 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -29,11 +29,12 @@
for(var/i = 1 to STR.max_items)
new spawn_type(src)
-/obj/item/storage/fancy/update_icon()
+/obj/item/storage/fancy/update_icon_state()
if(fancy_open)
icon_state = "[icon_type]box[contents.len]"
else
icon_state = "[icon_type]box"
+ return ..()
/obj/item/storage/fancy/examine(mob/user)
. = ..()
@@ -68,7 +69,7 @@
icon_type = "donut"
name = "donut box"
desc = "Mmm. Donuts."
- spawn_type = /obj/item/reagent_containers/food/snacks/donut
+ spawn_type = /obj/item/reagent_containers/food/snacks/donut/premade
fancy_open = TRUE
/obj/item/storage/fancy/donut_box/ComponentInitialize()
@@ -109,8 +110,8 @@
icon_state = "candlebox5"
icon_type = "candle"
item_state = "candlebox5"
+ w_class = WEIGHT_CLASS_NORMAL
throwforce = 2
- slot_flags = ITEM_SLOT_BELT
spawn_type = /obj/item/candle
fancy_open = TRUE
@@ -118,6 +119,7 @@
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
+ STR.can_hold = typecacheof(list(/obj/item/candle, /obj/item/lighter, /obj/item/storage/box/matches))
/obj/item/storage/fancy/candle_box/attack_self(mob_user)
return
@@ -174,30 +176,34 @@
else
to_chat(user, "There is no lighter in the pack.")
-/obj/item/storage/fancy/cigarettes/update_icon()
+/obj/item/storage/fancy/cigarettes/update_icon_state()
+ . = ..()
if(fancy_open || !contents.len)
- cut_overlays()
if(!contents.len)
icon_state = "[initial(icon_state)]_empty"
else
icon_state = initial(icon_state)
- add_overlay("[icon_state]_open")
- var/cig_position = 1
- for(var/C in contents)
- var/mutable_appearance/inserted_overlay = mutable_appearance(icon)
-
- if(istype(C, /obj/item/lighter/greyscale))
- inserted_overlay.icon_state = "lighter_in"
- else if(istype(C, /obj/item/lighter))
- inserted_overlay.icon_state = "zippo_in"
- else
- inserted_overlay.icon_state = "cigarette"
-
- inserted_overlay.icon_state = "[inserted_overlay.icon_state]_[cig_position]"
- add_overlay(inserted_overlay)
- cig_position++
- else
- cut_overlays()
+
+/obj/item/storage/fancy/cigarettes/update_overlays()
+ . = ..()
+ if(fancy_open && contents.len)
+ . += "[icon_state]_open"
+ var/cig_position = 1
+ for(var/C in contents)
+ var/mutable_appearance/inserted_overlay = mutable_appearance(icon)
+
+ if(istype(C, /obj/item/lighter/greyscale))
+ inserted_overlay.icon_state = "lighter_in"
+ else if(istype(C, /obj/item/lighter))
+ inserted_overlay.icon_state = "zippo_in"
+ //else if(candy)
+ // inserted_overlay.icon_state = "candy"
+ else
+ inserted_overlay.icon_state = "cigarette"
+
+ inserted_overlay.icon_state = "[inserted_overlay.icon_state]_[cig_position]"
+ . += inserted_overlay
+ cig_position++
/obj/item/storage/fancy/cigarettes/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
if(!ismob(M))
@@ -293,10 +299,10 @@
STR.max_items = 10
STR.can_hold = typecacheof(list(/obj/item/rollingpaper))
-/obj/item/storage/fancy/rollingpapers/update_icon()
- cut_overlays()
+/obj/item/storage/fancy/rollingpapers/update_overlays()
+ . = ..()
if(!contents.len)
- add_overlay("[icon_state]_empty")
+ . += "[icon_state]_empty"
/////////////
//CIGAR BOX//
@@ -318,19 +324,20 @@
STR.can_hold = typecacheof(list(/obj/item/clothing/mask/cigarette/cigar))
/obj/item/storage/fancy/cigarettes/cigars/update_icon()
- cut_overlays()
if(fancy_open)
icon_state = "[initial(icon_state)]_open"
+ else
+ icon_state = "[initial(icon_state)]"
+/obj/item/storage/fancy/cigarettes/cigars/update_overlays()
+ . = ..()
+ if(fancy_open)
var/cigar_position = 1 //generate sprites for cigars in the box
for(var/obj/item/clothing/mask/cigarette/cigar/smokes in contents)
var/mutable_appearance/cigar_overlay = mutable_appearance(icon, "[smokes.icon_off]_[cigar_position]")
- add_overlay(cigar_overlay)
+ . += cigar_overlay
cigar_position++
- else
- icon_state = "[initial(icon_state)]"
-
/obj/item/storage/fancy/cigarettes/cigars/cohiba
name = "\improper Cohiba Robusto cigar case"
desc = "A case of imported Cohiba cigars, renowned for their strong flavor."
diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm
index 615419e31acfd..325d45fb3394d 100644
--- a/code/game/objects/items/storage/firstaid.dm
+++ b/code/game/objects/items/storage/firstaid.dm
@@ -453,9 +453,9 @@
STR.click_gather = TRUE
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice))
-/obj/item/storage/pill_bottle/suicide_act(mob/user)
+/obj/item/storage/pill_bottle/suicide_act(mob/living/user)
user.visible_message("[user] is trying to get the cap off [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (TOXLOSS)
+ return TOXLOSS
/obj/item/storage/pill_bottle/charcoal
name = "bottle of charcoal pills"
diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm
index 6bca42420136f..5df956d461d46 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -117,13 +117,11 @@
for(var/i in 1 to 3)
new /obj/item/clothing/accessory/medal/conduct(src)
-/obj/item/storage/lockbox/medal/update_icon()
- cut_overlays()
+/obj/item/storage/lockbox/medal/update_icon_state()
var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
if(locked)
icon_state = "[base_icon_state]+l"
item_state = "[base_icon_state]+l"
- open = FALSE
else
icon_state = "[base_icon_state]"
item_state = "[base_icon_state]"
@@ -132,16 +130,24 @@
if(broken)
icon_state += "+b"
item_state = "[base_icon_state]+b"
- if(contents && open)
- for (var/i in 1 to contents.len)
- var/obj/item/clothing/accessory/medal/M = contents[i]
- var/mutable_appearance/medalicon = mutable_appearance(initial(icon), M.medaltype)
- if(i > 1 && i <= 5)
- medalicon.pixel_x += ((i-1)*4)
- else if(i > 5)
- medalicon.pixel_y -= 7
- medalicon.pixel_x += ((i-6)*4)
- add_overlay(medalicon)
+ return ..()
+
+/obj/item/storage/lockbox/medal/update_overlays()
+ . = ..()
+ if(!contents || !open)
+ return
+ var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
+ if(locked)
+ return
+ for (var/i in 1 to contents.len)
+ var/obj/item/clothing/accessory/medal/M = contents[i]
+ var/mutable_appearance/medalicon = mutable_appearance(initial(icon), M.medaltype)
+ if(i > 1 && i <= 5)
+ medalicon.pixel_x += ((i-1)*4)
+ else if(i > 5)
+ medalicon.pixel_y -= 7
+ medalicon.pixel_x += ((i-6)*4)
+ . += medalicon
/obj/item/storage/lockbox/medal/sec
name = "security medal box"
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
index 2d5b4f8ec0eec..f57bfda3cb2fb 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -30,16 +30,15 @@
latches = "triple_latch"
update_icon()
-/obj/item/storage/toolbox/update_icon()
- ..()
- cut_overlays()
+/obj/item/storage/toolbox/update_overlays()
+ . = ..()
if(has_latches)
- add_overlay(latches)
+ . += latches
-/obj/item/storage/toolbox/suicide_act(mob/user)
+/obj/item/storage/toolbox/suicide_act(mob/living/user)
user.visible_message("[user] robusts [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/storage/toolbox/emergency
name = "emergency toolbox"
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 33d6321ea8ece..6e10be5442d00 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -118,7 +118,7 @@
if("metaops")
new /obj/item/clothing/suit/space/hardsuit/syndi(src) // 8 tc
- new /obj/item/gun/ballistic/shotgun/bulldog/unrestricted(src) // 8 tc
+ new /obj/item/gun/ballistic/shotgun/automatic/bulldog/unrestricted(src) // 8 tc
new /obj/item/implanter/explosive(src) // 2 tc
new /obj/item/ammo_box/magazine/m12g(src) // 2 tc
new /obj/item/ammo_box/magazine/m12g(src) // 2 tc
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index 477b5df0f46ee..61dfadfc94014 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -43,6 +43,7 @@
/obj/item/storage/wallet/proc/refreshID()
LAZYCLEARLIST(combined_access)
+
if(!(front_id in src))
front_id = null
for(var/obj/item/card/id/I in contents)
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index 62af59007e1cc..475cb3f6a910a 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -23,9 +23,9 @@
/obj/item/melee/baton/get_cell()
return cell
-/obj/item/melee/baton/suicide_act(mob/user)
+/obj/item/melee/baton/suicide_act(mob/living/user)
user.visible_message("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!")
- return (FIRELOSS)
+ return FIRELOSS
/obj/item/melee/baton/Initialize(mapload)
. = ..()
@@ -71,7 +71,7 @@
playsound(src, "sparks", 75, TRUE, -1)
-/obj/item/melee/baton/update_icon()
+/obj/item/melee/baton/update_icon_state()
if(obj_flags & OBJ_EMPED)
icon_state = "[initial(icon_state)]"
else if(turned_on)
@@ -80,6 +80,7 @@
icon_state = "[initial(icon_state)]_nocell"
else
icon_state = "[initial(icon_state)]"
+ return ..()
/obj/item/melee/baton/examine(mob/user)
. = ..()
diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm
index 8e946e4fb370a..793c43a44f1c8 100644
--- a/code/game/objects/items/tanks/jetpack.dm
+++ b/code/game/objects/items/tanks/jetpack.dm
@@ -52,9 +52,7 @@
else
turn_off(user)
to_chat(user, "You turn the jetpack off.")
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/tank/jetpack/equipped(mob/user, slot)
..()
@@ -133,14 +131,13 @@
return TRUE
-/obj/item/tank/jetpack/suicide_act(mob/user)
- if (istype(user, /mob/living/carbon/human/))
- var/mob/living/carbon/human/H = user
- H.say(";WHAT THE FUCK IS CARBON DIOXIDE?", forced="jetpack suicide")
- H.visible_message("[user] is suffocating [user.p_them()]self with [src]! It looks like [user.p_they()] didn't read what that jetpack says!")
- return (OXYLOSS)
- else
- ..()
+/obj/item/tank/jetpack/suicide_act(mob/living/user)
+ if (!ishuman(user))
+ return
+ var/mob/living/carbon/human/H = user
+ H.say(";WHAT THE FUCK IS CARBON DIOXIDE?", forced="jetpack suicide")
+ H.visible_message("[user] is suffocating [user.p_them()]self with [src]! It looks like [user.p_they()] didn't read what that jetpack says!")
+ return OXYLOSS
/obj/item/tank/jetpack/improvised
name = "improvised jetpack"
diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm
index 2ebdc264ddadb..11e41735ed6a6 100644
--- a/code/game/objects/items/tanks/tanks.dm
+++ b/code/game/objects/items/tanks/tanks.dm
@@ -128,25 +128,25 @@
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
qdel(src)
-/obj/item/tank/suicide_act(mob/user)
- var/mob/living/carbon/human/H = user
+/obj/item/tank/suicide_act(mob/living/user)
+ var/mob/living/carbon/human/human_user = user
user.visible_message("[user] is putting [src]'s valve to [user.p_their()] lips! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/effects/spray.ogg', 10, 1, -3)
- if (!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000)
- for(var/obj/item/W in H)
- H.dropItemToGround(W)
+ if (!QDELETED(human_user) && air_contents && air_contents.return_pressure() >= 1000)
+ for(var/obj/item/W in human_user)
+ human_user.dropItemToGround(W)
if(prob(50))
step(W, pick(GLOB.alldirs))
- ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC)
- H.bleed_rate = 5
- H.gib_animation()
+ ADD_TRAIT(human_user, TRAIT_DISFIGURED, TRAIT_GENERIC)
+ human_user.bleed_rate = 5
+ human_user.gib_animation()
sleep(3)
- H.adjustBruteLoss(1000) //to make the body super-bloody
- H.spawn_gibs()
- H.spill_organs()
- H.spread_bodyparts()
+ human_user.adjustBruteLoss(1000) //to make the body super-bloody
+ human_user.spawn_gibs()
+ human_user.spill_organs()
+ human_user.spread_bodyparts()
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/tank/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
@@ -204,7 +204,7 @@
pressure = text2num(pressure)
. = TRUE
if(.)
- distribute_pressure = CLAMP(round(pressure), TANK_MIN_RELEASE_PRESSURE, TANK_MAX_RELEASE_PRESSURE)
+ distribute_pressure = clamp(round(pressure), TANK_MIN_RELEASE_PRESSURE, TANK_MAX_RELEASE_PRESSURE)
/obj/item/tank/remove_air(amount)
return air_contents.remove(amount)
diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm
index d1dee414c8895..a3607fa5188e8 100644
--- a/code/game/objects/items/teleportation.dm
+++ b/code/game/objects/items/teleportation.dm
@@ -251,7 +251,7 @@
return DESTINATION_PORTAL
return FALSE
-/obj/item/hand_tele/suicide_act(mob/user)
+/obj/item/hand_tele/suicide_act(mob/living/user)
if(iscarbon(user))
user.visible_message("[user] is creating a weak portal and sticking [user.p_their()] head through! It looks like [user.p_theyre()] trying to commit suicide!")
var/mob/living/carbon/itemUser = user
@@ -263,7 +263,7 @@
itemUser.visible_message("The portal snaps closed taking [user]'s head with it!")
else
itemUser.visible_message("[user] looks even further depressed as they realize they do not have a head...and suddenly dies of shame!")
- return (BRUTELOSS)
+ return BRUTELOSS
/*
* Syndicate Teleporter
diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm
index f22f9a5e77ca4..e92289f30efa1 100644
--- a/code/game/objects/items/theft_tools.dm
+++ b/code/game/objects/items/theft_tools.dm
@@ -36,9 +36,9 @@
flick(pulseicon, src)
radiation_pulse(src, 400, 2)
-/obj/item/nuke_core/suicide_act(mob/user)
+/obj/item/nuke_core/suicide_act(mob/living/user)
user.visible_message("[user] is rubbing [src] against [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!")
- return (TOXLOSS)
+ return TOXLOSS
//nuke core box, for carrying the core
/obj/item/nuke_core_container
@@ -156,13 +156,14 @@
..()
if(!iscarbon(user))
return FALSE
- var/mob/ded = user
- user.visible_message("[ded] reaches out and tries to pick up [src]. [ded.p_their()] body starts to glow and bursts into flames before flashing into dust!",\
+ var/mob/victim = user
+ user.visible_message("[victim] reaches out and tries to pick up [src]. [victim.p_their()] body starts to glow and bursts into flames before flashing into dust!",\
"You reach for [src] with your hands. That was dumb.",\
"Everything suddenly goes silent.")
radiation_pulse(user, 500, 2)
playsound(get_turf(user), 'sound/effects/supermatter.ogg', 50, 1)
- ded.dust()
+ victim.investigate_log("has been dusted by [src].", INVESTIGATE_DEATHS)
+ victim.dust()
/obj/item/nuke_core_container/supermatter
name = "supermatter bin"
@@ -227,11 +228,10 @@
QDEL_NULL(sliver)
return ..()
-/obj/item/hemostat/supermatter/update_icon()
- if(sliver)
- icon_state = "supermatter_tongs_loaded"
- else
- icon_state = "supermatter_tongs"
+/obj/item/hemostat/supermatter/update_icon_state()
+ icon_state = "supermatter_tongs[sliver ? "_loaded" : null]"
+ //item_state = "supermatter_tongs[sliver ? "_loaded" : null]"
+ return ..()
/obj/item/hemostat/supermatter/afterattack(atom/O, mob/user, proximity)
. = ..()
@@ -251,6 +251,7 @@
/obj/item/hemostat/supermatter/proc/Consume(atom/movable/AM, mob/user)
if(ismob(AM))
var/mob/victim = AM
+ victim.investigate_log("has been dusted by [src].", INVESTIGATE_DEATHS)
victim.dust()
message_admins("[src] has consumed [key_name_admin(victim)] [ADMIN_JMP(src)].")
investigate_log("has consumed [key_name(victim)].", "supermatter")
@@ -261,6 +262,7 @@
user.visible_message("As [user] touches [AM] with \the [src], both flash into dust and silence fills the room...",\
"You touch [AM] with [src], and everything suddenly goes silent.\n[AM] and [sliver] flash into dust, and soon as you can register this, you do as well.",\
"Everything suddenly goes silent.")
+ user.investigate_log("has been dusted by [src].", INVESTIGATE_DEATHS)
user.dust()
radiation_pulse(src, 500, 2)
playsound(src, 'sound/effects/supermatter.ogg', 50, 1)
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm
index ed19e270bcf82..7b780e9219cea 100644
--- a/code/game/objects/items/tools/crowbar.dm
+++ b/code/game/objects/items/tools/crowbar.dm
@@ -20,10 +20,10 @@
drop_sound = 'sound/items/handling/crowbar_drop.ogg'
pickup_sound = 'sound/items/handling/crowbar_pickup.ogg'
-/obj/item/crowbar/suicide_act(mob/user)
+/obj/item/crowbar/suicide_act(mob/living/user)
user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/crowbar/red
icon_state = "crowbar_red"
diff --git a/code/game/objects/items/tools/powertools.dm b/code/game/objects/items/tools/powertools.dm
index 57447b8904e8c..1e8aa0544a917 100644
--- a/code/game/objects/items/tools/powertools.dm
+++ b/code/game/objects/items/tools/powertools.dm
@@ -62,7 +62,7 @@
attack_verb = list("drilled", "screwed", "jabbed")
throw_range = 3
-/obj/item/powertool/hand_drill/suicide_act(mob/user)
+/obj/item/powertool/hand_drill/suicide_act(mob/living/user)
if(tool_behaviour == TOOL_SCREWDRIVER)
user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!")
else
@@ -133,7 +133,7 @@
ADD_TRAIT(src, TRAIT_DOOR_PRYER, TRAIT_JAWS_OF_LIFE)
-/obj/item/powertool/jaws_of_life/suicide_act(mob/user)
+/obj/item/powertool/jaws_of_life/suicide_act(mob/living/user)
if(tool_behaviour == TOOL_CROWBAR)
user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1)
diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm
index 3d0820099f5c7..3875a5ec30b1b 100644
--- a/code/game/objects/items/tools/screwdriver.dm
+++ b/code/game/objects/items/tools/screwdriver.dm
@@ -40,9 +40,9 @@
"yellow" = "#ffa500"
)
-/obj/item/screwdriver/suicide_act(mob/user)
+/obj/item/screwdriver/suicide_act(mob/living/user)
user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!")
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/screwdriver/Initialize(mapload)
if(random_color)
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 7050a76a5d3de..2b940add3b50c 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -50,22 +50,25 @@
reagents.add_reagent(/datum/reagent/fuel, max_fuel)
update_icon()
-/obj/item/weldingtool/proc/update_torch()
+/obj/item/weldingtool/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+
+/obj/item/weldingtool/update_icon_state()
if(welding)
- add_overlay("[initial(icon_state)]-on")
item_state = "[initial(item_state)]1"
else
item_state = "[initial(item_state)]"
+ return ..()
-
-/obj/item/weldingtool/update_icon()
- cut_overlays()
+/obj/item/weldingtool/update_overlays()
+ . = ..()
if(change_icons)
var/ratio = get_fuel() / max_fuel
ratio = CEILING(ratio*4, 1) * 25
- add_overlay("[initial(icon_state)][ratio]")
- update_torch()
- return
+ . += "[initial(icon_state)][ratio]"
+ if(welding)
+ . += "[initial(icon_state)]-on"
/obj/item/weldingtool/process(delta_time)
@@ -90,9 +93,9 @@
open_flame()
-/obj/item/weldingtool/suicide_act(mob/user)
+/obj/item/weldingtool/suicide_act(mob/living/user)
user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!")
- return (FIRELOSS)
+ return FIRELOSS
/obj/item/weldingtool/attackby(obj/item/I, mob/user, params)
@@ -182,11 +185,6 @@
set_light_on(FALSE)
switched_on(user)
update_icon()
- //mob icon update
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_hands(0)
-
return 0
return 1
diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm
index a21ee3a523953..e075719e454f3 100644
--- a/code/game/objects/items/tools/wirecutters.dm
+++ b/code/game/objects/items/tools/wirecutters.dm
@@ -41,13 +41,13 @@
add_atom_colour(wirecutter_colors[our_color], FIXED_COLOUR_PRIORITY)
update_icon()
-/obj/item/wirecutters/update_icon()
+/obj/item/wirecutters/update_overlays()
+ . = ..()
if(!random_color) //icon override
return
- cut_overlays()
var/mutable_appearance/base_overlay = mutable_appearance(icon, "cutters_cutty_thingy")
base_overlay.appearance_flags = RESET_COLOR
- add_overlay(base_overlay)
+ . += base_overlay
/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user)
if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable))
@@ -62,10 +62,10 @@
else
..()
-/obj/item/wirecutters/suicide_act(mob/user)
+/obj/item/wirecutters/suicide_act(mob/living/user)
user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, usesound, 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/wirecutters/brass
name = "brass wirecutters"
diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm
index cbf292b4591a7..d26adbbd39f1f 100644
--- a/code/game/objects/items/tools/wrench.dm
+++ b/code/game/objects/items/tools/wrench.dm
@@ -19,10 +19,10 @@
toolspeed = 1
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 30, STAMINA = 0)
-/obj/item/wrench/suicide_act(mob/user)
+/obj/item/wrench/suicide_act(mob/living/user)
user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/wrench/brass
name = "brass wrench"
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 41c3dd6466be3..4f6587231abad 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -224,8 +224,9 @@
materials = list(/datum/material/iron=10, /datum/material/glass=10)
var/amount_left = 7
-/obj/item/toy/ammo/gun/update_icon()
- src.icon_state = "357OLD-[src.amount_left]"
+/obj/item/toy/ammo/gun/update_icon_state()
+ icon_state = "357OLD-[amount_left]"
+ return ..()
/obj/item/toy/ammo/gun/examine(mob/user)
. = ..()
@@ -674,6 +675,8 @@
|| A Deck of Cards for playing various games of chance ||
*/
+
+
/obj/item/toy/cards
resistance_flags = FLAMMABLE
max_integrity = 50
@@ -690,7 +693,7 @@
/obj/item/toy/cards/suicide_act(mob/living/carbon/user)
user.visible_message("[user] is slitting [user.p_their()] wrists with \the [src]! It looks like [user.p_they()] [user.p_have()] a crummy hand!")
- playsound(src, 'sound/items/cardshuffle.ogg', 50, 1)
+ playsound(src, 'sound/items/cardshuffle.ogg', 50, TRUE)
return BRUTELOSS
/obj/item/toy/cards/proc/apply_card_vars(obj/item/toy/cards/newobj, obj/item/toy/cards/sourceobj) // Applies variables for supporting multiple types of card deck
@@ -713,29 +716,15 @@
. = ..()
populate_deck()
+///Generates all the cards within the deck.
/obj/item/toy/cards/deck/proc/populate_deck()
icon_state = "deck_[deckstyle]_full"
- for(var/i in 2 to 10)
- cards += "[i] of Hearts"
- cards += "[i] of Spades"
- cards += "[i] of Clubs"
- cards += "[i] of Diamonds"
- cards += "King of Hearts"
- cards += "King of Spades"
- cards += "King of Clubs"
- cards += "King of Diamonds"
- cards += "Queen of Hearts"
- cards += "Queen of Spades"
- cards += "Queen of Clubs"
- cards += "Queen of Diamonds"
- cards += "Jack of Hearts"
- cards += "Jack of Spades"
- cards += "Jack of Clubs"
- cards += "Jack of Diamonds"
- cards += "Ace of Hearts"
- cards += "Ace of Spades"
- cards += "Ace of Clubs"
- cards += "Ace of Diamonds"
+ for(var/suit in list("Hearts", "Spades", "Clubs", "Diamonds"))
+ cards += "Ace of [suit]"
+ for(var/i in 2 to 10)
+ cards += "[i] of [suit]"
+ for(var/person in list("Jack", "Queen", "King"))
+ cards += "[person] of [suit]"
//ATTACK HAND IGNORING PARENT RETURN VALUE
//ATTACK HAND NOT CALLING PARENT
@@ -748,7 +737,7 @@
if(!(L.mobility_flags & MOBILITY_PICKUP))
return
var/choice = null
- if(!LAZYLEN(cards))
+ if(cards.len == 0)
to_chat(user, "There are no more cards to draw!")
return
var/obj/item/toy/cards/singlecard/H = new/obj/item/toy/cards/singlecard(user.loc)
@@ -759,25 +748,29 @@
H.parentdeck = src
var/O = src
H.apply_card_vars(H,O)
- cards.Cut(1,2) //Removes the top card from the list
+ popleft(cards)
+ H.pickup(user)
user.put_in_hands(H)
user.visible_message("[user] draws a card from the deck.", "You draw a card from the deck.")
update_icon()
-
-/obj/item/toy/cards/deck/update_icon()
- if(LAZYLEN(cards) > original_size/2)
- icon_state = "deck_[deckstyle]_full"
- else if(LAZYLEN(cards) > original_size/4)
- icon_state = "deck_[deckstyle]_half"
- else if(LAZYLEN(cards))
- icon_state = "deck_[deckstyle]_low"
- else if(!LAZYLEN(cards))
- icon_state = "deck_[deckstyle]_empty"
+ return H
+
+/obj/item/toy/cards/deck/update_icon_state()
+ switch(cards.len)
+ if(27 to INFINITY)
+ icon_state = "deck_[deckstyle]_full"
+ if(11 to 27)
+ icon_state = "deck_[deckstyle]_half"
+ if(1 to 11)
+ icon_state = "deck_[deckstyle]_low"
+ else
+ icon_state = "deck_[deckstyle]_empty"
+ return ..()
/obj/item/toy/cards/deck/attack_self(mob/user)
if(cooldown < world.time - 50)
cards = shuffle(cards)
- playsound(src, 'sound/items/cardshuffle.ogg', 50, 1)
+ playsound(src, 'sound/items/cardshuffle.ogg', 50, TRUE)
user.visible_message("[user] shuffles the deck.", "You shuffle the deck.")
cooldown = world.time
@@ -810,22 +803,22 @@
return ..()
/obj/item/toy/cards/deck/MouseDrop(atom/over_object)
- . = ..()
- var/mob/living/M = usr
- if(!istype(M) || !(M.mobility_flags & MOBILITY_PICKUP))
- return
- if(Adjacent(usr))
- if(over_object == M && loc != M)
- M.put_in_hands(src)
- to_chat(usr, "You pick up the deck.")
+ . = ..()
+ var/mob/living/M = usr
+ if(!istype(M) || !(M.mobility_flags & MOBILITY_PICKUP))
+ return
+ if(Adjacent(usr))
+ if(over_object == M && loc != M)
+ M.put_in_hands(src)
+ to_chat(usr, "You pick up the deck.")
- else if(istype(over_object, /atom/movable/screen/inventory/hand))
- var/atom/movable/screen/inventory/hand/H = over_object
- if(M.putItemFromInventoryInHandIfPossible(src, H.held_index))
- to_chat(usr, "You pick up the deck.")
+ else if(istype(over_object, /atom/movable/screen/inventory/hand))
+ var/atom/movable/screen/inventory/hand/H = over_object
+ if(M.putItemFromInventoryInHandIfPossible(src, H.held_index))
+ to_chat(usr, "You pick up the deck.")
- else
- to_chat(usr, "You can't reach it from here!")
+ else
+ to_chat(usr, "You can't reach it from here!")
@@ -838,56 +831,43 @@
var/list/currenthand = list()
var/choice = null
-
/obj/item/toy/cards/cardhand/attack_self(mob/user)
- user.set_machine(src)
+ var/list/handradial = list()
interact(user)
-/obj/item/toy/cards/cardhand/ui_interact(mob/user)
- . = ..()
- var/dat = "You have:
"
for(var/t in currenthand)
- dat += "A [t].
"
- dat += "Which card will you remove next?"
- var/datum/browser/popup = new(user, "cardhand", "Hand of Cards", 400, 240)
- popup.set_content(dat)
- popup.open()
-
-/obj/item/toy/cards/cardhand/Topic(href, href_list)
- if(..())
- return
+ handradial[t] = image(icon = src.icon, icon_state = "sc_[t]_[deckstyle]")
+
if(usr.stat || !ishuman(usr))
return
var/mob/living/carbon/human/cardUser = usr
if(!(cardUser.mobility_flags & MOBILITY_USE))
return
var/O = src
- if(href_list["pick"])
- if (cardUser.is_holding(src))
- var/choice = href_list["pick"]
- if(!(choice in src.currenthand))
- log_href_exploit(usr)
- return
- var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc)
- src.currenthand -= choice
- C.parentdeck = src.parentdeck
- C.cardname = choice
- C.apply_card_vars(C,O)
- cardUser.put_in_hands(C)
- cardUser.visible_message("[cardUser] draws a card from [cardUser.p_their()] hand.", "You take the [C.cardname] from your hand.")
-
- interact(cardUser)
- update_sprite()
- if(src.currenthand.len == 1)
- var/obj/item/toy/cards/singlecard/N = new/obj/item/toy/cards/singlecard(src.loc)
- N.parentdeck = src.parentdeck
- N.cardname = src.currenthand[1]
- N.apply_card_vars(N,O)
- qdel(src)
- cardUser.put_in_hands(N)
- to_chat(cardUser, "You also take [currenthand[1]] and hold it.")
- cardUser << browse(null, "window=cardhand")
- return
+ var/choice = show_radial_menu(usr,src, handradial, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
+ if(!choice)
+ return FALSE
+ var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc)
+ currenthand -= choice
+ handradial -= choice
+ C.parentdeck = parentdeck
+ C.cardname = choice
+ C.apply_card_vars(C,O)
+ C.pickup(cardUser)
+ cardUser.put_in_hands(C)
+ cardUser.visible_message("[cardUser] draws a card from [cardUser.p_their()] hand.", "You take the [C.cardname] from your hand.")
+
+ interact(cardUser)
+ update_sprite()
+ if(length(currenthand) == 1)
+ var/obj/item/toy/cards/singlecard/N = new/obj/item/toy/cards/singlecard(loc)
+ N.parentdeck = parentdeck
+ N.cardname = currenthand[1]
+ N.apply_card_vars(N,O)
+ qdel(src)
+ N.pickup(cardUser)
+ cardUser.put_in_hands(N)
+ to_chat(cardUser, "You also take [currenthand[1]] and hold it.")
/obj/item/toy/cards/cardhand/attackby(obj/item/toy/cards/singlecard/C, mob/living/user, params)
if(istype(C))
@@ -914,6 +894,22 @@
newobj.card_attack_verb = sourceobj.card_attack_verb
newobj.resistance_flags = sourceobj.resistance_flags
+/**
+ * check_menu: Checks if we are allowed to interact with a radial menu
+ *
+ * Arguments:
+ * * user The mob interacting with a menu
+ */
+/obj/item/toy/cards/cardhand/proc/check_menu(mob/living/user)
+ if(!istype(user))
+ return FALSE
+ if(user.incapacitated())
+ return FALSE
+ return TRUE
+
+/**
+ * This proc updates the sprite for when you create a hand of cards
+ */
/obj/item/toy/cards/cardhand/proc/update_sprite()
cut_overlays()
var/overlay_cards = currenthand.len
@@ -925,10 +921,10 @@
/obj/item/toy/cards/singlecard
name = "card"
- desc = "a card"
+ desc = "A playing card used to play card games like poker."
icon = 'icons/obj/toy.dmi'
icon_state = "singlecard_down_nanotrasen"
- w_class = WEIGHT_CLASS_SMALL
+ w_class = WEIGHT_CLASS_TINY
var/cardname = null
var/flipped = 0
pixel_x = -5
@@ -983,6 +979,7 @@
to_chat(user, "You combine the [C.cardname] and the [src.cardname] into a hand.")
qdel(C)
qdel(src)
+ H.pickup(user)
user.put_in_active_hand(H)
else
to_chat(user, "You can't mix cards from other decks!")
@@ -1022,11 +1019,9 @@
newobj.card_attack_verb = sourceobj.card_attack_verb
newobj.attack_verb = newobj.card_attack_verb
-
/*
|| Syndicate playing cards, for pretending you're Gambit and playing poker for the nuke disk. ||
*/
-
/obj/item/toy/cards/deck/syndicate
name = "suspicious looking deck of cards"
desc = "A deck of space-grade playing cards. They seem unusually rigid."
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 7835f3f62aaf7..80f458e96eb38 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -15,9 +15,9 @@
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 70, STAMINA = 0)
resistance_flags = FIRE_PROOF
-/obj/item/banhammer/suicide_act(mob/user)
- user.visible_message("[user] is hitting [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life.")
- return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS)
+/obj/item/banhammer/suicide_act(mob/living/user)
+ user.visible_message("[user] is hitting [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life.")
+ return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS)
/*
oranges says: This is a meme relating to the english translation of the ss13 russian wiki page on lurkmore.
mrdoombringer sez: and remember kids, if you try and PR a fix for this item's grammar, you are admitting that you are, indeed, a newfriend.
@@ -48,7 +48,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "ripped", "diced", "cut")
-/obj/item/sord/suicide_act(mob/user)
+/obj/item/sord/suicide_act(mob/living/user)
user.visible_message("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty.", \
"You try to impale yourself with [src], but it's USELESS...")
return SHAME
@@ -90,9 +90,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
. = ..()
AddComponent(/datum/component/butchering, 40, 105)
-/obj/item/claymore/suicide_act(mob/user)
+/obj/item/claymore/suicide_act(mob/living/user)
user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim."
@@ -149,6 +149,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES
add_notch(user)
target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!")
+ target.investigate_log("has been dusted by a highlander claymore.", INVESTIGATE_DEATHS)
target.dust()
/obj/item/claymore/highlander/attack_self(mob/living/user)
@@ -264,9 +265,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/katana/cursed
slot_flags = null
-/obj/item/katana/suicide_act(mob/user)
+/obj/item/katana/suicide_act(mob/living/user)
user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!")
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/wirerod
name = "wired rod"
@@ -399,9 +400,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
hitsound = 'sound/weapons/genhit.ogg'
sharpness = IS_BLUNT
-/obj/item/switchblade/suicide_act(mob/user)
+/obj/item/switchblade/suicide_act(mob/living/user)
user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/switchblade/kitchen
name = "iron switchblade"
@@ -437,12 +438,12 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
attack_verb = list("called", "rang")
hitsound = 'sound/weapons/ring.ogg'
-/obj/item/phone/suicide_act(mob/user)
+/obj/item/phone/suicide_act(mob/living/user)
if(locate(/obj/structure/chair/stool) in user.loc)
user.visible_message("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!")
else
user.visible_message("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!")
- return(OXYLOSS)
+ return OXYLOSS
/obj/item/cane
name = "cane"
@@ -505,9 +506,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon = 'icons/obj/wizard.dmi'
icon_state = "ectoplasm"
-/obj/item/ectoplasm/suicide_act(mob/user)
+/obj/item/ectoplasm/suicide_act(mob/living/user)
user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane!")
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/ectoplasm/angelic
icon = 'icons/obj/wizard.dmi'
@@ -758,24 +759,27 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/melee/flyswatter/Initialize(mapload)
. = ..()
strong_against = typecacheof(list(
- /mob/living/simple_animal/hostile/poison/bees/,
- /mob/living/simple_animal/butterfly,
- /mob/living/basic/cockroach,
- /obj/item/queen_bee
+ /mob/living/simple_animal/hostile/poison/bees/,
+ /mob/living/simple_animal/butterfly,
+ /mob/living/basic/cockroach,
+ /obj/item/queen_bee
))
/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag)
. = ..()
- if(proximity_flag)
- if(is_type_in_typecache(target, strong_against))
- new /obj/effect/decal/cleanable/insectguts(target.drop_location())
- to_chat(user, "You easily splat the [target].")
- if(istype(target, /mob/living/))
- var/mob/living/bug = target
- bug.death(1)
- else
- qdel(target)
+ if(!proximity_flag || HAS_TRAIT(user, TRAIT_PACIFISM))
+ return
+
+ if(is_type_in_typecache(target, strong_against))
+ new /obj/effect/decal/cleanable/insectguts(target.drop_location())
+ to_chat(user, "You easily splat the [target].")
+ if(istype(target, /mob/living/))
+ var/mob/living/bug = target
+ bug.investigate_log("has been splatted by a flyswatter.", INVESTIGATE_DEATHS)
+ bug.death(1)
+ else
+ qdel(target)
/obj/item/circlegame
name = "circled hand"
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 52fdb93c3f106..3443f1b65a5a3 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -33,7 +33,7 @@
if(damage_flag)
armor_protection = armor.getRating(damage_flag)
if(armor_protection) //Only apply weak-against-armor/hollowpoint effects if there actually IS armor.
- armor_protection = CLAMP(armor_protection - armour_penetration, min(armor_protection, 0), 100)
+ armor_protection = clamp(armor_protection - armour_penetration, min(armor_protection, 0), 100)
return round(damage_amount * (100 - armor_protection)*0.01, DAMAGE_PRECISION)
//the sound played when the obj is damaged.
@@ -228,7 +228,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(T.intact && HAS_TRAIT(src, TRAIT_T_RAY_VISIBLE))
return
if(exposed_temperature && !(resistance_flags & FIRE_PROOF))
- take_damage(CLAMP(0.02 * exposed_temperature, 0, 20), BURN, FIRE, 0)
+ take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, FIRE, 0)
if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE) && !(resistance_flags & FIRE_PROOF))
resistance_flags |= ON_FIRE
SSfire_burning.processing[src] = src
@@ -259,7 +259,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(has_buckled_mobs())
for(var/m in buckled_mobs)
var/mob/living/buckled_mob = m
- buckled_mob.electrocute_act((CLAMP(round(strength/400), 10, 90) + rand(-5, 5)), src, tesla_shock = 1)
+ buckled_mob.electrocute_act((clamp(round(strength/400), 10, 90) + rand(-5, 5)), src, tesla_shock = 1)
/obj/proc/reset_shocked()
obj_flags &= ~BEING_SHOCKED
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index 62501363e11ea..b01676702fadc 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -339,6 +339,14 @@
item_chair = null
icon_state = "officechair_dark"
+/obj/structure/chair/office/relaymove(mob/user, direction)
+ if(!direction)
+ return FALSE
+ if(direction == dir)
+ return
+ setDir(direction)
+ return FALSE
+
/obj/structure/chair/office/Moved()
. = ..()
if(has_gravity())
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index d70ade784ac5b..735e16b6f7cd5 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -582,12 +582,12 @@
step_towards(user, T2)
T1 = get_turf(user)
if(T1 == T2)
- user.resting = TRUE //so people can jump into crates without slamming the lid on their head
+ user.set_resting(TRUE) //so people can jump into crates without slamming the lid on their head
if(!close(user))
to_chat(user, "You can't get [src] to close!")
- user.resting = FALSE
+ user.set_resting(FALSE)
return
- user.resting = FALSE
+ user.set_resting(FALSE)
togglelock(user)
T1.visible_message("[user] dives into [src]!")
diff --git a/code/game/objects/structures/divine.dm b/code/game/objects/structures/divine.dm
index 8667804dab1b9..353697111bb3d 100644
--- a/code/game/objects/structures/divine.dm
+++ b/code/game/objects/structures/divine.dm
@@ -17,6 +17,7 @@
if(!L)
return
to_chat(user, "You attempt to sacrifice [L] by invoking the sacrificial ritual.")
+ L.investigate_log("has been sacrificially gibbed on an altar.", INVESTIGATE_DEATHS)
L.gib()
message_admins("[ADMIN_LOOKUPFLW(user)] has sacrificed [key_name_admin(L)] on the sacrificial altar at [AREACOORD(src)].")
diff --git a/code/game/objects/structures/fireplace.dm b/code/game/objects/structures/fireplace.dm
index 13eaacdfa589f..6b610992d9aa6 100644
--- a/code/game/objects/structures/fireplace.dm
+++ b/code/game/objects/structures/fireplace.dm
@@ -129,7 +129,7 @@
if(burn_time_remaining() < MAXIMUM_BURN_TIMER)
flame_expiry_timer = world.time + MAXIMUM_BURN_TIMER
else
- fuel_added = CLAMP(fuel_added + amount, 0, MAXIMUM_BURN_TIMER)
+ fuel_added = clamp(fuel_added + amount, 0, MAXIMUM_BURN_TIMER)
/obj/structure/fireplace/proc/burn_time_remaining()
if(lit)
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 388d58bfaddcc..7e98be116ca57 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -273,7 +273,9 @@ GLOBAL_LIST_EMPTY(crematoriums)
log_combat(user, M, "cremated")
else
M.log_message("was cremated", LOG_ATTACK)
- M.death(1)
+ if(user.stat != DEAD)
+ user.investigate_log("has died from being cremated.", INVESTIGATE_DEATHS)
+ M.death(TRUE)
if(M) //some animals get automatically deleted on death.
M.ghostize()
qdel(M)
diff --git a/code/game/objects/structures/petrified_statue.dm b/code/game/objects/structures/petrified_statue.dm
index 1b2702f2d3cf4..b54adca7ecda7 100644
--- a/code/game/objects/structures/petrified_statue.dm
+++ b/code/game/objects/structures/petrified_statue.dm
@@ -68,8 +68,9 @@
/obj/structure/statue/petrified/deconstruct(disassembled = TRUE)
if(!disassembled)
if(petrified_mob)
+ petrified_mob.investigate_log("has been dusted by statue deconstruction.", INVESTIGATE_DEATHS)
petrified_mob.dust()
- visible_message("[src] shatters!.")
+ visible_message("[src] shatters!")
qdel(src)
diff --git a/code/game/objects/structures/showcase.dm b/code/game/objects/structures/showcase.dm
index c7d4f98f248f4..038134f41c3d5 100644
--- a/code/game/objects/structures/showcase.dm
+++ b/code/game/objects/structures/showcase.dm
@@ -15,18 +15,18 @@
name = "\improper CentCom identification console"
desc = "You can use this to change ID's."
icon = 'icons/obj/computer.dmi'
- icon_state = "computer"
+ icon_state = "computer-0"
/obj/structure/showcase/fakeid/Initialize(mapload)
. = ..()
add_overlay("id")
- add_overlay("id_key")
+ add_overlay("generic_key")
/obj/structure/showcase/fakesec
name = "\improper CentCom security records"
desc = "Used to view and edit personnel's security records."
icon = 'icons/obj/computer.dmi'
- icon_state = "computer"
+ icon_state = "computer-0"
/obj/structure/showcase/fakesec/Initialize(mapload)
. = ..()
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index ba71167abf40f..144e39881e4fe 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -287,9 +287,9 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
if(depth)
var/list/target_baseturfs
if(length(copytarget.baseturfs))
- // with default inputs this would be Copy(CLAMP(2, -INFINITY, baseturfs.len))
+ // with default inputs this would be Copy(clamp(2, -INFINITY, baseturfs.len))
// Don't forget a lower index is lower in the baseturfs stack, the bottom is baseturfs[1]
- target_baseturfs = copytarget.baseturfs.Copy(CLAMP(1 + ignore_bottom, 1 + copytarget.baseturfs.len - depth, copytarget.baseturfs.len))
+ target_baseturfs = copytarget.baseturfs.Copy(clamp(1 + ignore_bottom, 1 + copytarget.baseturfs.len - depth, copytarget.baseturfs.len))
else if(!ignore_bottom)
target_baseturfs = list(copytarget.baseturfs)
if(target_baseturfs)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index f56ae01bdb9d5..b6221d1419d1e 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -525,7 +525,7 @@ GLOBAL_LIST_EMPTY(created_baseturf_lists)
/turf/AllowDrop()
return TRUE
-/turf/proc/add_vomit_floor(mob/living/M, toxvomit = NONE)
+/turf/proc/add_vomit_floor(mob/living/M, toxvomit = NONE, purge = TRUE)
var/obj/effect/decal/cleanable/vomit/V = new /obj/effect/decal/cleanable/vomit(src, M.get_static_viruses())
@@ -539,7 +539,11 @@ GLOBAL_LIST_EMPTY(created_baseturf_lists)
V.icon_state = "vomitpurp_[pick(1,4)]"
else if (toxvomit == VOMIT_TOXIC)
V.icon_state = "vomittox_[pick(1,4)]"
- if (iscarbon(M))
+ else if (toxvomit == VOMIT_NANITE)
+ V.name = "metallic slurry"
+ V.desc = "A puddle of metallic slurry that looks vaguely like very fine sand. It almost seems like it's moving..."
+ V.icon_state = "vomitnanite_[pick(1,4)]"
+ if (purge && iscarbon(M))
var/mob/living/carbon/C = M
if(C.reagents)
clear_reagents_to_vomit_pool(C,V)
diff --git a/code/game/world.dm b/code/game/world.dm
index a9d2320094faa..fac2213f04d4e 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -160,6 +160,7 @@ GLOBAL_VAR(restart_counter)
GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log"
GLOB.world_paper_log = "[GLOB.log_directory]/paper.log"
GLOB.tgui_log = "[GLOB.log_directory]/tgui.log"
+ GLOB.prefs_log = "[GLOB.log_directory]/preferences.log"
#ifdef UNIT_TESTS
GLOB.test_log = file("[GLOB.log_directory]/tests.log")
@@ -180,6 +181,7 @@ GLOBAL_VAR(restart_counter)
start_log(GLOB.world_job_debug_log)
start_log(GLOB.world_id_log)
start_log(GLOB.tgui_log)
+ start_log(GLOB.prefs_log)
GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently
if(fexists(GLOB.config_error_log))
@@ -411,6 +413,29 @@ GLOBAL_VAR(restart_counter)
/world/proc/refresh_atmos_grid()
+/world/proc/change_fps(new_value = 20)
+ if(new_value <= 0)
+ CRASH("change_fps() called with [new_value] new_value.")
+ if(fps == new_value)
+ return //No change required.
+
+ fps = new_value
+ on_tickrate_change()
+
+/* UNUSED. uncomment if using
+/world/proc/change_tick_lag(new_value = 0.5)
+ if(new_value <= 0)
+ CRASH("change_tick_lag() called with [new_value] new_value.")
+ if(tick_lag == new_value)
+ return //No change required.
+
+ tick_lag = new_value
+ on_tickrate_change()
+*/
+
+/world/proc/on_tickrate_change()
+ SStimer?.reset_buckets()
+
/world/proc/init_byond_tracy()
var/library
diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm
index 802c7b0c7ebe8..dcba7faa8990f 100644
--- a/code/modules/admin/admin_investigate.dm
+++ b/code/modules/admin/admin_investigate.dm
@@ -11,23 +11,25 @@
return
var/list/investigates = list(
- INVESTIGATE_RESEARCH,
- INVESTIGATE_EXONET,
- INVESTIGATE_PORTAL,
- INVESTIGATE_ENGINES,
- INVESTIGATE_WIRES,
- INVESTIGATE_TELESCI,
- INVESTIGATE_GRAVITY,
- INVESTIGATE_RECORDS,
- INVESTIGATE_CARGO,
INVESTIGATE_ATMOS,
- INVESTIGATE_EXPERIMENTOR,
INVESTIGATE_BOTANY,
+ INVESTIGATE_CARGO,
+ INVESTIGATE_DEATHS,
+ INVESTIGATE_ENGINES,
+ INVESTIGATE_EXONET,
+ INVESTIGATE_EXPERIMENTOR,
+ INVESTIGATE_GRAVITY,
INVESTIGATE_HALLUCINATIONS,
- INVESTIGATE_RADIATION,
+ INVESTIGATE_ITEMS,
INVESTIGATE_NANITES,
+ INVESTIGATE_PORTAL,
INVESTIGATE_PRESENTS,
- INVESTIGATE_ITEMS)
+ INVESTIGATE_RADIATION,
+ INVESTIGATE_RECORDS,
+ INVESTIGATE_RESEARCH,
+ INVESTIGATE_TELESCI,
+ INVESTIGATE_WIRES,
+ )
var/list/logs_present = list("notes, memos, watchlist")
var/list/logs_missing = list("---")
diff --git a/code/modules/admin/battle_royale.dm b/code/modules/admin/battle_royale.dm
index 1c6e4f8fcf9bc..3326bfb73e400 100644
--- a/code/modules/admin/battle_royale.dm
+++ b/code/modules/admin/battle_royale.dm
@@ -434,10 +434,10 @@ GLOBAL_DATUM(battle_royale, /datum/battle_royale_controller)
center_turf = center
/obj/effect/death_wall/proc/decrease_size()
- var/minx = CLAMP(center_turf.x - current_radius, 1, 255)
- var/maxx = CLAMP(center_turf.x + current_radius, 1, 255)
- var/miny = CLAMP(center_turf.y - current_radius, 1, 255)
- var/maxy = CLAMP(center_turf.y + current_radius, 1, 255)
+ var/minx = clamp(center_turf.x - current_radius, 1, 255)
+ var/maxx = clamp(center_turf.x + current_radius, 1, 255)
+ var/miny = clamp(center_turf.y - current_radius, 1, 255)
+ var/maxy = clamp(center_turf.y + current_radius, 1, 255)
if(y == maxy || y == miny)
//We have nowhere to move to so are deleted
if(x == minx || x == minx + 1 || x == maxx || x == maxx - 1)
diff --git a/code/modules/admin/fun_balloon.dm b/code/modules/admin/fun_balloon.dm
index 33308c17d44e7..619cb5c34bb3d 100644
--- a/code/modules/admin/fun_balloon.dm
+++ b/code/modules/admin/fun_balloon.dm
@@ -60,7 +60,7 @@
to_chat(body, "Your mob has been taken over by a ghost!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(body)])")
- body.ghostize(0)
+ body.ghostize(FALSE)
body.key = C.key
new /obj/effect/temp_visual/gravpush(get_turf(body))
diff --git a/code/modules/admin/sound_emitter.dm b/code/modules/admin/sound_emitter.dm
index 0fee3c6ba8ad4..5644e8694d119 100644
--- a/code/modules/admin/sound_emitter.dm
+++ b/code/modules/admin/sound_emitter.dm
@@ -95,7 +95,7 @@
var/new_volume = input(user, "Choose a volume.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_volume))
return
- new_volume = CLAMP(new_volume, 0, 100)
+ new_volume = clamp(new_volume, 0, 100)
sound_volume = new_volume
to_chat(user, "Volume set to [sound_volume]%.")
if(href_list["edit_mode"])
@@ -118,7 +118,7 @@
var/new_radius = input(user, "Choose a radius.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_radius))
return
- new_radius = CLAMP(new_radius, 0, 127)
+ new_radius = clamp(new_radius, 0, 127)
play_radius = new_radius
to_chat(user, "Audible radius set to [play_radius].")
if(href_list["play"])
diff --git a/code/modules/admin/sql_message_system.dm b/code/modules/admin/sql_message_system.dm
index 84150c0c36588..be27255532cfe 100644
--- a/code/modules/admin/sql_message_system.dm
+++ b/code/modules/admin/sql_message_system.dm
@@ -502,7 +502,7 @@
var/nsd = CONFIG_GET(number/note_stale_days)
var/nfd = CONFIG_GET(number/note_fresh_days)
if (agegate && type == "note" && isnum_safe(nsd) && isnum_safe(nfd) && nsd > nfd)
- var/alpha = CLAMP(100 - (age - nfd) * (85 / (nsd - nfd)), 15, 100)
+ var/alpha = clamp(100 - (age - nfd) * (85 / (nsd - nfd)), 15, 100)
if (alpha < 100)
if (alpha <= 15)
if (skipped)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index afd5152e6276c..04b7a43267539 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1418,7 +1418,7 @@
return
var/list/offset = splittext(href_list["offset"],",")
- var/number = CLAMP(text2num(href_list["object_count"]), 1, 100)
+ var/number = clamp(text2num(href_list["object_count"]), 1, 100)
var/X = offset.len > 0 ? text2num(offset[1]) : 0
var/Y = offset.len > 1 ? text2num(offset[2]) : 0
var/Z = offset.len > 2 ? text2num(offset[3]) : 0
diff --git a/code/modules/admin/verbs/_help.dm b/code/modules/admin/verbs/_help.dm
index 2952233cbf01a..bf9c7a9c534a1 100644
--- a/code/modules/admin/verbs/_help.dm
+++ b/code/modules/admin/verbs/_help.dm
@@ -233,10 +233,19 @@
for(var/datum/help_ticket/AH in l)
if(AH.initiator)
tab_data["#[AH.id]. [AH.initiator_key_name]"] = list(
- text = AH.name,
+ text = AH.stat_text,
type = STAT_BUTTON,
action = "open_ticket",
params = list("id" = AH.id),
+ multirow = TRUE,
+ buttons = list(
+ list(
+ "title" = AH.claimee_key_name ? "Claimed by [AH.claimee_key_name]" : "Claim",
+ "color" = AH.claimee_key_name ? "red" : "green",
+ "action_id" = "claim_ticket",
+ "params" = list("id" = AH.id)
+ )
+ )
)
else
++num_disconnected
@@ -311,6 +320,7 @@
/datum/help_ticket
var/id
var/name
+ var/stat_text
var/state = TICKET_UNCLAIMED
/// The first (sanitized) message for this ticket
var/initial_msg
@@ -359,6 +369,7 @@
opened_at = world.time
name = copytext_char(msg, 1, 100)
+ stat_text = copytext_char(msg, 1, 500)
var/datum/help_tickets/data_glob = get_data_glob()
if(!istype(data_glob))
diff --git a/code/modules/admin/verbs/borgpanel.dm b/code/modules/admin/verbs/borgpanel.dm
index ef88eba0544f5..77e2b5acb12bc 100644
--- a/code/modules/admin/verbs/borgpanel.dm
+++ b/code/modules/admin/verbs/borgpanel.dm
@@ -89,7 +89,7 @@
if ("set_charge")
var/newcharge = input("New charge (0-[borg.cell.maxcharge]):", borg.name, borg.cell.charge) as num|null
if (newcharge)
- borg.cell.charge = CLAMP(newcharge, 0, borg.cell.maxcharge)
+ borg.cell.charge = clamp(newcharge, 0, borg.cell.maxcharge)
message_admins("[key_name_admin(user)] set the charge of [ADMIN_LOOKUPFLW(borg)] to [borg.cell.charge].")
log_admin("[key_name(user)] set the charge of [key_name(borg)] to [borg.cell.charge].")
if ("remove_cell")
diff --git a/code/modules/admin/verbs/fps.dm b/code/modules/admin/verbs/fps.dm
index 2b65d2a44c5a0..a738955052612 100644
--- a/code/modules/admin/verbs/fps.dm
+++ b/code/modules/admin/verbs/fps.dm
@@ -23,4 +23,4 @@
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Set Server FPS", "[new_fps]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
CONFIG_SET(number/fps, new_fps)
- world.fps = new_fps
+ world.change_fps(new_fps)
diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm
index f08ee0db993e5..c5038cc2de77c 100644
--- a/code/modules/admin/verbs/playsound.dm
+++ b/code/modules/admin/verbs/playsound.dm
@@ -13,7 +13,7 @@
var/vol = input(usr, "What volume would you like the sound to play at?",, 100) as null|num
if(!vol)
return
- vol = CLAMP(vol, 1, 100)
+ vol = clamp(vol, 1, 100)
var/sound/admin_sound = new()
admin_sound.file = S
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index 127f032e9c24b..8922b68e23d64 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -58,9 +58,7 @@
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
H.update_inv_wear_suit()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user)
if(slot == ITEM_SLOT_OCLOTHING) //we only give the mob the ability to activate the vest if he's actually wearing it.
diff --git a/code/modules/antagonists/abductor/machinery/camera.dm b/code/modules/antagonists/abductor/machinery/camera.dm
index 1d15a2c5772a0..2fc5400c6d91e 100644
--- a/code/modules/antagonists/abductor/machinery/camera.dm
+++ b/code/modules/antagonists/abductor/machinery/camera.dm
@@ -13,6 +13,10 @@
icon = 'icons/obj/abductor.dmi'
icon_state = "camera"
+ base_icon_state = null
+ smoothing_flags = NONE
+ smoothing_groups = null
+ canSmoothWith = null
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
reveal_camera_mob = TRUE
diff --git a/code/modules/antagonists/blob/blob_mobs.dm b/code/modules/antagonists/blob/blob_mobs.dm
index e2c9356645a03..6763875819065 100644
--- a/code/modules/antagonists/blob/blob_mobs.dm
+++ b/code/modules/antagonists/blob/blob_mobs.dm
@@ -55,7 +55,7 @@
/mob/living/simple_animal/hostile/blob/fire_act(exposed_temperature, exposed_volume)
..()
if(exposed_temperature)
- adjustFireLoss(CLAMP(0.01 * exposed_temperature, 1, 5))
+ adjustFireLoss(clamp(0.01 * exposed_temperature, 1, 5))
else
adjustFireLoss(5)
diff --git a/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm b/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm
index 5a165e8bf4aaa..41a28d5204e14 100644
--- a/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm
+++ b/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm
@@ -36,6 +36,7 @@
reac_volume = ..()
M.apply_damage(0.6*reac_volume, TOX)
if(O && ishuman(M) && M.stat == UNCONSCIOUS)
+ M.investigate_log("has been killed by distributed neurons (blob).", INVESTIGATE_DEATHS)
M.death() //sleeping in a fight? bad plan.
var/points = rand(5, 10)
var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(get_turf(M))
diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm
index afb8c1e3ab2f9..fb2e7fba7d486 100644
--- a/code/modules/antagonists/blob/overmind.dm
+++ b/code/modules/antagonists/blob/overmind.dm
@@ -148,6 +148,8 @@ GLOBAL_LIST_EMPTY(blob_nodes)
if(!(FACTION_BLOB in L.faction))
playsound(L, 'sound/effects/splat.ogg', 50, 1)
+ if(L.stat != DEAD)
+ L.investigate_log("has died from blob takeover.", INVESTIGATE_DEATHS)
L.death()
new/mob/living/simple_animal/hostile/blob/blobspore(T)
else
@@ -215,7 +217,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
B.hud_used.blobpwrdisplay.maptext = MAPTEXT("[round(blob_core.obj_integrity)]
")
/mob/camera/blob/proc/add_points(points)
- blob_points = CLAMP(blob_points + points, 0, max_blob_points)
+ blob_points = clamp(blob_points + points, 0, max_blob_points)
hud_used.blobpwrdisplay.maptext = MAPTEXT("[round(blob_points)]
")
/mob/camera/blob/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm
index 3792b36b3639b..7313a5989a885 100644
--- a/code/modules/antagonists/changeling/powers/absorb.dm
+++ b/code/modules/antagonists/changeling/powers/absorb.dm
@@ -142,6 +142,8 @@
changeling.isabsorbing = 0
changeling.canrespec = 1
- target.death(0)
+ if(target.stat != DEAD)
+ target.investigate_log("has died from being changeling absorbed.", INVESTIGATE_DEATHS)
+ target.death(FALSE)
target.Drain()
return TRUE
diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm
index 2d66d264db427..13a40871292d9 100644
--- a/code/modules/antagonists/changeling/powers/fakedeath.dm
+++ b/code/modules/antagonists/changeling/powers/fakedeath.dm
@@ -24,7 +24,6 @@
else
to_chat(user, "We begin our stasis, preparing energy to arise once more.")
user.fakedeath("changeling") //play dead
- user.update_stat()
user.update_mobility()
addtimer(CALLBACK(src, PROC_REF(ready_to_regenerate), user.mind), LING_FAKEDEATH_TIME, TIMER_UNIQUE)
return TRUE
diff --git a/code/modules/antagonists/changeling/powers/headcrab.dm b/code/modules/antagonists/changeling/powers/headcrab.dm
index 85cf9dd85961a..7f75daae24be3 100644
--- a/code/modules/antagonists/changeling/powers/headcrab.dm
+++ b/code/modules/antagonists/changeling/powers/headcrab.dm
@@ -56,5 +56,6 @@
if(crab.origin)
crab.origin.active = 1
crab.origin.transfer_to(crab)
+ user.investigate_log("has been gibbed by using their Last Resort headcrab ability.", INVESTIGATE_DEATHS)
user.gib()
to_chat(crab, "You burst out of the remains of your former body in a shower of gore!")
diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm
index 34ad063d6e5bd..c974b8aa2194e 100644
--- a/code/modules/antagonists/changeling/powers/mutations.dm
+++ b/code/modules/antagonists/changeling/powers/mutations.dm
@@ -248,10 +248,9 @@
if(charges == 0)
qdel(src)
-/obj/item/gun/magic/tentacle/suicide_act(mob/user)
+/obj/item/gun/magic/tentacle/suicide_act(mob/living/user)
user.visible_message("[user] coils [src] tightly around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide!")
- return (OXYLOSS)
-
+ return OXYLOSS
/obj/item/ammo_casing/magic/tentacle
name = "tentacle"
diff --git a/code/modules/antagonists/clock_cult/items/replica_fabricator.dm b/code/modules/antagonists/clock_cult/items/replica_fabricator.dm
index 4377824f1987a..3ede705c2568a 100644
--- a/code/modules/antagonists/clock_cult/items/replica_fabricator.dm
+++ b/code/modules/antagonists/clock_cult/items/replica_fabricator.dm
@@ -57,12 +57,12 @@
return
GLOB.clockcult_power -= 200
to_chat(user, "You repair some of the damage on \the [C].")
- C.obj_integrity = CLAMP(C.obj_integrity + 15, 0, C.max_integrity)
+ C.obj_integrity = clamp(C.obj_integrity + 15, 0, C.max_integrity)
else
to_chat(user, "You fail to repair the damage of \the [C]...")
/obj/item/clockwork/replica_fabricator/proc/fabricate_sheets(turf/target, mob/user)
- var/sheets = FLOOR(CLAMP(GLOB.clockcult_power / BRASS_POWER_COST, 0, 50), 1)
+ var/sheets = FLOOR(clamp(GLOB.clockcult_power / BRASS_POWER_COST, 0, 50), 1)
if(sheets == 0)
return
GLOB.clockcult_power -= sheets * BRASS_POWER_COST
diff --git a/code/modules/antagonists/clock_cult/scriptures/kindle.dm b/code/modules/antagonists/clock_cult/scriptures/kindle.dm
index c8593f36bb13e..3a572894dde09 100644
--- a/code/modules/antagonists/clock_cult/scriptures/kindle.dm
+++ b/code/modules/antagonists/clock_cult/scriptures/kindle.dm
@@ -54,7 +54,7 @@
M.Paralyze(150)
else
to_chat(invoker, "[M] seems somewhat resistant to your powers!")
- M.confused = CLAMP(M.confused, 50, INFINITY)
+ M.confused = clamp(M.confused, 50, INFINITY)
if(issilicon(M))
var/mob/living/silicon/S = M
S.emp_act(EMP_HEAVY)
diff --git a/code/modules/antagonists/clock_cult/scriptures/sigil_of_vitality.dm b/code/modules/antagonists/clock_cult/scriptures/sigil_of_vitality.dm
index 0d80bd2aa4790..d5e4010d9c490 100644
--- a/code/modules/antagonists/clock_cult/scriptures/sigil_of_vitality.dm
+++ b/code/modules/antagonists/clock_cult/scriptures/sigil_of_vitality.dm
@@ -61,7 +61,7 @@
else
visible_message("\The [src] fails to revive [M]!")
return
- var/healing_performed = CLAMP(M.maxHealth - M.health, 0, 5) //5 Vitality to heal 5 of all damage types at once
+ var/healing_performed = clamp(M.maxHealth - M.health, 0, 5) //5 Vitality to heal 5 of all damage types at once
if(GLOB.clockcult_vitality >= healing_performed * 0.3)
GLOB.clockcult_vitality -= healing_performed * 0.3
//Do healing
diff --git a/code/modules/antagonists/clock_cult/structure/clockwork_camera.dm b/code/modules/antagonists/clock_cult/structure/clockwork_camera.dm
index 55eb9795502b5..0cc0a9d8a8a3a 100644
--- a/code/modules/antagonists/clock_cult/structure/clockwork_camera.dm
+++ b/code/modules/antagonists/clock_cult/structure/clockwork_camera.dm
@@ -57,6 +57,10 @@
icon_screen = "ratvar1"
icon_keyboard = "ratvar_key1"
icon_state = "ratvarcomputer"
+ base_icon_state = null
+ smoothing_flags = NONE
+ smoothing_groups = null
+ canSmoothWith = null
clockwork = TRUE
lock_override = CAMERA_LOCK_STATION
broken_overlay_emissive = TRUE
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 3dc4b39cd7727..644f52368d8a4 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -335,9 +335,11 @@ structure_check() searches for nearby cultist structures required for the invoca
if(sacrificial)
if(iscyborg(sacrificial))
playsound(sacrificial, 'sound/magic/disable_tech.ogg', 100, 1)
+ sacrificial.investigate_log("has been sacrificially dusted by the cult.", INVESTIGATE_DEATHS)
sacrificial.dust() //To prevent the MMI from remaining
else
playsound(sacrificial, 'sound/magic/disintegrate.ogg', 100, 1)
+ sacrificial.investigate_log("has been sacrificially gibbed by the cult.", INVESTIGATE_DEATHS)
sacrificial.gib()
return TRUE
@@ -934,7 +936,7 @@ structure_check() searches for nearby cultist structures required for the invoca
affecting.add_atom_colour(RUNE_COLOR_DARKRED, ADMIN_COLOUR_PRIORITY)
affecting.visible_message("[affecting] freezes statue-still, glowing an unearthly red.", \
"You see what lies beyond. All is revealed. In this form you find that your voice booms louder and you can mark targets for the entire cult")
- var/mob/dead/observer/G = affecting.ghostize(1)
+ var/mob/dead/observer/G = affecting.ghostize(TRUE)
var/datum/action/innate/cult/comm/spirit/CM = new
var/datum/action/innate/cult/ghostmark/GM = new
G.name = "Dark Spirit of [G.name]"
diff --git a/code/modules/antagonists/heretic/influences.dm b/code/modules/antagonists/heretic/influences.dm
index 8b394c5d71477..fbf5e092f56d4 100644
--- a/code/modules/antagonists/heretic/influences.dm
+++ b/code/modules/antagonists/heretic/influences.dm
@@ -183,6 +183,7 @@
qdel(head)
else
human_user.gib()
+ human_user.investigate_log("has died from using telekinesis on a heretic influence.", INVESTIGATE_DEATHS)
var/datum/effect_system/reagents_explosion/explosion = new()
explosion.set_up(1, get_turf(human_user), TRUE, 0)
diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm
index 9d696dd4f9f4b..fee23bad30d2a 100644
--- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm
+++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm
@@ -482,6 +482,7 @@
sac_target.spill_organs()
sac_target.apply_damage(250, BRUTE)
if(sac_target.stat != DEAD)
+ sac_target.investigate_log("has been killed by heretic sacrifice.", INVESTIGATE_DEATHS)
sac_target.death()
sac_target.visible_message(
"[sac_target]'s organs are pulled out of [sac_target.p_their()] chest by shadowy hands!",
diff --git a/code/modules/antagonists/heretic/magic/mansus_grasp.dm b/code/modules/antagonists/heretic/magic/mansus_grasp.dm
index b41a8fc8e46f8..0fb467dce66db 100644
--- a/code/modules/antagonists/heretic/magic/mansus_grasp.dm
+++ b/code/modules/antagonists/heretic/magic/mansus_grasp.dm
@@ -16,7 +16,7 @@
catchphrase = "R'CH T'H TR'TH!"
on_use_sound = 'sound/items/welder.ogg'
-/obj/item/melee/touch_attack/mansus_fist/Initialize(mapload)
+/obj/item/melee/touch_attack/mansus_fist/Initialize(mapload, obj/effect/proc_holder/spell/targeted/touch/_spell)
. = ..()
AddComponent(/datum/component/effect_remover, \
success_feedback = "You remove %THEEFFECT.", \
@@ -86,7 +86,7 @@
return TRUE
-/obj/item/melee/touch_attack/mansus_fist/suicide_act(mob/user)
+/obj/item/melee/touch_attack/mansus_fist/suicide_act(mob/living/user)
user.visible_message("[user] covers [user.p_their()] face with [user.p_their()] sickly-looking hand! It looks like [user.p_theyre()] trying to commit suicide!")
var/mob/living/carbon/carbon_user = user //iscarbon already used in spell's parent
if(!IS_HERETIC(user))
diff --git a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
index 9b63424954158..0c484e312d3dd 100644
--- a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
+++ b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
@@ -24,6 +24,7 @@
continue
//This is essentially a death mark, use this to finish your opponent quicker.
if(target.InCritical() && !HAS_TRAIT(target, TRAIT_NODEATH))
+ target.investigate_log("has been killed by fiery rebirth.", INVESTIGATE_DEATHS)
target.death()
target.adjustFireLoss(20)
diff --git a/code/modules/antagonists/incursion/incursion.dm b/code/modules/antagonists/incursion/incursion.dm
index bde2dc75b0a03..306168009d6c4 100644
--- a/code/modules/antagonists/incursion/incursion.dm
+++ b/code/modules/antagonists/incursion/incursion.dm
@@ -171,7 +171,7 @@
objectives = list()
var/is_hijacker = GLOB.player_details.len >= 35 ? prob(15) : 0
for(var/i = 1 to max(1, CONFIG_GET(number/incursion_objective_amount)))
- forge_single_objective(CLAMP((5 + !is_hijacker)-i, 1, 3), restricted_jobs) //Hijack = 3, 2, 1, 1 no hijack = 3, 3, 2, 1
+ forge_single_objective(clamp((5 + !is_hijacker)-i, 1, 3), restricted_jobs) //Hijack = 3, 2, 1, 1 no hijack = 3, 3, 2, 1
if(is_hijacker)
if(!(locate(/datum/objective/hijack) in objectives))
add_objective(new/datum/objective/hijack)
@@ -179,7 +179,7 @@
add_objective(new/datum/objective/escape/single, FALSE)
/datum/team/incursion/proc/forge_single_objective(difficulty=1, list/restricted_jobs)
- difficulty = CLAMP(difficulty, 1, 3)
+ difficulty = clamp(difficulty, 1, 3)
switch(difficulty)
if(3)
if(LAZYLEN(active_ais()) && prob(25)) //25 %
diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
index 946ea478f5c5a..a62ef4234ab55 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
@@ -612,6 +612,8 @@
return
for(var/mob/M in GLOB.mob_list)
if(M.stat != DEAD && M.get_virtual_z_level() == z)
+ to_chat(M, "You are shredded to atoms!")
+ M.investigate_log("has been gibbed by a nuclear blast.", INVESTIGATE_DEATHS)
M.gib()
/*
@@ -733,7 +735,7 @@ This is here to make the tiles around the station mininuke change when it's arme
return TRUE
return ..()
-/obj/item/disk/nuclear/suicide_act(mob/user)
+/obj/item/disk/nuclear/suicide_act(mob/living/user)
user.visible_message("[user] is going delta! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(src, 'sound/machines/alarm.ogg', 50, -1, TRUE)
for(var/i in 1 to 100)
@@ -745,7 +747,7 @@ This is here to make the tiles around the station mininuke change when it's arme
user.remove_atom_colour(ADMIN_COLOUR_PRIORITY)
user.visible_message("[user] is destroyed by the nuclear blast!")
user.adjustOxyLoss(200)
- user.death(0)
+ user.death(FALSE)
/obj/item/disk/nuclear/fake
fake = TRUE
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index ed585f33f995a..1f147c110d771 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -530,10 +530,10 @@
revenant = null
qdel(src)
-/obj/item/ectoplasm/revenant/suicide_act(mob/user)
+/obj/item/ectoplasm/revenant/suicide_act(mob/living/user)
user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the shadow realm!")
scatter()
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/ectoplasm/revenant/Destroy()
if(!QDELETED(revenant))
diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm
index 230014931f5f6..484ad8cc40f3d 100644
--- a/code/modules/antagonists/revenant/revenant_abilities.dm
+++ b/code/modules/antagonists/revenant/revenant_abilities.dm
@@ -72,7 +72,7 @@
if(orbiting)
to_chat(src, "You can't siphon essence during orbiting!")
return
- if(!target.stat && !target.stam_paralyzed)
+ if(!target.stat && !HAS_TRAIT_FROM(target, TRAIT_INCAPACITATED, STAMINA))
to_chat(src, "[target.p_their(TRUE)] soul is too strong to harvest.")
if(prob(10))
to_chat(target, "You feel as if you are being watched.")
@@ -100,7 +100,7 @@
if(90 to INFINITY)
to_chat(src, "Ah, the perfect soul. [target] will yield massive amounts of essence to you.")
if(do_after(src, rand(15, 25), target, timed_action_flags = IGNORE_HELD_ITEM)) //how about now
- if(!target.stat && !target.stam_paralyzed)
+ if(!target.stat && !HAS_TRAIT_FROM(target, TRAIT_INCAPACITATED, STAMINA))
to_chat(src, "[target.p_theyre(TRUE)] now powerful enough to fight off your draining.")
to_chat(target, "You feel something tugging across your body before subsiding.")
draining = 0
@@ -134,7 +134,9 @@
target.visible_message("[target] slumps onto the ground.", \
"Violets lights, dancing in your vision, getting clo--")
drained_mobs.Add(target)
- target.death(0)
+ if(target.stat != DEAD)
+ target.investigate_log("has died from revenant harvest.", INVESTIGATE_DEATHS)
+ target.death(FALSE)
else
to_chat(src, "[target ? "[target] has":"[target.p_theyve(TRUE)]"] been drawn out of your grasp. The link has been broken.")
if(target) //Wait, target is WHERE NOW?
diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm
index a87a518d7f5dc..5ac98e68db402 100644
--- a/code/modules/antagonists/revenant/revenant_blight.dm
+++ b/code/modules/antagonists/revenant/revenant_blight.dm
@@ -30,7 +30,7 @@
..()
affected_mob.adjustStaminaLoss(1) //Provides gradual exhaustion, but mostly to prevent regeneration and set an upper limit on disease duration to about five minutes
if(!(affected_mob.mobility_flags & MOBILITY_STAND))
- if(affected_mob.stam_paralyzed && !finalstage)
+ if(HAS_TRAIT_FROM(affected_mob, TRAIT_INCAPACITATED, STAMINA) && !finalstage)
stage = 5
if(!startresting || restingat != get_turf(affected_mob))
startresting = world.time
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index fc7269fbf6afb..b16db081ffad9 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -154,11 +154,12 @@
/mob/living/simple_animal/slaughter/laughter/ex_act(severity)
switch(severity)
- if(1)
+ if(EXPLODE_DEVASTATE)
+ investigate_log("has died from a devastating explosion.", INVESTIGATE_DEATHS)
death()
- if(2)
+ if(EXPLODE_HEAVY)
adjustBruteLoss(60)
- if(3)
+ if(EXPLODE_LIGHT)
adjustBruteLoss(30)
/mob/living/simple_animal/slaughter/laughter/proc/release_friends()
diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
index a6ac41c762e78..f184949b58fe5 100644
--- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
+++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
@@ -391,6 +391,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
if(issilicon(L))
continue
to_chat(L, "The blast wave from [src] tears you atom from atom!")
+ L.investigate_log("has been dusted by a doomsday device.", INVESTIGATE_DEATHS)
L.dust()
to_chat(world, "The AI cleansed the station of life with the Doomsday device!")
SSticker.force_ending = 1
@@ -412,7 +413,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
turret.max_integrity = 200
turret.obj_integrity = 200
turret.emp_proofing = TRUE
- turret.AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_CONTENTS | EMP_PROTECT_WIRES)
+ turret.AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS)
turret.stun_projectile = /obj/projectile/beam/disabler/pass_glass //// AI defenses are often built with glass, so this is big.
turret.stun_projectile_sound = 'sound/weapons/lasercannonfire.ogg'
turret.lethal_projectile = /obj/projectile/beam/laser/heavylaser //Once you see it, you will know what it means to FEAR.
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 8e1aa524513bc..cdb3511ea8235 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -147,6 +147,7 @@
return
C.vomit(0, TRUE, TRUE, 3, TRUE)
C.spew_organ(3, 2)
+ C.investigate_log("has died from using telekinesis on a tear in reality.", INVESTIGATE_DEATHS)
C.death()
/obj/tear_in_reality/Bump(atom/A)
@@ -415,7 +416,7 @@
/obj/item/voodoo/suicide_act(mob/living/carbon/user)
user.visible_message("[user] links the voodoo doll to [user.p_them()]self and sits on it, infinitely crushing [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!")
user.gib()
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/voodoo/fire_act(exposed_temperature, exposed_volume)
if(target)
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index 1ed13726a57bd..c4e3a6e1b1347 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -36,9 +36,7 @@
else
user.visible_message("[user]'s [src] receives a signal and [user.p_they()] die[user.p_s()] like a gamer!")
user.adjustOxyLoss(200)//it sends an electrical pulse to their heart, killing them. or something.
- user.death(0)
- user.set_suicide(TRUE)
- user.suicide_log()
+ user.death(FALSE)
playsound(user, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
qdel(src)
@@ -204,7 +202,6 @@
/obj/item/assembly/signaler/anomaly/manual_suicide(mob/living/carbon/user)
user.visible_message("[user]'s [src] is reacting to the radio signal, warping [user.p_their()] body!")
user.set_suicide(TRUE)
- user.suicide_log()
user.gib()
/obj/item/assembly/signaler/anomaly/attackby(obj/item/I, mob/user, params)
diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm
index e6ffbfcba0d40..830a8c32f8efc 100644
--- a/code/modules/assembly/timer.dm
+++ b/code/modules/assembly/timer.dm
@@ -21,7 +21,7 @@
/obj/item/assembly/timer/proc/manual_suicide(mob/living/user)
user.visible_message("[user]'s time is up!")
user.adjustOxyLoss(200)
- user.death(0)
+ user.death(FALSE)
/obj/item/assembly/timer/Initialize(mapload)
. = ..()
diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
index 756161ee84ef6..5af7263477686 100644
--- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
+++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
@@ -225,7 +225,7 @@
/turf/proc/handle_decompression_floor_rip()
/turf/open/floor/handle_decompression_floor_rip(sum)
- if(sum > 20 && prob(CLAMP(sum / 20, 0, 15)))
+ if(sum > 20 && prob(clamp(sum / 20, 0, 15)))
if(floor_tile)
new floor_tile(src)
make_plating()
@@ -277,13 +277,13 @@
move_prob = (pressure_difference/pressure_resistance*PROBABILITY_BASE_PRECENT)-PROBABILITY_OFFSET
move_prob += pressure_resistance_prob_delta
if(move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO))))
- var/move_force = max_force * CLAMP(move_prob, 0, 100) / 100
+ var/move_force = max_force * clamp(move_prob, 0, 100) / 100
if(move_force > 6000)
// WALLSLAM HELL TIME OH BOY
var/turf/throw_turf = get_ranged_target_turf(get_turf(src), direction, round(move_force / 2000))
if(throw_target && (get_dir(src, throw_target) & direction))
throw_turf = get_turf(throw_target)
- var/throw_speed = CLAMP(round(move_force / 3000), 1, 10)
+ var/throw_speed = clamp(round(move_force / 3000), 1, 10)
throw_at(throw_turf, move_force / 3000, throw_speed)
else
step(src, direction)
diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm
index 43c7b983ff0bd..23e7c52f50a80 100644
--- a/code/modules/atmospherics/gasmixtures/reactions.dm
+++ b/code/modules/atmospherics/gasmixtures/reactions.dm
@@ -600,5 +600,5 @@
if(energy_released)
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.set_temperature(CLAMP((air.return_temperature()*old_heat_capacity + energy_released)/new_heat_capacity,TCMB,INFINITY))
+ air.set_temperature(clamp((air.return_temperature()*old_heat_capacity + energy_released)/new_heat_capacity,TCMB,INFINITY))
return REACTING
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index 2a7638cd6222a..e8f3d97f87275 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -316,6 +316,8 @@
if(world.time - user.last_played_vent > VENT_SOUND_DELAY)
user.last_played_vent = world.time
playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3)
+ if(prob(1))
+ audible_message("You hear something crawling through the ducts...")
else if(is_type_in_typecache(src, GLOB.ventcrawl_machinery) && can_crawl_through()) //if we move in a way the pipe can connect, but doesn't - or we're in a vent
user.forceMove(loc)
user.visible_message("You hear something squeezing through the ducts...", "You climb out the ventilation system.")
@@ -328,7 +330,7 @@
L.handle_ventcrawl(src)
return
-
+/// Whether ventcrawling creatures can move in or out of this machine.
/obj/machinery/atmospherics/proc/can_crawl_through()
return TRUE
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
index 2e4a86b9f0149..298b46b58133d 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
@@ -164,13 +164,13 @@
pump_direction = 1
if("set_input_pressure" in signal.data)
- input_pressure_min = CLAMP(text2num(signal.data["set_input_pressure"]),0,ONE_ATMOSPHERE*50)
+ input_pressure_min = clamp(text2num(signal.data["set_input_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_output_pressure" in signal.data)
- output_pressure_max = CLAMP(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
+ output_pressure_max = clamp(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_external_pressure" in signal.data)
- external_pressure_bound = CLAMP(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
+ external_pressure_bound = clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
if("status" in signal.data)
spawn(2)
@@ -202,7 +202,7 @@
. += "It seems welded shut."
/obj/machinery/atmospherics/components/binary/dp_vent_pump/can_crawl_through()
- return !welded
+ return !(machine_stat & BROKEN) && !welded
/obj/machinery/atmospherics/components/binary/dp_vent_pump/attack_alien(mob/user)
if(!welded || !(do_after(user, 20, target = src)))
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
index a4152557933bd..7496fa99b06d6 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
@@ -177,6 +177,8 @@
to_chat(user, "You cannot unwrench [src], turn it off first!")
return FALSE
+/obj/machinery/atmospherics/components/binary/pump/can_crawl_through()
+ return on // If a pump is off, it'll block even when not powered
/obj/machinery/atmospherics/components/binary/pump/layer2
piping_layer = 2
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm
index fd6d447f8c2fe..d751f7f9dad35 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm
@@ -40,6 +40,9 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
flick("[valve_type]valve_[on][!on]-[set_overlay_offset(piping_layer)]", src)
icon_state = "[valve_type]valve_[on ? "on" : "off"]-[set_overlay_offset(piping_layer)]"
+/obj/machinery/atmospherics/components/binary/valve/can_crawl_through()
+ return !(machine_stat & BROKEN) && on // valves should block whatever is trying to go through them, regardless of power
+
/**
* Called by finish_interact(), switch between open and closed, reconcile the air between two pipelines
*/
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
index 72567fed7d644..638527e13f1cf 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
@@ -166,7 +166,7 @@
if("set_transfer_rate" in signal.data)
var/datum/gas_mixture/air1 = airs[1]
- transfer_rate = CLAMP(text2num(signal.data["set_transfer_rate"]),0,air1.return_volume())
+ transfer_rate = clamp(text2num(signal.data["set_transfer_rate"]),0,air1.return_volume())
if(on != old_on)
investigate_log("was turned [on ? "on" : "off"] by a remote signal", INVESTIGATE_ATMOS)
@@ -194,6 +194,9 @@
to_chat(user, "The pump quiets down as you turn its limiters back on.")
return TRUE
+/obj/machinery/atmospherics/components/binary/volume_pump/can_crawl_through()
+ return on
+
// mapping
/obj/machinery/atmospherics/components/binary/volume_pump/layer2
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index b0b41bc67b8b9..13a0f189ff778 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -455,7 +455,7 @@
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
/obj/machinery/atmospherics/components/unary/cryo_cell/can_crawl_through()
- return // can't ventcrawl in or out of cryo.
+ return FALSE // can't ventcrawl in or out of cryo.
/obj/machinery/atmospherics/components/unary/cryo_cell/can_see_pipes()
return 0 // you can't see the pipe network when inside a cryo cell.
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
index 1c4789c306ef2..47a12d462d568 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
@@ -133,7 +133,7 @@
if("set_volume_rate" in signal.data)
var/number = text2num(signal.data["set_volume_rate"])
var/datum/gas_mixture/air_contents = airs[1]
- volume_rate = CLAMP(number, 0, air_contents.return_volume())
+ volume_rate = clamp(number, 0, air_contents.return_volume())
addtimer(CALLBACK(src, PROC_REF(broadcast_status)), 2)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
index adfe8079bab1e..1fa5221e38eac 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
@@ -42,7 +42,7 @@
update_parents()
/obj/machinery/atmospherics/components/unary/passive_vent/can_crawl_through()
- return TRUE
+ return TRUE // we don't care about power or being broken
/obj/machinery/atmospherics/components/unary/passive_vent/layer2
piping_layer = 2
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index c2da6f4ad18d8..1168685df2b64 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -219,13 +219,13 @@
if("set_internal_pressure" in signal.data)
var/old_pressure = internal_pressure_bound
- internal_pressure_bound = CLAMP(text2num(signal.data["set_internal_pressure"]),0,ONE_ATMOSPHERE*50)
+ internal_pressure_bound = clamp(text2num(signal.data["set_internal_pressure"]),0,ONE_ATMOSPHERE*50)
if(old_pressure != internal_pressure_bound)
investigate_log(" internal pressure was set to [internal_pressure_bound] by [key_name(signal_sender)]",INVESTIGATE_ATMOS)
if("set_external_pressure" in signal.data)
var/old_pressure = external_pressure_bound
- external_pressure_bound = CLAMP(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
+ external_pressure_bound = clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
if(old_pressure != external_pressure_bound)
investigate_log(" external pressure was set to [external_pressure_bound] by [key_name(signal_sender)]",INVESTIGATE_ATMOS)
@@ -236,10 +236,10 @@
internal_pressure_bound = 0
if("adjust_internal_pressure" in signal.data)
- internal_pressure_bound = CLAMP(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),0,ONE_ATMOSPHERE*50)
+ internal_pressure_bound = clamp(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),0,ONE_ATMOSPHERE*50)
if("adjust_external_pressure" in signal.data)
- external_pressure_bound = CLAMP(external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),0,ONE_ATMOSPHERE*50)
+ external_pressure_bound = clamp(external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),0,ONE_ATMOSPHERE*50)
if("init" in signal.data)
name = signal.data["init"]
@@ -280,13 +280,13 @@
if(welded)
. += "It seems welded shut."
+/obj/machinery/atmospherics/components/unary/vent_pump/can_crawl_through()
+ return !(machine_stat & BROKEN) && !welded
+
/obj/machinery/atmospherics/components/unary/vent_pump/power_change()
. = ..()
update_icon_nopipes()
-/obj/machinery/atmospherics/components/unary/vent_pump/can_crawl_through()
- return !welded
-
/obj/machinery/atmospherics/components/unary/vent_pump/attack_alien(mob/user)
if(!welded || !(do_after(user, 20, target = src)))
return
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index 66b71df3eb503..1f11984bee46b 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -260,7 +260,7 @@
. += "It seems welded shut."
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through()
- return !welded
+ return !(machine_stat & BROKEN) && !welded
/obj/machinery/atmospherics/components/unary/vent_scrubber/attack_alien(mob/user)
if(!welded || !(do_after(user, 20, target = src)))
diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm
index 8e6223551b6af..a7c18ebc430a5 100644
--- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm
+++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm
@@ -130,9 +130,9 @@
if(initialize_directions & dir)
return ..()
if((NORTH|EAST) & dir)
- user.ventcrawl_layer = CLAMP(user.ventcrawl_layer + 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
+ user.ventcrawl_layer = clamp(user.ventcrawl_layer + 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
if((SOUTH|WEST) & dir)
- user.ventcrawl_layer = CLAMP(user.ventcrawl_layer - 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
+ user.ventcrawl_layer = clamp(user.ventcrawl_layer - 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
to_chat(user, "You align yourself with the [user.ventcrawl_layer]\th output.")
/obj/machinery/atmospherics/pipe/layer_manifold/visible
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index e602f3b17804b..a3af0fd37d364 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -591,6 +591,7 @@
return
if(!(src.team in L.faction))
to_chat(L, "Stay out of the enemy spawn!")
+ L.investigate_log("has died from entering the enemy spawn in CTF.", INVESTIGATE_DEATHS)
L.death()
/obj/structure/trap/ctf/red
diff --git a/code/modules/awaymissions/mission_code/challenge.dm b/code/modules/awaymissions/mission_code/challenge.dm
index 73c3eea8d800d..4df8fbf32f894 100644
--- a/code/modules/awaymissions/mission_code/challenge.dm
+++ b/code/modules/awaymissions/mission_code/challenge.dm
@@ -30,7 +30,7 @@
active = TRUE
locked = TRUE
- state = 2
+ welded = TRUE
/obj/machinery/power/emitter/energycannon/RefreshParts()
return
diff --git a/code/modules/cargo/bounties/chef.dm b/code/modules/cargo/bounties/chef.dm
index a4405e20943d2..0847416702ed6 100644
--- a/code/modules/cargo/bounties/chef.dm
+++ b/code/modules/cargo/bounties/chef.dm
@@ -43,7 +43,7 @@
name = "Bread"
description = "Problems with central planning have led to bread prices skyrocketing. Ship some bread to ease tensions."
reward = 1000
- wanted_types = list(/obj/item/food/bread, /obj/item/food/breadslice, /obj/item/reagent_containers/food/snacks/bun, /obj/item/reagent_containers/food/snacks/pizzabread, /obj/item/reagent_containers/food/snacks/rawpastrybase)
+ wanted_types = list(/obj/item/food/bread, /obj/item/food/breadslice, /obj/item/food/bun, /obj/item/food/pizzabread, /obj/item/food/rawpastrybase)
/datum/bounty/item/chef/pie
name = "Pie"
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 014f4147dc900..2175bd891b559 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -473,7 +473,7 @@
/datum/supply_pack/security/vending/security
name = "SecTech Supply Crate"
- desc = "Officer Paul bought all the donuts? Then refill the security vendor with ths crate."
+ desc = "Officer Paul bought all the handcuffs? Then refill the security vendor with ths crate."
cost = 1200
max_supply = 3
contains = list(/obj/item/vending_refill/security)
diff --git a/code/modules/client/loadout/loadout_general.dm b/code/modules/client/loadout/loadout_general.dm
index 575e800f7636e..35aa804d73e00 100644
--- a/code/modules/client/loadout/loadout_general.dm
+++ b/code/modules/client/loadout/loadout_general.dm
@@ -16,6 +16,12 @@
path = /obj/item/toy/eightball
cost = 500
+/datum/gear/misc/tarotdeck
+ display_name = "Tarot Deck"
+ description = "A full 78 card deck of Tarot Cards, no refunds on false predicitons."
+ path = /obj/item/toy/cards/deck/tarot
+ cost = 600
+
/datum/gear/misc/antagtoken
display_name = "Discount Antag Token"
description = "Says \"Made in China\" on the back. Seems fishy."
diff --git a/code/modules/client/preferences/middleware/antags.dm b/code/modules/client/preferences/middleware/antags.dm
index 909b2e8191666..b778531ba1366 100644
--- a/code/modules/client/preferences/middleware/antags.dm
+++ b/code/modules/client/preferences/middleware/antags.dm
@@ -80,10 +80,13 @@
var/any_changed = FALSE
for (var/sent_antag in sent_antags)
if(!(sent_antag in valid_antags))
+ log_preferences("[preferences?.parent?.ckey]: WARN - Filtered role preference edit for [sent_antag] to [toggled] due to being invalid.")
continue
if(per_character)
+ log_preferences("[preferences?.parent?.ckey]: Set per-character role preference for [sent_antag] to [toggled].")
preferences.role_preferences["[sent_antag]"] = toggled
else
+ log_preferences("[preferences?.parent?.ckey]: Set global role preference for [sent_antag] to [toggled].")
preferences.role_preferences_global["[sent_antag]"] = toggled
any_changed = TRUE
if(any_changed)
diff --git a/code/modules/client/preferences/middleware/keybindings.dm b/code/modules/client/preferences/middleware/keybindings.dm
index ba17ee71683be..4c06684595967 100644
--- a/code/modules/client/preferences/middleware/keybindings.dm
+++ b/code/modules/client/preferences/middleware/keybindings.dm
@@ -27,6 +27,7 @@
/datum/preference_middleware/keybindings/proc/reset_all_keybinds(list/params, mob/user)
preferences.set_default_key_bindings(save = TRUE) // this also updates special keybinds
preferences.update_static_data(user)
+ log_preferences("[preferences?.parent?.ckey]: Reset all keybinds.")
return TRUE
/datum/preference_middleware/keybindings/proc/reset_keybinds_to_defaults(list/params, mob/user)
diff --git a/code/modules/client/preferences/middleware/loadout.dm b/code/modules/client/preferences/middleware/loadout.dm
index aab738899f3ec..b3de622c806ab 100644
--- a/code/modules/client/preferences/middleware/loadout.dm
+++ b/code/modules/client/preferences/middleware/loadout.dm
@@ -58,6 +58,7 @@
preferences.purchased_gear += TG.id
TG.purchase(user.client)
user.client.inc_metabalance((TG.cost * -1), TRUE, "Purchased [TG.display_name].")
+ log_preferences("[preferences?.parent?.ckey]: Purchased loadout gear: [TG.id] ([TG.display_name])")
preferences.mark_undatumized_dirty_player()
return TRUE
else
@@ -69,6 +70,7 @@
return
if(TG.id in preferences.equipped_gear)
preferences.equipped_gear -= TG.id
+ log_preferences("[preferences?.parent?.ckey]: Unequipped loadout gear: [TG.id] ([TG.display_name])")
preferences.character_preview_view?.update_body()
preferences.mark_undatumized_dirty_character()
return TRUE
@@ -85,6 +87,7 @@
if((TG.id in preferences.purchased_gear))
if(!(TG.subtype_path in type_blacklist) || !(TG.slot in slot_blacklist))
preferences.equipped_gear += TG.id
+ log_preferences("[preferences?.parent?.ckey]: Equipped loadout gear: [TG.id] ([TG.display_name])")
preferences.character_preview_view?.update_body()
preferences.mark_undatumized_dirty_character()
return TRUE
diff --git a/code/modules/client/preferences/middleware/names.dm b/code/modules/client/preferences/middleware/names.dm
index 4f9e716a2e304..e1d9930edd1ab 100644
--- a/code/modules/client/preferences/middleware/names.dm
+++ b/code/modules/client/preferences/middleware/names.dm
@@ -53,4 +53,5 @@
if (!istype(name_preference))
return FALSE
+ log_preferences("[preferences?.parent?.ckey]: Randomized name preference [name_preference.type]")
return preferences.update_preference(name_preference, name_preference.create_random_value(preferences), in_menu = TRUE)
diff --git a/code/modules/client/preferences/middleware/quirks.dm b/code/modules/client/preferences/middleware/quirks.dm
index 874afb70103d7..0a5269ab2ff9a 100644
--- a/code/modules/client/preferences/middleware/quirks.dm
+++ b/code/modules/client/preferences/middleware/quirks.dm
@@ -34,11 +34,14 @@
for (var/quirk_name in quirks)
var/datum/quirk/quirk = quirks[quirk_name]
+ if(!ispath(quirk))
+ CRASH("Error: invalid quirk value in quirks for quirk_name [quirk_name]: [quirk]")
quirk_info[sanitize_css_class_name(quirk_name)] = list(
"description" = initial(quirk.desc),
"icon" = initial(quirk.icon),
"name" = quirk_name,
"value" = initial(quirk.value),
+ "path" = quirk
)
return list(
diff --git a/code/modules/client/preferences/middleware/random.dm b/code/modules/client/preferences/middleware/random.dm
index cbf7ec927b9ed..1b7d5149e2ef9 100644
--- a/code/modules/client/preferences/middleware/random.dm
+++ b/code/modules/client/preferences/middleware/random.dm
@@ -25,6 +25,7 @@
)
/datum/preference_middleware/random/proc/randomize_character()
+ log_preferences("[preferences?.parent?.ckey]: Force randomized their character.")
for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
if (preferences.should_randomize(preference))
preferences.write_preference(preference, preference.create_random_value(preferences))
@@ -44,6 +45,8 @@
if (!requested_preference.is_randomizable())
return FALSE
+ log_preferences("[preferences?.parent?.ckey]: Set randomization for [requested_preference.type] to [value].")
+
if (value == RANDOM_ANTAG_ONLY)
preferences.randomize[requested_preference_key] = RANDOM_ANTAG_ONLY
else if (value == RANDOM_ENABLED)
diff --git a/code/modules/client/preferences/preference_entry.dm b/code/modules/client/preferences/preference_entry.dm
index 6464d229af1e4..49ee69d77e192 100644
--- a/code/modules/client/preferences/preference_entry.dm
+++ b/code/modules/client/preferences/preference_entry.dm
@@ -181,9 +181,12 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
/datum/preferences/proc/get_preference_holder(datum/preference/preference_entry)
RETURN_TYPE(/datum/preferences_holder)
- if(preference_entry.preference_type == PREFERENCE_CHARACTER)
- return character_data
- return player_data
+ switch(preference_entry.preference_type)
+ if(PREFERENCE_CHARACTER)
+ return character_data
+ if(PREFERENCE_PLAYER)
+ return player_data
+ return null
/// Read a /datum/preference type and return its value, only using cached values and queueing any necessary writes.
/datum/preferences/proc/read_preference(preference_typepath)
@@ -213,8 +216,8 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
CRASH("Preference type `[preference_typepath]` is invalid! [extra_info]")
- if (preference_entry.preference_type == PREFERENCE_CHARACTER)
- CRASH("read_player_preference called on PREFERENCE_CHARACTER type preference [preference_typepath].")
+ if (preference_entry.preference_type != PREFERENCE_PLAYER)
+ CRASH("read_player_preference called on [preference_entry.preference_type] type preference [preference_typepath].")
return player_data.read_preference(src, preference_entry)
@@ -232,9 +235,8 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
CRASH("Preference type `[preference_typepath]` is invalid! [extra_info]")
- if (preference_entry.preference_type == PREFERENCE_PLAYER)
- CRASH("read_character_preference called on PREFERENCE_PLAYER type preference [preference_typepath].")
-
+ if (preference_entry.preference_type != PREFERENCE_CHARACTER)
+ CRASH("read_character_preference called on [preference_entry.preference_type] type preference [preference_typepath].")
return character_data.read_preference(src, preference_entry)
/// Set a /datum/preference entry.
@@ -258,8 +260,12 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
if (!preference.is_accessible(src, ignore_page = !in_menu))
return FALSE
+ log_preferences("[parent.ckey]: Updating preference [preference.type] TO \"[preference_value]\".")
+
write_preference(preference, preference_value)
+ log_preferences("[parent.ckey]: Applying updated preference [preference.type].")
+
if (preference.preference_type == PREFERENCE_PLAYER)
preference.apply_to_client_updated(parent, read_preference(preference.type))
else
diff --git a/code/modules/client/preferences/preferences.dm b/code/modules/client/preferences/preferences.dm
index ee25bb082ee68..59b14eff55779 100644
--- a/code/modules/client/preferences/preferences.dm
+++ b/code/modules/client/preferences/preferences.dm
@@ -106,6 +106,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
qdel(src)
return
src.parent = parent
+ log_preferences("[parent.ckey]: Preferences datum created.")
for (var/middleware_type in subtypesof(/datum/preference_middleware))
middleware += new middleware_type(src)
@@ -115,6 +116,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
unlock_content = !!parent.IsByondMember()
if(unlock_content)
max_save_slots = 8
+ log_preferences("[parent.ckey]: Checked BYOND membership: [unlock_content ? "MEMBER" : "NONMEMBER"].")
else
CRASH("attempted to create a preferences datum without a client!")
@@ -124,43 +126,66 @@ GLOBAL_LIST_EMPTY(preferences_datums)
save_locked = TRUE
- var/loaded_preferences_successfully = load_preferences()
- if(loaded_preferences_successfully)
+ var/pref_load = load_preferences()
+ var/char_load
+ if(pref_load == PREFERENCE_LOAD_SUCCESS || pref_load == PREFERENCE_LOAD_NO_DATA)
+ log_preferences("[parent?.ckey]: Player preferences loaded and applied.")
if("6030fe461e610e2be3a2c3e75c06067e" in purchased_gear) //MD5 hash of, "extra character slot"
max_save_slots += 1
- if(load_character()) // This returns true if there is a database and character in the active slot.
- // Get the profile data
- fetch_character_profiles()
- create_character_preview_view()
- save_locked = FALSE
- return
- // Begin no database / new player logic. This ONLY fires if there is an SQL error or no database / the player and character is new.
+ // Apply the loaded preferences!!
+ if(istype(parent))
+ apply_all_client_preferences()
+ char_load = load_character()
+ else if(istype(parent) && istype(player_data)) // defaults should already exist because player_data generates them
+ log_preferences("[parent?.ckey]: Player preferences generated and applied.")
+ apply_all_client_preferences()
+ else // Ok what the fuck - abort mission
+ log_preferences("[parent?.ckey]: ERROR - Player preferences FAILED to load or apply. DELETING.")
+ save_locked = FALSE
+ qdel(src) // this will also remove us from the write queue
+ return
- if(!loaded_preferences_successfully) // create a new character object
+ // character_data is null, so we need to just set it up manually with defaults.
+ // This means either there is no DB or we are a guest key.
+ if(pref_load == PREFERENCE_LOAD_IGNORE)
+ log_preferences("[parent?.ckey]: Applying guest character preferences.")
character_data = new(src, default_slot)
- // Get the profile data
- fetch_character_profiles()
+ character_data.provide_defaults(src, should_use_informed = FALSE)
+
+ // New player or guest/no DB. Use the fallback species
+ if(pref_load == PREFERENCE_LOAD_IGNORE || pref_load == PREFERENCE_LOAD_NO_DATA)
+ log_preferences("[parent?.ckey]: Applying fallback species.")
var/new_species_path = GLOB.species_list[get_fallback_species_id() || "human"]
character_data.write_preference(src, GLOB.preference_entries[/datum/preference/choiced/species], new_species_path)
- // We couldn't load character data so just randomize the character appearance
- randomize_appearance_prefs()
- if(parent)
- apply_all_client_preferences() // apply now since normally this is done in load_preferences(). Defaults were set in preferences_player
- // The character name is fresh, update the character list.
- update_current_character_profile()
+ // If the character is fresh in any way, we need to randomize it.
+ var/fresh_character = pref_load == PREFERENCE_LOAD_IGNORE || char_load == PREFERENCE_LOAD_IGNORE || char_load == PREFERENCE_LOAD_NO_DATA
+ if(fresh_character)
+ log_preferences("[parent?.ckey]: New character created - randomizing appearance.")
+ randomize_appearance_prefs()
+
+ // Provide informed defaults for guests/no DB - these depend on other preferences, so we do that after randomizing.
+ if(pref_load == PREFERENCE_LOAD_IGNORE)
+ character_data.provide_defaults(src, should_use_informed = TRUE)
+
+ // Get character profiles, since they haven't been fetched at all yet
+ fetch_character_profiles()
+ // The database won't have the correct name yet, so manually load it, if it changed.
+ if(fresh_character)
+ update_current_character_profile()
create_character_preview_view()
save_locked = FALSE
// If this was a NEW CKEY ENTRY, and not a guest key (handled in save_preferences()), save it.
// Guest keys are ignored by mark_undatumized_dirty
- if(!loaded_preferences_successfully)
+ if(pref_load == PREFERENCE_LOAD_NO_DATA)
// This will essentially force a write, while also using the queueing system.
// For new ckeys, it is almost guaranteed we already hit the queue, since write_preference (used for when a datumized entry is null)
// Will also queue the CKEY. But this will also ensure that undatumized prefs get written.
mark_undatumized_dirty_player()
- mark_undatumized_dirty_character()
+ if(char_load == PREFERENCE_LOAD_NO_DATA)
+ mark_undatumized_dirty_character()
/datum/preferences/ui_interact(mob/user, datum/tgui/ui)
// IMPORTANT: If someone opens the prefs menu before jobs load, then the jobs menu will be empty for everyone.
@@ -249,18 +274,23 @@ GLOBAL_LIST_EMPTY(preferences_datums)
/// No switching slots during a save
if(save_locked)
return
+ log_preferences("[parent?.ckey]: Slot change event from [default_slot] to [new_slot].")
save_locked = TRUE
// Save previous character (immediately, delaying this could mean data is lost)
save_character()
// SAFETY: `load_character` performs sanitization the slot number
- if (!load_character(new_slot))
+ var/character_load_result = load_character(new_slot)
+
+ if (character_load_result == PREFERENCE_LOAD_NO_DATA || character_load_result == PREFERENCE_LOAD_IGNORE)
+ log_preferences("[parent?.ckey]: Generating new character in new slot [new_slot].")
// there is no character in the slot. Make a new one. Save it.
update_current_character_profile()
randomize_appearance_prefs()
+ if(character_load_result == PREFERENCE_LOAD_NO_DATA)
// Queue an undatumized save, just in case (it's likely already queued, but we should write undatumized data as well)
mark_undatumized_dirty_character()
-
+ log_preferences("[parent?.ckey]: Slot change complete.")
for (var/datum/preference_middleware/preference_middleware as anything in middleware)
preference_middleware.on_new_character(usr)
@@ -382,6 +412,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
/// Applies all PREFERENCE_PLAYER preferences immediately
/datum/preferences/proc/apply_all_client_preferences()
+ log_preferences("[parent?.ckey]: Applying client preferences.")
for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
if (preference.preference_type != PREFERENCE_PLAYER)
continue
@@ -391,6 +422,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
/datum/preferences/proc/update_current_character_profile()
if(!islist(character_profiles_cached))
return
+ log_preferences("[parent?.ckey]: Updating cached character profile.")
character_profiles_cached[default_slot] = read_character_preference(/datum/preference/name/real_name)
/// Immediately refetch the character list
@@ -398,7 +430,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character_data.get_all_character_names(src)
/// Applies the given preferences to a human mob.
-/datum/preferences/proc/apply_prefs_to(mob/living/carbon/human/character, icon_updates = TRUE)
+/datum/preferences/proc/apply_prefs_to(mob/living/carbon/human/character, icon_updates = TRUE, log = TRUE)
+ if(log)
+ log_preferences("[parent?.ckey]: Applying character preferences to mob [key_name(character)] ([REF(character)]).")
character.dna.features = list()
for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
diff --git a/code/modules/client/preferences/serialization/preferences_character.dm b/code/modules/client/preferences/serialization/preferences_character.dm
index eab3a87bec608..5bdaebf54c7ab 100644
--- a/code/modules/client/preferences/serialization/preferences_character.dm
+++ b/code/modules/client/preferences/serialization/preferences_character.dm
@@ -1,5 +1,6 @@
/// A cache for character preferences data
/datum/preferences_holder/preferences_character
+ pref_type = PREFERENCE_CHARACTER
/// INT: Slot number. Used for internal tracking. The slot number also correspnds to the number of slots in the characters list
var/slot_number = 0
/// List of column names to be queried
@@ -17,23 +18,10 @@
column_names = get_column_names()
..(prefs)
-/datum/preferences_holder/preferences_character/proc/load_from_database(datum/preferences/prefs)
- if(IS_GUEST_KEY(prefs.parent.key) || !query_data(prefs)) // Query direct, otherwise create informed defaults
- for (var/preference_type in GLOB.preference_entries)
- var/datum/preference/preference = GLOB.preference_entries[preference_type]
- if (preference.preference_type != pref_type)
- continue
- preference_data[preference.db_key] = preference.deserialize(preference.create_informed_default_value(prefs), prefs)
- return FALSE
- if(!istype(prefs.parent)) // Client was nulled during query execution
- return FALSE
- return TRUE
-
-/datum/preferences_holder/preferences_character/proc/query_data(datum/preferences/prefs)
- if(!SSdbcore.IsConnected())
- return FALSE
- if(!istype(prefs.parent))
- return FALSE
+/datum/preferences_holder/preferences_character/query_data(datum/preferences/prefs)
+ . = ..()
+ if(. != PREFERENCE_LOAD_SUCCESS)
+ return .
var/list/values
var/datum/DBQuery/Q = SSdbcore.NewQuery(
"SELECT [db_column_list(column_names)] FROM [format_table_name("characters")] WHERE ckey=:ckey AND slot=:slot",
@@ -41,59 +29,67 @@
)
if(!Q.warn_execute())
qdel(Q)
- return FALSE
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized character preferences load query failed.")
+ return PREFERENCE_LOAD_ERROR
if(Q.NextRow())
values = Q.item
if(!length(values)) // There is no character
qdel(Q)
- return FALSE
+ log_preferences("[prefs.parent.ckey]: Datumized character preferences load found no results in row.")
+ return PREFERENCE_LOAD_NO_DATA
else
qdel(Q)
- return FALSE
+ log_preferences("[prefs.parent.ckey]: Datumized character preferences load found no rows.")
+ return PREFERENCE_LOAD_NO_DATA
qdel(Q)
if(length(values) != length(column_names))
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized character preferences load found the wrong amount of columns.")
CRASH("Error querying character data: the returned value length is not equal to the number of columns requested.")
for(var/index in 1 to length(values))
var/db_key = column_names[index]
var/datum/preference/preference = GLOB.preference_entries_by_key[db_key]
if(!istype(preference))
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized character preferences failed to find preference column [db_key] in game, but it was in the database.")
CRASH("Could not find preference with db_key [db_key] when querying database.")
var/value = values[index]
preference_data[db_key] = isnull(value) ? null : preference.deserialize(value, prefs)
- return TRUE
-
-/datum/preferences_holder/preferences_character/proc/write_to_database(datum/preferences/prefs)
- . = write_data(prefs)
- dirty_prefs.Cut() // clear all dirty preferences
+ log_preferences("[prefs.parent.ckey]: Successfully loaded datumized character preferences.")
+ return PREFERENCE_LOAD_SUCCESS
-/datum/preferences_holder/preferences_character/proc/write_data(datum/preferences/prefs)
- if(!SSdbcore.IsConnected() || !istype(prefs.parent) || IS_GUEST_KEY(prefs.parent.key))
- return FALSE
+/datum/preferences_holder/preferences_character/write_data(datum/preferences/prefs)
+ . = ..()
+ if(. != PREFERENCE_LOAD_SUCCESS)
+ return .
var/list/column_names_short = list()
var/list/new_data = list()
for(var/db_key in dirty_prefs)
if(!(db_key in preference_data))
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized character preferences write found invalid db_key [db_key] in dirty preferences list.")
CRASH("Invalid db_key found in dirty preferences list: [db_key].")
var/datum/preference/preference = GLOB.preference_entries_by_key[db_key]
if(!istype(preference))
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized character preferences write found invalid db_key [db_key] in dirty preferences list (2).")
CRASH("Could not find preference with db_key [db_key] when writing to database.")
+ if(preference.preference_type != pref_type)
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized character preferences write found invalid preference type [preference.preference_type] for [db_key] (want [pref_type]).")
+ CRASH("Invalid preference located from db_key [db_key] for the preference type [pref_type] (had [preference.preference_type])")
new_data[db_key] = preference.serialize(preference_data[db_key])
var/column_name = clean_column_name(preference)
if(length(column_name))
column_names_short += column_name
if(!length(column_names_short)) // nothing to update
- return TRUE
+ log_preferences("[prefs.parent.ckey]: Datumized character preferences write - no columns to write.")
+ return PREFERENCE_LOAD_NO_DATA
new_data["ckey"] = prefs.parent.ckey
new_data["slot"] = slot_number
var/datum/DBQuery/Q = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("characters")] (ckey, slot, [db_column_list(column_names_short)]) VALUES (:ckey, :slot, [db_column_list(column_names_short, TRUE)]) ON DUPLICATE KEY UPDATE [db_column_values(column_names_short)]", new_data
)
var/success = Q.warn_execute()
- if(!success)
- to_chat(prefs.parent, "Failed to save your character. Please inform the server operator or a maintainer of this error.")
qdel(Q)
prefs.fail_state = success
- return success
+ log_preferences("[prefs.parent.ckey]: Datumized character preferences write result [success ? "GOOD" : "ERROR"].")
+ return success ? PREFERENCE_LOAD_SUCCESS : PREFERENCE_LOAD_ERROR
/datum/preferences_holder/preferences_character/proc/get_column_names()
var/list/result = list()
@@ -168,6 +164,7 @@
)
if(!Q.warn_execute())
qdel(Q)
+ log_preferences("[prefs.parent.ckey]: ERROR - SQL error while retrieving character profiles.")
CRASH("An SQL error occurred while retrieving character profile data.")
var/list/data = list()
for(var/index in 1 to TRUE_MAX_SAVE_SLOTS)
@@ -185,3 +182,4 @@
data[values[1]] = values[2] // data[1] = "John Smith"
qdel(Q)
prefs.character_profiles_cached = data
+ log_preferences("[prefs.parent.ckey]: Successfully retrieved character profiles.")
diff --git a/code/modules/client/preferences/serialization/preferences_database.dm b/code/modules/client/preferences/serialization/preferences_database.dm
index e3e26d6ebaa07..2f5e92ff949bc 100644
--- a/code/modules/client/preferences/serialization/preferences_database.dm
+++ b/code/modules/client/preferences/serialization/preferences_database.dm
@@ -8,6 +8,7 @@
if(parent && IS_GUEST_KEY(parent.key)) // NO saving guests to the DB!
return FALSE
dirty_undatumized_preferences_player = TRUE
+ log_preferences("[parent?.ckey]: Undatumized player preference changed.")
SSpreferences.queue_write(src)
/// Marks undatumized preferences as dirty, so it will be serialized on the next preference write.
@@ -17,6 +18,7 @@
if(parent && IS_GUEST_KEY(parent.key)) // NO saving guests to the DB!
return FALSE
dirty_undatumized_preferences_character = TRUE
+ log_preferences("[parent?.ckey]: Undatumized character preference changed.")
SSpreferences.queue_write(src)
/// If any character preference is dirty.
@@ -43,14 +45,21 @@
/datum/preferences/proc/load_preferences()
if(!istype(parent))
- return FALSE
+ return PREFERENCE_LOAD_ERROR
// Cache their ckey because they can disconnect while datumized prefs read.
var/parent_ckey = parent.ckey
// Get the datumized stuff first
player_data = new(src)
- if(!player_data.load_from_database(src)) // checks db connection
- return FALSE
-
+ var/load_result = player_data.load_from_database(src)
+ if(load_result == PREFERENCE_LOAD_ERROR || load_result == null)
+ log_preferences("[parent_ckey]: ERROR - player_data failed to load datumized player preferences.")
+ if(istype(parent))
+ to_chat(parent, "Failed to load your datumized preferences. Please inform the server operator or a maintainer of this error.")
+ return PREFERENCE_LOAD_ERROR
+ if(load_result == PREFERENCE_LOAD_IGNORE)
+ log_preferences("[parent_ckey]: WARN - player_data load ignored.")
+ return PREFERENCE_LOAD_IGNORE
+ log_preferences("[parent_ckey]: Undatumized player preferences loading.")
var/datum/DBQuery/read_player_data = SSdbcore.NewQuery(
"SELECT CAST(preference_tag AS CHAR) AS ptag, preference_value FROM [format_table_name("preferences")] WHERE ckey=:ckey",
list("ckey" = parent_ckey)
@@ -62,7 +71,8 @@
if(!read_player_data.Execute())
qdel(read_player_data)
- return FALSE
+ log_preferences("[parent_ckey]: ERROR - Undatumized player preferences load query failed.")
+ return PREFERENCE_LOAD_ERROR
else
while(read_player_data.NextRow())
prefmap[read_player_data.item[1]] = read_player_data.item[2]
@@ -103,9 +113,12 @@
if(istype(entry))
continue
role_preferences_global -= preference
+ log_preferences("[parent_ckey]: WARN - Cleaned up invalid global role preference entry [preference].")
+ mark_undatumized_dirty_player()
if (!length(key_bindings))
set_default_key_bindings(save = TRUE)
+ log_preferences("[parent_ckey]: Created default keybindings on load.")
else
var/any_changed = FALSE
for(var/key_name in GLOB.keybindings_by_name)
@@ -116,12 +129,12 @@
set_keybind(key_name, keybind.keys.Copy())
any_changed = TRUE
if(any_changed)
+ log_preferences("[parent_ckey]: Assigned new keybind data on load.")
if(parent)
parent.update_special_keybinds(src)
mark_undatumized_dirty_player() // Write the new keybinds to the database.
- if(parent)
- apply_all_client_preferences()
- return TRUE
+ log_preferences("[parent_ckey]: Player preferences load result: [length(prefmap)] records.")
+ return length(prefmap) ? PREFERENCE_LOAD_SUCCESS : PREFERENCE_LOAD_NO_DATA
#undef READPREF_STR
#undef READPREF_INT
@@ -136,14 +149,24 @@
if(!istype(parent))
return FALSE
if(IS_GUEST_KEY(parent.key)) // NO saving guests to the DB!
+ log_preferences("[parent.ckey]: WARN - Preference save ignored due to guest key.")
return FALSE
// Cache their ckey because they can disconnect while datumized prefs write.
// DO NOT RENAME THIS SHIT. it will break the defines
var/parent_ckey = parent.ckey
- if(!player_data?.write_to_database(src))
+ var/write_result = player_data?.write_to_database(src)
+ if(write_result == PREFERENCE_LOAD_ERROR || write_result == null)
+ log_preferences("[parent_ckey]: ERROR - player_data failed to save datumized player preferences.")
+ if(istype(parent))
+ to_chat(parent, "Failed to save your datumized preferences. Please inform the server operator or a maintainer of this error.")
+ return FALSE
+ if(write_result == PREFERENCE_LOAD_IGNORE)
+ log_preferences("[parent_ckey]: WARN - player_data save ignored.")
return FALSE
if(!dirty_undatumized_preferences_player) // Nothing to write. Call it a success.
+ log_preferences("[parent_ckey]: Undatumized player preferences save skipped due to no changes.")
return TRUE
+ log_preferences("[parent_ckey]: Undatumized player preferences saving.")
dirty_undatumized_preferences_player = FALSE // we edit this immediately, since the DB query sleeps, the var could be modified during the sleep.
var/list/datum/DBQuery/write_queries = list() // do not rename this you muppet
@@ -161,6 +184,7 @@
// QuerySelect can execute many queries at once. That name is dumb but w/e
SSdbcore.QuerySelect(write_queries, TRUE, TRUE)
+ log_preferences("[parent_ckey]: Undatumized player preferences saved.")
return TRUE
#undef PREP_WRITEPREF_STR
@@ -181,21 +205,33 @@
/datum/preferences/proc/load_character(slot)
if(!istype(parent))
- return FALSE
+ return PREFERENCE_LOAD_ERROR
if(!slot)
slot = default_slot
slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot))
if(slot != default_slot)
+ log_preferences("[parent.ckey]: Slot change applying, from [default_slot] to [slot].")
default_slot = slot
mark_undatumized_dirty_player()
// Cache their ckey because they can disconnect while datumized prefs read.
var/parent_ckey = parent.ckey
- character_data = new(src, slot)
- if(!character_data.load_from_database(src)) // checks db connection
- return FALSE
+ if(character_data)
+ qdel(character_data)
+ character_data = new(src, slot)
+ var/read_result = character_data.load_from_database(src)
+
+ if(read_result == PREFERENCE_LOAD_ERROR || read_result == null)
+ log_preferences("[parent_ckey]: ERROR - character_data failed to load datumized character preferences.")
+ if(istype(parent))
+ to_chat(parent, "Failed to load your datumized character preferences. Please inform the server operator or a maintainer of this error.")
+ return PREFERENCE_LOAD_ERROR
+ if(read_result == PREFERENCE_LOAD_IGNORE)
+ log_preferences("[parent_ckey]: WARN - character_data load ignored.")
+ return PREFERENCE_LOAD_IGNORE
+ log_preferences("[parent_ckey]: Undatumized character preferences loading.")
// Do NOT statically cache this or I will kill you. You are asking an evil vareditor to break the DB in a BAD way
// also DO NOT rename this
var/list/column_names = list(
@@ -216,17 +252,21 @@
var/list/values
if(!Q.warn_execute())
qdel(Q)
- return FALSE
+ log_preferences("[parent_ckey]: ERROR - Undatumized character preferences load query failed.")
+ return PREFERENCE_LOAD_ERROR
if(Q.NextRow())
values = Q.item
if(!length(values)) // There is no character
qdel(Q)
- return FALSE
+ log_preferences("[parent_ckey]: Undatumized character preferences load found no results in row.")
+ return PREFERENCE_LOAD_NO_DATA
else
qdel(Q)
- return FALSE
+ log_preferences("[parent_ckey]: Undatumized character preferences load found no rows.")
+ return PREFERENCE_LOAD_NO_DATA
qdel(Q)
if(length(values) != length(column_names))
+ log_preferences("[parent_ckey]: ERROR - Undatumized character preferences load found the wrong amount of columns.")
CRASH("Error querying character data: the returned value length is not equal to the number of columns requested.")
// Decode
@@ -247,6 +287,7 @@
for(var/j in job_preferences)
if(job_preferences[j] != JP_LOW && job_preferences[j] != JP_MEDIUM && job_preferences[j] != JP_HIGH)
job_preferences -= j
+ log_preferences("[parent_ckey]: WARN - Cleaned up invalid job preference entry: [j]")
mark_undatumized_dirty_character()
// Validate role prefs
@@ -256,6 +297,7 @@
if(istype(entry) && entry.per_character)
continue
role_preferences -= preference
+ log_preferences("[parent_ckey]: WARN - Cleaned up invalid character role preference entry [preference].")
mark_undatumized_dirty_character()
// Validate equipped gear
@@ -272,7 +314,7 @@
equipped_gear -= gear_id
mark_undatumized_dirty_character()
- return TRUE
+ return PREFERENCE_LOAD_SUCCESS
#undef JSONREAD_PREF
@@ -285,13 +327,25 @@
if(!istype(parent))
return FALSE
if(IS_GUEST_KEY(parent.key)) // NO saving guests to the DB!
+ log_preferences("[parent.ckey]: WARN - Character preference save ignored due to guest key.")
return FALSE
// Cache their ckey because they can disconnect while datumized prefs write.
var/parent_ckey = parent.ckey
- if(!character_data?.write_to_database(src))
+
+ var/write_result = character_data?.write_to_database(src)
+ if(write_result == PREFERENCE_LOAD_ERROR || write_result == null)
+ log_preferences("[parent_ckey]: ERROR - character_data failed to save datumized character preferences.")
+ if(istype(parent))
+ to_chat(parent, "Failed to save your datumized character preferences. Please inform the server operator or a maintainer of this error.")
+ return FALSE
+ if(write_result == PREFERENCE_LOAD_IGNORE)
+ log_preferences("[parent_ckey]: WARN - character_data save ignored.")
return FALSE
+
if(!dirty_undatumized_preferences_character) // Nothing to write. Call it a success.
+ log_preferences("[parent_ckey]: Undatumized character preferences save skipped due to no changes.")
return TRUE
+ log_preferences("[parent_ckey]: Undatumized character preferences saving.")
dirty_undatumized_preferences_character = FALSE // we edit this immediately, since the DB query sleeps, the var could be modified during the sleep.
// DO NOT RENAME THESE LISTS! THANKS!! <3
@@ -311,9 +365,10 @@
)
var/success = Q.warn_execute()
if(!success && istype(parent))
- to_chat(parent, "Failed to save your character. Please inform the server operator or a maintainer of this error.")
+ to_chat(parent, "Failed to save your undatumized character preferences. Please inform the server operator or a maintainer of this error.")
qdel(Q)
fail_state = success
+ log_preferences("[parent_ckey]: Undatumized character preferences save status: [success ? "GOOD" : "ERROR"].")
return success
#undef WRITEPREF_STR
@@ -328,25 +383,48 @@
var/pref_type
/datum/preferences_holder/New(datum/preferences/prefs)
+ if(!pref_type)
+ CRASH("Preferences holder pref_type is [pref_type]")
preference_data = list()
dirty_prefs = list()
- // Read everything into cache
+ log_preferences("[prefs?.parent?.ckey]: Holder created of type [pref_type].")
+
+/datum/preferences_holder/proc/provide_defaults(datum/preferences/prefs, should_use_informed)
+ log_preferences("[prefs?.parent?.ckey]: Holder of type [pref_type] providing defaults (informed: [should_use_informed]).")
for (var/preference_type in GLOB.preference_entries)
var/datum/preference/preference = GLOB.preference_entries[preference_type]
- if (preference.preference_type != pref_type || preference.informed)
+ if (preference.preference_type != pref_type || (preference.informed != should_use_informed))
continue
- // we can't use informed values here. The name will get populated manually
- preference_data[preference.db_key] = preference.deserialize(preference.create_default_value(), prefs)
+ if(should_use_informed)
+ preference_data[preference.db_key] = preference.deserialize(preference.create_informed_default_value(prefs), prefs)
+ else
+ preference_data[preference.db_key] = preference.deserialize(preference.create_default_value(), prefs)
+
+/datum/preferences_holder/proc/load_from_database(datum/preferences/prefs)
+ var/result = !IS_GUEST_KEY(prefs.parent.key) ? query_data(prefs) : PREFERENCE_LOAD_IGNORE
+ if(!istype(prefs.parent)) // Client was nulled during query execution
+ return PREFERENCE_LOAD_ERROR
+ return result
+
+/datum/preferences_holder/proc/query_data(datum/preferences/prefs)
+ SHOULD_CALL_PARENT(TRUE)
+ if(!SSdbcore.IsConnected())
+ return PREFERENCE_LOAD_IGNORE
+ if(!istype(prefs.parent))
+ return PREFERENCE_LOAD_ERROR
+ return PREFERENCE_LOAD_SUCCESS
/datum/preferences_holder/proc/read_preference(datum/preferences/preferences, datum/preference/preference)
SHOULD_NOT_SLEEP(TRUE)
var/value = read_raw(preferences, preference)
if (isnull(value))
+ log_preferences("[preferences?.parent?.ckey]: Creating default value for [preference.type].")
value = preference.create_informed_default_value(preferences)
if (write_preference(preferences, preference, value))
return value
else
+ log_preferences("[preferences?.parent?.ckey]: Failed to write default value. See runtime log.")
CRASH("Couldn't write the default value for [preference.type] (received [value])")
return value
@@ -361,10 +439,26 @@
/datum/preferences_holder/proc/write_preference(datum/preferences/preferences, datum/preference/preference, value)
var/new_value = preference.deserialize(value, preferences)
if (!preference.is_valid(new_value))
+ log_preferences("[preferences?.parent?.ckey]: Preference value write for [preference.type] TO \"[new_value]\" ignored due to being invalid.")
return FALSE
preference_data[preference.db_key] = new_value
if(!istype(preferences.parent) || IS_GUEST_KEY(preferences.parent.key)) // NO saving guests to the DB!
return TRUE
dirty_prefs |= preference.db_key
SSpreferences.queue_write(preferences)
+ log_preferences("[preferences?.parent?.ckey]: Preference value write for [preference.type] TO \"[value]\" created.")
return TRUE
+
+/datum/preferences_holder/proc/write_to_database(datum/preferences/prefs)
+ . = write_data(prefs)
+ dirty_prefs.Cut() // clear all dirty preferences
+
+/datum/preferences_holder/proc/write_data(datum/preferences/prefs)
+ SHOULD_CALL_PARENT(TRUE)
+ if(!SSdbcore.IsConnected())
+ return PREFERENCE_LOAD_IGNORE
+ if(!istype(prefs.parent))
+ return PREFERENCE_LOAD_ERROR
+ if(IS_GUEST_KEY(prefs.parent.key))
+ return PREFERENCE_LOAD_IGNORE
+ return PREFERENCE_LOAD_SUCCESS
diff --git a/code/modules/client/preferences/serialization/preferences_player.dm b/code/modules/client/preferences/serialization/preferences_player.dm
index 62e833862bc7e..9f318d9f74a9c 100644
--- a/code/modules/client/preferences/serialization/preferences_player.dm
+++ b/code/modules/client/preferences/serialization/preferences_player.dm
@@ -2,73 +2,67 @@
/datum/preferences_holder/preferences_player
pref_type = PREFERENCE_PLAYER
-/datum/preferences_holder/preferences_player/proc/load_from_database(datum/preferences/prefs)
- if(IS_GUEST_KEY(prefs.parent.key) || !query_data(prefs)) // Query direct, otherwise create informed defaults
- for (var/preference_type in GLOB.preference_entries)
- var/datum/preference/preference = GLOB.preference_entries[preference_type]
- if (preference.preference_type != pref_type)
- continue
- preference_data[preference.db_key] = preference.deserialize(preference.create_informed_default_value(prefs), prefs)
- // Give the developers +1 sanity points
- if(Debugger?.enabled)
- prefs.update_preference(/datum/preference/toggle/sound_ambience, FALSE)
- prefs.update_preference(/datum/preference/toggle/sound_ship_ambience, FALSE)
- prefs.update_preference(/datum/preference/toggle/sound_lobby, FALSE)
- return FALSE
- if(!istype(prefs.parent)) // Client was nulled during query execution
- return FALSE
- return TRUE
+/datum/preferences_holder/preferences_player/load_from_database(datum/preferences/prefs)
+ . = ..()
+ // Give the developers +1 sanity points
+ if(. == PREFERENCE_LOAD_IGNORE && Debugger?.enabled)
+ prefs.update_preference(/datum/preference/toggle/sound_ambience, FALSE)
+ prefs.update_preference(/datum/preference/toggle/sound_ship_ambience, FALSE)
+ prefs.update_preference(/datum/preference/toggle/sound_lobby, FALSE)
+ return .
-/datum/preferences_holder/preferences_player/proc/query_data(datum/preferences/prefs)
- if(!SSdbcore.IsConnected())
- return FALSE
- if(!istype(prefs.parent))
- return FALSE
+/datum/preferences_holder/preferences_player/query_data(datum/preferences/prefs)
+ . = ..()
+ if(. != PREFERENCE_LOAD_SUCCESS)
+ return .
var/datum/DBQuery/Q = SSdbcore.NewQuery(
"SELECT CAST(preference_tag AS CHAR) AS ptag, preference_value FROM [format_table_name("preferences")] WHERE ckey=:ckey",
list("ckey" = prefs.parent.ckey)
)
if(!Q.warn_execute())
qdel(Q)
- return FALSE
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized player preferences load query failed.")
+ return PREFERENCE_LOAD_ERROR
var/any_data = FALSE
while(Q.NextRow())
var/db_key = Q.item[1]
var/value = Q.item[2]
var/datum/preference/preference = GLOB.preference_entries_by_key[db_key]
if(!preference)
- // If you ever want to error for unknown tags, this would be helpful.
- // As of now we don't really care since it doesn't help anything to throw runtimes everywhere.
- //CRASH("Unknown preference tag in database: [db_key] for ckey [prefs.parent.ckey]")
+ if(!(db_key in GLOB.undatumized_preference_tags_player))
+ log_preferences("[prefs.parent.ckey]: WARN - Datumized player preferences failed to find preference [db_key] in game, but it was in the database.")
continue
preference_data[db_key] = isnull(value) ? null : preference.deserialize(value, prefs)
any_data = TRUE
qdel(Q)
- return any_data
+ log_preferences("[prefs.parent.ckey]: Successfully loaded datumized character preferences[!any_data ? " (no records found)" : ""].")
+ return any_data ? PREFERENCE_LOAD_SUCCESS : PREFERENCE_LOAD_NO_DATA
-/datum/preferences_holder/preferences_player/proc/write_to_database(datum/preferences/prefs)
- . = write_data(prefs)
- dirty_prefs.Cut() // clear all dirty preferences
-
-/datum/preferences_holder/preferences_player/proc/write_data(datum/preferences/prefs)
- if(!SSdbcore.IsConnected() || !istype(prefs.parent) || IS_GUEST_KEY(prefs.parent.key))
- return FALSE
+/datum/preferences_holder/preferences_player/write_data(datum/preferences/prefs)
+ . = ..()
+ if(. != PREFERENCE_LOAD_SUCCESS)
+ return .
var/list/sql_inserts = list()
for(var/db_key in dirty_prefs)
if(!(db_key in preference_data))
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized player preferences write found invalid db_key [db_key] in dirty preferences list.")
CRASH("Invalid db_key found in dirty preferences list: [db_key].")
var/datum/preference/preference = GLOB.preference_entries_by_key[db_key]
if(!istype(preference))
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized player preferences write found invalid db_key [db_key] in dirty preferences list (2).")
CRASH("Could not find preference with db_key [db_key] when writing to database.")
+ if(preference.preference_type != pref_type)
+ log_preferences("[prefs.parent.ckey]: ERROR - Datumized player preferences write found invalid preference type [preference.preference_type] for [db_key] (want [pref_type]).")
+ CRASH("Invalid preference located from db_key [db_key] for the preference type [pref_type] (had [preference.preference_type])")
sql_inserts += list(list(
"ckey" = prefs.parent.ckey,
"preference_tag" = db_key,
"preference_value" = preference.serialize(preference_data[db_key])
))
if(!length(sql_inserts)) // nothing to update
- return TRUE
+ log_preferences("[prefs.parent.ckey]: Datumized player preferences write - no columns to write.")
+ return PREFERENCE_LOAD_NO_DATA
var/success = SSdbcore.MassInsert(format_table_name("preferences"), sql_inserts, duplicate_key = TRUE, warn = TRUE)
- if(!success)
- to_chat(prefs.parent, "Failed to save your player preferences. Please inform the server operator or a maintainer of this error.")
prefs.fail_state = success
- return success
+ log_preferences("[prefs.parent.ckey]: Datumized player preferences write result [success ? "GOOD" : "ERROR"].")
+ return success ? PREFERENCE_LOAD_SUCCESS : PREFERENCE_LOAD_ERROR
diff --git a/code/modules/client/preferences/submodules/preference_character_preview.dm b/code/modules/client/preferences/submodules/preference_character_preview.dm
index ff228bc69ee07..90fbc06d3ae5f 100644
--- a/code/modules/client/preferences/submodules/preference_character_preview.dm
+++ b/code/modules/client/preferences/submodules/preference_character_preview.dm
@@ -15,7 +15,7 @@
return image('icons/mob/robots.dmi', icon_state = "robot", dir = SOUTH)
// Set up the dummy for its photoshoot
- apply_prefs_to(mannequin, TRUE)
+ apply_prefs_to(mannequin, TRUE, log = FALSE)
// Normalize size, since it doesn't scale properly in the preview.
mannequin.dna.features["body_size"] = "Normal"
mannequin.dna.update_body_size()
diff --git a/code/modules/client/preferences/submodules/preference_jobs.dm b/code/modules/client/preferences/submodules/preference_jobs.dm
index f384538b987ac..e1785a6dfbee1 100644
--- a/code/modules/client/preferences/submodules/preference_jobs.dm
+++ b/code/modules/client/preferences/submodules/preference_jobs.dm
@@ -2,6 +2,8 @@
if (!job)
return FALSE
+ log_preferences("[parent?.ckey]: Set [job.title] preference to level [level].")
+
if (level == JP_HIGH)
var/datum/job/overflow_role = SSjob.overflow_role
var/overflow_role_title = initial(overflow_role.title)
@@ -11,8 +13,10 @@
// Overflow role needs to go to NEVER, not medium!
if(other_job == overflow_role_title)
job_preferences[other_job] = null
+ log_preferences("[parent?.ckey]: Set [other_job] preference to level null.")
else
job_preferences[other_job] = JP_MEDIUM
+ log_preferences("[parent?.ckey]: Set [other_job] preference to level [JP_MEDIUM].")
if(level == null)
job_preferences -= job.title
diff --git a/code/modules/client/preferences/submodules/preference_keybindings.dm b/code/modules/client/preferences/submodules/preference_keybindings.dm
index d54c1fc066f03..4fdf3014f676b 100644
--- a/code/modules/client/preferences/submodules/preference_keybindings.dm
+++ b/code/modules/client/preferences/submodules/preference_keybindings.dm
@@ -28,6 +28,7 @@
return FALSE
if(!islist(hotkeys))
return
+ log_preferences("[parent?.ckey]: Set keybind [keybind_name] to [english_list(hotkeys)].")
key_bindings[keybind_name] = hotkeys
key_bindings_by_key = get_key_bindings_by_key(key_bindings)
mark_undatumized_dirty_player()
diff --git a/code/modules/client/preferences/submodules/preference_randomization.dm b/code/modules/client/preferences/submodules/preference_randomization.dm
index 70ffa96944def..9c557d2c9a523 100644
--- a/code/modules/client/preferences/submodules/preference_randomization.dm
+++ b/code/modules/client/preferences/submodules/preference_randomization.dm
@@ -5,6 +5,7 @@
continue
if (preference.is_randomizable())
+ log_preferences("[parent?.ckey]: Randomizing [preference.type] from flags [randomize_flags == ALL ? "ALL" : randomize_flags].")
write_preference(preference, preference.create_random_value(src))
/// Randomizes the character according to preferences.
@@ -18,6 +19,7 @@
for (var/datum/preference/preference as anything in get_preferences_in_priority_order())
if (should_randomize(preference, antag_override))
+ log_preferences("[parent?.ckey]: Randomizing [preference.type] according to randomization options.")
write_preference(preference, preference.create_random_value(src))
/// Returns the default `randomize` variable ouptut
diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm
index c2943b1c67c54..93e95ab50e35a 100644
--- a/code/modules/client/verbs/suicide.dm
+++ b/code/modules/client/verbs/suicide.dm
@@ -75,12 +75,15 @@
adjustOxyLoss(200/damage_mod)
if(damagetype & MANUAL_SUICIDE) //Assume the object will handle the death.
+ investigate_log("has died from committing suicide[held_item ? " with [held_item]" : ""].", INVESTIGATE_DEATHS)
return
//If something went wrong, just do normal oxyloss
if(!(damagetype & (BRUTELOSS | FIRELOSS | TOXLOSS | OXYLOSS) ))
adjustOxyLoss(max(200 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0))
+ investigate_log("has died from committing suicide[held_item ? " with [held_item]" : ""].", INVESTIGATE_DEATHS)
+
death(FALSE)
ghostize(FALSE,SENTIENCE_ERASE) // Disallows reentering body and disassociates mind
@@ -113,6 +116,7 @@
suicide_log()
adjustOxyLoss(max(200 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0))
+ investigate_log("has died from committing suicide[held_item ? " with [held_item]" : ""].", INVESTIGATE_DEATHS)
death(FALSE)
/mob/living/brain/verb/suicide()
@@ -241,6 +245,7 @@
ghostize(FALSE,SENTIENCE_ERASE) // Disallows reentering body and disassociates mind
/mob/living/proc/suicide_log()
+ investigate_log("has died from committing suicide.", INVESTIGATE_DEATHS)
log_game("[key_name(src)] committed suicide at [AREACOORD(src)] as [src.type].")
if(CONFIG_GET(flag/restricted_suicide))
message_admins("[key_name(src)] committed suicide at [AREACOORD(src)] as [src.type].")
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 33307f56c9e7e..2161a31b30e1f 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -415,9 +415,7 @@ BLIND // can't see anything
if(iscarbon(user))
var/mob/living/carbon/C = user
C.head_update(src, forced = TRUE)
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
return TRUE
/obj/item/clothing/proc/visor_toggling() //handles all the actual toggling of flags
diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm
index 39e3e700cd279..35f4c2a09b928 100644
--- a/code/modules/clothing/glasses/engine_goggles.dm
+++ b/code/modules/clothing/glasses/engine_goggles.dm
@@ -52,9 +52,7 @@
H.update_sight()
update_icon()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/clothing/glasses/meson/engine/attack_self(mob/user)
toggle_mode(user, TRUE)
diff --git a/code/modules/clothing/head/beanie.dm b/code/modules/clothing/head/beanie.dm
index f8a26ac036135..aebb48b24e90e 100644
--- a/code/modules/clothing/head/beanie.dm
+++ b/code/modules/clothing/head/beanie.dm
@@ -87,7 +87,7 @@
name = "durathread beanie"
desc = "A beanie made from durathread, its resilient fibres provide some protection to the wearer."
icon_state = "beaniedurathread"
- armor = list(MELEE = 15, BULLET = 5, LASER = 15, ENERGY = 5, BOMB = 10, BIO = 0, RAD = 0, FIRE = 30, ACID = 5, STAMINA = 20)
+ armor = list(MELEE = 15, BULLET = 25, LASER = 15, ENERGY = 5, BOMB = 10, BIO = 0, RAD = 0, FIRE = 30, ACID = 5, STAMINA = 20)
/obj/item/clothing/head/beanie/waldo
name = "red striped bobble hat"
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 116eeedf7d66f..6f3549bbfe48d 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -83,6 +83,9 @@
cold_protection = HEAD
heat_protection = HEAD
dog_fashion = null
+ flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT|HIDEMASK
+ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
+
/obj/item/clothing/head/hardhat/white
name = "white hard hat"
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 970d9d6cc047a..4db0948bde051 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -66,9 +66,7 @@
var/mob/living/carbon/human/H = loc
H.update_inv_head()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/clothing/head/helmet/attackby(obj/item/I, mob/user, params)
@@ -391,11 +389,11 @@
/obj/item/clothing/head/helmet/durathread
name = "durathread helmet"
- desc = "A helmet made from durathread and leather."
+ desc = "A helmet made from durathread, a strong material commonly used for ballistic protection."
icon_state = "durathread"
item_state = "durathread"
resistance_flags = FLAMMABLE
- armor = list(MELEE = 20, BULLET = 10, LASER = 30, ENERGY = 5, BOMB = 15, BIO = 0, RAD = 0, FIRE = 40, ACID = 50, STAMINA = 30)
+ armor = list(MELEE = 20, BULLET = 40, LASER = 30, ENERGY = 5, BOMB = 15, BIO = 0, RAD = 0, FIRE = 40, ACID = 50, STAMINA = 30)
strip_delay = 60
/obj/item/clothing/head/helmet/rus_helmet
diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm
index 6b8381be237c3..a8452422465fe 100644
--- a/code/modules/clothing/head/jobs.dm
+++ b/code/modules/clothing/head/jobs.dm
@@ -15,7 +15,7 @@
dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/chef
-/obj/item/clothing/head/chefhat/suicide_act(mob/user)
+/obj/item/clothing/head/chefhat/suicide_act(mob/living/user)
user.visible_message("[user] is donning [src]! It looks like [user.p_theyre()] trying to become a chef.")
user.say("Bork Bork Bork!", forced = "chef hat suicide")
sleep(20)
@@ -145,7 +145,7 @@
name = "durathread beret"
desc = "A beret made from durathread, its resilient fibres provide some protection to the wearer."
icon_state = "beretdurathread"
- armor = list(MELEE = 15, BULLET = 5, LASER = 15, ENERGY = 20, BOMB = 10, BIO = 0, RAD = 0, FIRE = 30, ACID = 5, STAMINA = 20)
+ armor = list(MELEE = 15, BULLET = 25, LASER = 15, ENERGY = 20, BOMB = 10, BIO = 0, RAD = 0, FIRE = 30, ACID = 5, STAMINA = 20)
//Security
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index bcc6790770d8e..a4374a061b093 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -200,15 +200,15 @@
desc = "A really cool hat if you're a mobster. A really lame hat if you're not."
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small
-/obj/item/clothing/head/fedora/suicide_act(mob/user)
+/obj/item/clothing/head/fedora/suicide_act(mob/living/user)
if(user.gender == FEMALE)
- return 0
+ return
var/mob/living/carbon/human/H = user
user.visible_message("[user] is donning [src]! It looks like [user.p_theyre()] trying to be nice to girls.")
user.say("M'lady.", forced = "fedora suicide")
sleep(10)
H.facial_hair_style = "Neckbeard"
- return(BRUTELOSS)
+ return BRUTELOSS
/obj/item/clothing/head/sombrero
name = "sombrero"
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index 92427e6120d87..daf35b7ed9bc0 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -22,7 +22,7 @@
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean_blood))
/obj/item/clothing/shoes/suicide_act(mob/living/carbon/user)
- if(rand(2)>1)
+ if(prob(50))
user.visible_message("[user] begins tying \the [src] up waaay too tightly! It looks like [user.p_theyre()] trying to commit suicide!")
var/obj/item/bodypart/l_leg = user.get_bodypart(BODY_ZONE_L_LEG)
var/obj/item/bodypart/r_leg = user.get_bodypart(BODY_ZONE_R_LEG)
@@ -37,8 +37,8 @@
user.visible_message("[user] is bashing [user.p_their()] own head in with [src]! Ain't that a kick in the head?")
for(var/i in 1 to 3)
sleep(3)
- playsound(user, 'sound/weapons/genhit2.ogg', 50, 1)
- return(BRUTELOSS)
+ playsound(user, 'sound/weapons/genhit2.ogg', 50, TRUE)
+ return BRUTELOSS
/obj/item/clothing/shoes/worn_overlays(mutable_appearance/standing, isinhands = FALSE)
. = list()
diff --git a/code/modules/clothing/shoes/bananashoes.dm b/code/modules/clothing/shoes/bananashoes.dm
index 8fee7440072fb..b58cdcd7c86a3 100644
--- a/code/modules/clothing/shoes/bananashoes.dm
+++ b/code/modules/clothing/shoes/bananashoes.dm
@@ -62,6 +62,4 @@
else
icon_state = "clown_prototype_off"
usr.update_inv_shoes()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm
index 75913d615fa1d..d2475cf7ac92a 100644
--- a/code/modules/clothing/shoes/magboots.dm
+++ b/code/modules/clothing/shoes/magboots.dm
@@ -33,9 +33,7 @@
to_chat(user, "You [magpulse ? "enable" : "disable"] the mag-pulse traction system.")
user.update_inv_shoes() //so our mob-overlays update
user.update_gravity(user.has_gravity())
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/clothing/shoes/magboots/negates_gravity()
return isspaceturf(get_turf(src)) ? FALSE : magpulse //We don't mimick gravity on space turfs
@@ -79,9 +77,7 @@
to_chat(user, "You [magpulse ? "enable" : "disable"] the mag-pulse traction system.")
user.update_inv_shoes()
user.update_gravity(user.has_gravity())
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/clothing/shoes/magboots/crushing
desc = "Normal looking magboots that are altered to increase magnetic pull to crush anything underfoot."
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index b160f9943c167..f6ab865e2ff16 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -51,9 +51,7 @@
set_light_on(on)
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/clothing/head/helmet/space/hardsuit/dropped(mob/user)
..()
@@ -454,9 +452,7 @@
if(iscarbon(user))
var/mob/living/carbon/C = user
C.head_update(src, forced = 1)
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/clothing/head/helmet/space/hardsuit/syndi/proc/toggle_hardsuit_mode(mob/user) //Helmet Toggles Suit Mode
if(linkedsuit)
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index f192eec651e13..f19bba0ef3643 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -285,14 +285,14 @@
/obj/item/clothing/suit/armor/vest/durathread
name = "durathread vest"
- desc = "A vest made of durathread with strips of leather acting as trauma plates."
+ desc = "A bulletproof vest made from durathread, an inexpesive but relatively effective form of protection."
icon_state = "durathread"
item_state = "durathread"
strip_delay = 60
equip_delay_other = 40
max_integrity = 200
resistance_flags = FLAMMABLE
- armor = list(MELEE = 20, BULLET = 10, LASER = 30, ENERGY = 40, BOMB = 15, BIO = 0, RAD = 0, FIRE = 40, ACID = 50, STAMINA = 30)
+ armor = list(MELEE = 20, BULLET = 40, LASER = 30, ENERGY = 40, BOMB = 15, BIO = 0, RAD = 0, FIRE = 40, ACID = 50, STAMINA = 30)
/obj/item/clothing/suit/armor/vest/russian
name = "russian vest"
diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm
index 935fd3ac08407..4405c35131a2c 100644
--- a/code/modules/clothing/suits/cloaks.dm
+++ b/code/modules/clothing/suits/cloaks.dm
@@ -11,9 +11,9 @@
flags_inv = HIDESUITSTORAGE
pocket_storage_component_path = /datum/component/storage/concrete/pockets/exo/cloak
-/obj/item/clothing/neck/cloak/suicide_act(mob/user)
+/obj/item/clothing/neck/cloak/suicide_act(mob/living/user)
user.visible_message("[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return(OXYLOSS)
+ return OXYLOSS
/obj/item/clothing/neck/cloak/hos
name = "head of security's cloak"
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index c6480626984f8..b728ad9424bd9 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -579,6 +579,7 @@
body_parts_covered = CHEST|GROIN
attack_verb = list("warned", "cautioned", "smashed")
armor = list(MELEE = 5, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0, STAMINA = 0)
+ pocket_storage_component_path = null
@@ -969,11 +970,11 @@
name = "durathread hoodie"
desc = "A hoodie made from durathread, its resilient fibres provide some protection to the wearer."
color = "#8291a1"
- armor = list(MELEE = 15, LASER = 10, FIRE = 40, ACID = 10, BOMB = 5, STAMINA = 30)
+ armor = list(MELEE = 15, BULLET = 25, LASER = 10, FIRE = 40, ACID = 10, BOMB = 5, STAMINA = 30)
hoodtype = /obj/item/clothing/head/hooded/hoodie/durathread
/obj/item/clothing/head/hooded/hoodie/durathread
name = "durathread hoodie hood"
desc = "A duratread hood attached to your hoodie, robust as."
- armor = list(MELEE = 5, LASER = 5, FIRE = 20, ACID = 5, BOMB = 5, STAMINA = 15)
+ armor = list(MELEE = 5, BULLET = 5, LASER = 5, FIRE = 20, ACID = 5, BOMB = 5, STAMINA = 15)
color = "#8291a1"
diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm
index ac7a8f2d2c737..a079a0db3e03f 100644
--- a/code/modules/clothing/suits/toggles.dm
+++ b/code/modules/clothing/suits/toggles.dm
@@ -49,9 +49,8 @@
hood.moveToNullspace() //Hides hood in nullspace instead of within the pocket of whatever it's on
if(qdel_hood)
QDEL_NULL(hood)
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+
+ update_action_buttons()
/obj/item/clothing/suit/hooded/dropped()
..()
@@ -78,9 +77,7 @@
suittoggled = TRUE
icon_state = "[initial(icon_state)]_t"
H.update_inv_wear_suit()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
else
RemoveHood()
@@ -134,9 +131,7 @@
src.worn_icon_state = "[initial(icon_state)]_t"
src.suittoggled = TRUE
usr.update_inv_wear_suit()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ update_action_buttons()
/obj/item/clothing/suit/toggle/examine(mob/user)
. = ..()
diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm
index defc0c9d0200c..d40e27fd49778 100644
--- a/code/modules/clothing/under/color.dm
+++ b/code/modules/clothing/under/color.dm
@@ -213,13 +213,13 @@
name = "durathread jumpsuit"
desc = "A jumpsuit made from durathread, its resilient fibres provide some protection to the wearer."
greyscale_colors = "#8291a1"
- armor = list(MELEE = 10, LASER = 10, FIRE = 40, ACID = 10, BOMB = 5, ENERGY = 20, STAMINA = 20)
+ armor = list(MELEE = 10, BULLET = 15, LASER = 10, FIRE = 40, ACID = 10, BOMB = 5, ENERGY = 20, STAMINA = 20)
/obj/item/clothing/under/color/jumpskirt/durathread
name = "durathread jumpskirt"
desc = "A jumpskirt made from durathread, its resilient fibres provide some protection to the wearer."
greyscale_colors = "#8291a1"
- armor = list(MELEE = 10, LASER = 10, FIRE = 40, ACID = 10, BOMB = 5, ENERGY = 20, STAMINA = 20)
+ armor = list(MELEE = 10, BULLET = 15, LASER = 10, FIRE = 40, ACID = 10, BOMB = 5, ENERGY = 20, STAMINA = 20)
/obj/item/clothing/under/color/rainbow
name = "rainbow jumpsuit"
diff --git a/code/modules/detectivework/footprints_and_rag.dm b/code/modules/detectivework/footprints_and_rag.dm
index 3757f5c985c79..1957c914783e5 100644
--- a/code/modules/detectivework/footprints_and_rag.dm
+++ b/code/modules/detectivework/footprints_and_rag.dm
@@ -19,9 +19,9 @@
volume = 5
spillable = FALSE
-/obj/item/reagent_containers/glass/rag/suicide_act(mob/user)
+/obj/item/reagent_containers/glass/rag/suicide_act(mob/living/user)
user.visible_message("[user] is smothering [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (OXYLOSS)
+ return OXYLOSS
/obj/item/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user,proximity)
. = ..()
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index 8c5c3a584cfcd..a6fee0fa45704 100644
--- a/code/modules/food_and_drinks/drinks/drinks.dm
+++ b/code/modules/food_and_drinks/drinks/drinks.dm
@@ -267,7 +267,7 @@
name = "cup ramen"
desc = "Just add 5ml of water, self heats! A taste that reminds you of your school years. Now new with salty flavour!"
icon_state = "ramen"
- list_reagents = list(/datum/reagent/consumable/dry_ramen = 15, /datum/reagent/consumable/sodiumchloride = 3)
+ list_reagents = list(/datum/reagent/consumable/dry_ramen = 15, /datum/reagent/consumable/sodiumchloride = 3, /datum/reagent/consumable/maltodextrin = 10)
foodtype = GRAIN
isGlass = FALSE
custom_price = 38
diff --git a/code/modules/food_and_drinks/food/condiment.dm b/code/modules/food_and_drinks/food/condiment.dm
index 169a1832828d2..2a06c93634a65 100644
--- a/code/modules/food_and_drinks/food/condiment.dm
+++ b/code/modules/food_and_drinks/food/condiment.dm
@@ -152,7 +152,7 @@
volume = 20
list_reagents = list(/datum/reagent/consumable/sodiumchloride = 20)
-/obj/item/reagent_containers/food/condiment/saltshaker/suicide_act(mob/user)
+/obj/item/reagent_containers/food/condiment/saltshaker/suicide_act(mob/living/user)
user.visible_message("[user] begins to swap forms with the salt shaker! It looks like [user.p_theyre()] trying to commit suicide!")
var/newname = "[name]"
name = "[user.name]"
@@ -198,7 +198,7 @@
desc = "A big bag of flour. Good for baking!"
icon_state = "flour"
item_state = "flour"
- list_reagents = list(/datum/reagent/consumable/flour = 30)
+ list_reagents = list(/datum/reagent/consumable/flour = 50)
/obj/item/reagent_containers/food/condiment/soymilk
name = "soy milk"
@@ -214,7 +214,7 @@
desc = "A big bag of rice. Good for cooking!"
icon_state = "rice"
item_state = "flour"
- list_reagents = list(/datum/reagent/consumable/rice = 30)
+ list_reagents = list(/datum/reagent/consumable/rice = 50)
/obj/item/reagent_containers/food/condiment/soysauce
name = "soy sauce"
diff --git a/code/modules/food_and_drinks/food/snacks/dough.dm b/code/modules/food_and_drinks/food/snacks/dough.dm
deleted file mode 100644
index f8849de2ed06b..0000000000000
--- a/code/modules/food_and_drinks/food/snacks/dough.dm
+++ /dev/null
@@ -1,131 +0,0 @@
-
-
-/////////////////// Dough Ingredients ////////////////////////
-
-/obj/item/reagent_containers/food/snacks/dough
- name = "dough"
- desc = "A piece of dough."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "dough"
- cooked_type = /obj/item/food/bread/plain
- list_reagents = list(/datum/reagent/consumable/nutriment = 6)
- w_class = WEIGHT_CLASS_NORMAL
- tastes = list("dough" = 1)
- foodtype = GRAIN
-
-
-// Dough + rolling pin = flat dough
-/obj/item/reagent_containers/food/snacks/dough/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/kitchen/rollingpin))
- if(isturf(loc))
- new /obj/item/reagent_containers/food/snacks/flatdough(loc)
- to_chat(user, "You flatten [src].")
- qdel(src)
- else
- to_chat(user, "You need to put [src] on a surface to roll it out!")
- else
- ..()
-
-
-// sliceable into 3xdoughslices
-/obj/item/reagent_containers/food/snacks/flatdough
- name = "flat dough"
- desc = "A flattened dough."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "flat dough"
- slice_path = /obj/item/reagent_containers/food/snacks/doughslice
- slices_num = 3
- cooked_type = /obj/item/reagent_containers/food/snacks/pizzabread
- list_reagents = list(/datum/reagent/consumable/nutriment = 6)
- w_class = WEIGHT_CLASS_NORMAL
- tastes = list("dough" = 1)
- foodtype = GRAIN
-
-/obj/item/reagent_containers/food/snacks/pizzabread
- name = "pizza bread"
- desc = "Add ingredients to make a pizza."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "pizzabread"
- list_reagents = list(/datum/reagent/consumable/nutriment = 7)
- w_class = WEIGHT_CLASS_NORMAL
- tastes = list("bread" = 1)
- foodtype = GRAIN
-
-
-/obj/item/reagent_containers/food/snacks/doughslice
- name = "dough slice"
- desc = "A slice of dough. Can be cooked into a bun."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "doughslice"
- cooked_type = /obj/item/reagent_containers/food/snacks/bun
- filling_color = "#CD853F"
- tastes = list("dough" = 1)
- foodtype = GRAIN
-
-
-/obj/item/reagent_containers/food/snacks/bun
- name = "bun"
- desc = "A base for any self-respecting burger."
- icon = 'icons/obj/food/burgerbread.dmi'
- icon_state = "bun"
- list_reagents = list(/datum/reagent/consumable/nutriment = 1)
- filling_color = "#CD853F"
- tastes = list("bun" = 1) // the bun tastes of bun.
- foodtype = GRAIN
-
-/obj/item/reagent_containers/food/snacks/cakebatter
- name = "cake batter"
- desc = "Cook it to get a cake."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "cakebatter"
- cooked_type = /obj/item/food/cake/plain
- list_reagents = list(/datum/reagent/consumable/nutriment = 9)
- w_class = WEIGHT_CLASS_NORMAL
- tastes = list("batter" = 1)
- foodtype = GRAIN | DAIRY
-
-// Cake batter + rolling pin = pie dough
-/obj/item/reagent_containers/food/snacks/cakebatter/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/kitchen/rollingpin))
- if(isturf(loc))
- new /obj/item/reagent_containers/food/snacks/piedough(loc)
- to_chat(user, "You flatten [src].")
- qdel(src)
- else
- to_chat(user, "You need to put [src] on a surface to roll it out!")
- else
- ..()
-
-/obj/item/reagent_containers/food/snacks/piedough
- name = "pie dough"
- desc = "Cook it to get a pie."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "piedough"
- slice_path = /obj/item/reagent_containers/food/snacks/rawpastrybase
- slices_num = 3
- cooked_type = /obj/item/reagent_containers/food/snacks/pie/plain
- list_reagents = list(/datum/reagent/consumable/nutriment = 9)
- w_class = WEIGHT_CLASS_NORMAL
- tastes = list("dough" = 1)
- foodtype = GRAIN | DAIRY
-
-/obj/item/reagent_containers/food/snacks/rawpastrybase
- name = "raw pastry base"
- desc = "Must be cooked before use."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "rawpastrybase"
- cooked_type = /obj/item/reagent_containers/food/snacks/pastrybase
- filling_color = "#CD853F"
- list_reagents = list(/datum/reagent/consumable/nutriment = 1)
- tastes = list("raw pastry" = 1)
- foodtype = GRAIN | DAIRY
-
-/obj/item/reagent_containers/food/snacks/pastrybase
- name = "pastry base"
- desc = "A base for any self-respecting pastry."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "pastrybase"
- list_reagents = list(/datum/reagent/consumable/nutriment = 1)
- filling_color = "#CD853F"
- tastes = list("pastry" = 1)
- foodtype = GRAIN | DAIRY
diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm
index 98accce5e82e0..45ce6763d777c 100644
--- a/code/modules/food_and_drinks/food/snacks_meat.dm
+++ b/code/modules/food_and_drinks/food/snacks_meat.dm
@@ -203,17 +203,6 @@
tastes = list("the jungle" = 1, "bananas" = 1, "jimmies" = 1)
spawned_mob = /mob/living/simple_animal/hostile/gorilla
-/obj/item/reagent_containers/food/snacks/enchiladas
- name = "enchiladas"
- desc = "Viva La Mexico!"
- icon_state = "enchiladas"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2)
- bitesize = 4
- filling_color = "#FFA07A"
- list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/capsaicin = 6)
- tastes = list("hot peppers" = 1, "meat" = 3, "cheese" = 1, "sour cream" = 1)
- foodtype = MEAT
-
/obj/item/reagent_containers/food/snacks/stewedsoymeat
name = "stewed soy meat"
desc = "Even non-vegetarians will LOVE this!"
diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm
index dbf44ce3a4a1c..ab3ffc31564bf 100644
--- a/code/modules/food_and_drinks/food/snacks_other.dm
+++ b/code/modules/food_and_drinks/food/snacks_other.dm
@@ -291,56 +291,6 @@
tastes = list("eggplant" = 3, "cheese" = 1)
foodtype = VEGETABLES | DAIRY
-/obj/item/reagent_containers/food/snacks/tortilla
- name = "tortilla"
- desc = "The base for all your burritos."
- icon = 'icons/obj/food/food_ingredients.dmi'
- icon_state = "tortilla"
- list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 1)
- filling_color = "#FFEFD5"
- tastes = list("tortilla" = 1)
- foodtype = GRAIN
-
-/obj/item/reagent_containers/food/snacks/burrito
- name = "burrito"
- desc = "Tortilla wrapped goodness."
- icon_state = "burrito"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 2)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/vitamin = 1)
- filling_color = "#FFEFD5"
- tastes = list("tortilla" = 2)
- foodtype = GRAIN
-
-/obj/item/reagent_containers/food/snacks/cheesyburrito
- name = "cheesy burrito"
- desc = "It's a burrito filled with cheese."
- icon_state = "cheesyburrito"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/vitamin = 2)
- filling_color = "#FFD800"
- tastes = list("tortilla" = 2, "cheese" = 1)
- foodtype = GRAIN | DAIRY
-
-/obj/item/reagent_containers/food/snacks/carneburrito
- name = "carne asada burrito"
- desc = "The best burrito for meat lovers."
- icon_state = "carneburrito"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 1)
- list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 1)
- filling_color = "#A0522D"
- tastes = list("tortilla" = 2, "meat" = 4)
- foodtype = GRAIN | MEAT
-
-/obj/item/reagent_containers/food/snacks/fuegoburrito
- name = "fuego plasma burrito"
- desc = "A super spicy burrito."
- icon_state = "fuegoburrito"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 3)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/capsaicin = 5, /datum/reagent/consumable/nutriment/vitamin = 3)
- filling_color = "#FF2000"
- tastes = list("tortilla" = 2, "hot peppers" = 1)
- foodtype = GRAIN
-
/obj/item/reagent_containers/food/snacks/yakiimo
name = "yaki imo"
desc = "Made with roasted sweet potatoes!"
@@ -372,36 +322,6 @@
tastes = list("melon" = 1)
foodtype = FRUIT
-/obj/item/reagent_containers/food/snacks/nachos
- name = "nachos"
- desc = "Chips from Space Mexico."
- icon_state = "nachos"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1)
- list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 2)
- filling_color = "#F4A460"
- tastes = list("nachos" = 1)
- foodtype = VEGETABLES | FRIED
-
-/obj/item/reagent_containers/food/snacks/cheesynachos
- name = "cheesy nachos"
- desc = "The delicious combination of nachos and melting cheese."
- icon_state = "cheesynachos"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2)
- list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 3)
- filling_color = "#FFD700"
- tastes = list("nachos" = 2, "cheese" = 1)
- foodtype = VEGETABLES | FRIED | DAIRY
-
-/obj/item/reagent_containers/food/snacks/cubannachos
- name = "Cuban nachos"
- desc = "That's some dangerously spicy nachos."
- icon_state = "cubannachos"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 3)
- list_reagents = list(/datum/reagent/consumable/nutriment = 7, /datum/reagent/consumable/capsaicin = 8, /datum/reagent/consumable/nutriment/vitamin = 4)
- filling_color = "#DC143C"
- tastes = list("nachos" = 2, "hot pepper" = 1)
- foodtype = VEGETABLES | FRIED | DAIRY
-
/obj/item/reagent_containers/food/snacks/melonkeg
name = "melon keg"
desc = "Who knew vodka was a fruit?"
@@ -426,15 +346,6 @@
/*food_flags = FOOD_FINGER_FOOD*/
w_class = WEIGHT_CLASS_SMALL
-/obj/item/reagent_containers/food/snacks/stuffedlegion
- name = "stuffed legion"
- desc = "The former skull of a damned human, filled with goliath meat. It has a decorative lava pool made of ketchup and hotsauce."
- icon_state = "stuffed_legion"
- bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 3, /datum/reagent/consumable/capsaicin = 1, /datum/reagent/medicine/tricordrazine = 5)
- list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 5, /datum/reagent/consumable/capsaicin = 2, /datum/reagent/medicine/tricordrazine = 10)
- tastes = list("death" = 2, "rock" = 1, "meat" = 1, "hot peppers" = 1)
- foodtype = MEAT
-
/obj/item/reagent_containers/food/snacks/powercrepe
name = "Powercrepe"
desc = "With great power, comes great crepes. It looks like a pancake filled with jelly but packs quite a punch."
@@ -580,24 +491,6 @@
if(spamchecking)
qdel(src)
-/obj/item/reagent_containers/food/snacks/taco
- name = "taco"
- desc = "A traditional taco with meat, cheese, and lettuce."
- icon_state = "taco"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/vitamin = 2)
- filling_color = "F0D830"
- tastes = list("taco" = 4, "meat" = 2, "cheese" = 2, "lettuce" = 1)
- foodtype = MEAT | DAIRY | GRAIN | VEGETABLES
-
-/obj/item/reagent_containers/food/snacks/taco/plain
- desc = "A traditional taco with meat and cheese, minus the rabbit food."
- icon_state = "taco_plain"
- bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 2)
- list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 1)
- tastes = list("taco" = 4, "meat" = 2, "cheese" = 2)
- foodtype = MEAT | DAIRY | GRAIN
-
/obj/item/reagent_containers/food/snacks/branrequests
name = "Bran Requests Cereal"
desc = "A dry cereal that satiates your requests for bran. Tastes uniquely like raisins and salt."
diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm
index 949d0e52d551a..cc08fd1832968 100644
--- a/code/modules/food_and_drinks/food/snacks_pastry.dm
+++ b/code/modules/food_and_drinks/food/snacks_pastry.dm
@@ -148,6 +148,12 @@
is_decorated = TRUE
filling_color = "#879630"
+/obj/item/reagent_containers/food/snacks/donut/premade
+ name = "prepackaged donut"
+ desc = "A mass produced donut, goes great with a cup of coffee."
+ icon_state = "donut"
+ list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/sprinkles = 1, /datum/reagent/consumable/sugar = 2, /datum/reagent/consumable/maltodextrin = 6)
+
//////////////////////JELLY DONUTS/////////////////////////
/obj/item/reagent_containers/food/snacks/donut/jelly
@@ -456,7 +462,7 @@
name = "\improper Donk-pocket"
desc = "The food of choice for the seasoned traitor."
icon_state = "donkpocket"
- list_reagents = list(/datum/reagent/consumable/nutriment = 4)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/maltodextrin = 6)
cooked_type = /obj/item/reagent_containers/food/snacks/donkpocket/warm
filling_color = "#CD853F"
tastes = list("meat" = 2, "dough" = 2, "laziness" = 1)
@@ -468,7 +474,7 @@
name = "warm Donk-pocket"
desc = "The heated food of choice for the seasoned traitor."
bonus_reagents = list(/datum/reagent/medicine/omnizine = 3) //The original donk pocket has the most omnizine, can't beat the original on everything...
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 3)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 3, /datum/reagent/consumable/maltodextrin = 4)
cooked_type = null
tastes = list("meat" = 2, "dough" = 2, "laziness" = 1)
foodtype = GRAIN
@@ -477,7 +483,7 @@
name = "\improper Dank-pocket"
desc = "The food of choice for the seasoned botanist."
icon_state = "dankpocket"
- list_reagents = list(/datum/reagent/toxin/lipolicide = 3, /datum/reagent/drug/space_drugs = 3, /datum/reagent/consumable/nutriment = 4)
+ list_reagents = list(/datum/reagent/toxin/lipolicide = 3, /datum/reagent/drug/space_drugs = 3, /datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/maltodextrin = 2)
cooked_type = /obj/item/reagent_containers/food/snacks/donkpocket/dank/warm
filling_color = "#00FF00"
tastes = list("meat" = 2, "dough" = 2, "cannabis" = 2)
@@ -488,7 +494,7 @@
desc = "The food of choice for the baked botanist."
icon_state = "dankpocket"
bonus_reagents = list(/datum/reagent/medicine/omnizine = 1, /datum/reagent/drug/space_drugs = 2)
- list_reagents = list(/datum/reagent/toxin/lipolicide = 3, /datum/reagent/drug/space_drugs = 3, /datum/reagent/consumable/nutriment = 4)
+ list_reagents = list(/datum/reagent/toxin/lipolicide = 3, /datum/reagent/drug/space_drugs = 3, /datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/maltodextrin = 2)
cooked_type = null
tastes = list("meat" = 2, "dough" = 2, "cannabis" = 2)
foodtype = GRAIN | VEGETABLES
@@ -497,7 +503,7 @@
name = "\improper Spicy-pocket"
desc = "The classic snack food, now with a heat-activated spicy flair."
icon_state = "donkpocketspicy"
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/capsaicin = 2)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/capsaicin = 2, /datum/reagent/consumable/maltodextrin = 4)
cooked_type = /obj/item/reagent_containers/food/snacks/donkpocket/spicy/warm
filling_color = "#CD853F"
tastes = list("meat" = 2, "dough" = 2, "spice" = 1)
@@ -507,7 +513,7 @@
name = "warm Spicy-pocket"
desc = "The classic snack food, now maybe a bit too spicy."
bonus_reagents = list(/datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/capsaicin = 3)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/capsaicin = 2)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/capsaicin = 2, /datum/reagent/consumable/maltodextrin = 4)
tastes = list("meat" = 2, "dough" = 2, "weird spices" = 2)
foodtype = GRAIN
@@ -515,7 +521,7 @@
name = "\improper Teriyaki-pocket"
desc = "An east-asian take on the classic stationside snack."
icon_state = "donkpocketteriyaki"
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/soysauce = 2)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/soysauce = 2, /datum/reagent/consumable/maltodextrin = 4)
cooked_type = /obj/item/reagent_containers/food/snacks/donkpocket/teriyaki/warm
filling_color = "#CD853F"
tastes = list("meat" = 2, "dough" = 2, "soy sauce" = 2)
@@ -525,7 +531,7 @@
name = "warm Teriyaki-pocket"
desc = "An east-asian take on the classic stationside snack, now steamy and warm."
bonus_reagents = list(/datum/reagent/medicine/omnizine = 1)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/soysauce = 2)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/soysauce = 2, /datum/reagent/consumable/maltodextrin = 4)
tastes = list("meat" = 2, "dough" = 2, "soy sauce" = 2)
foodtype = GRAIN
@@ -533,7 +539,7 @@
name = "\improper Pizza-pocket"
desc = "Delicious, cheesy and surprisingly filling."
icon_state = "donkpocketpizza"
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/tomatojuice = 2)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/tomatojuice = 2, /datum/reagent/consumable/maltodextrin = 4)
cooked_type = /obj/item/reagent_containers/food/snacks/donkpocket/pizza/warm
filling_color = "#CD853F"
tastes = list("meat" = 2, "dough" = 2, "cheese"= 2)
@@ -543,7 +549,7 @@
name = "warm Pizza-pocket"
desc = "Delicious, cheesy, and even better when hot."
bonus_reagents = list(/datum/reagent/medicine/omnizine = 1)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/tomatojuice = 2)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/tomatojuice = 2, /datum/reagent/consumable/maltodextrin = 4)
tastes = list("meat" = 2, "dough" = 2, "melty cheese"= 2)
foodtype = GRAIN
@@ -551,7 +557,7 @@
name = "\improper Honk-pocket"
desc = "The award-winning donk-pocket that won the hearts of clowns and humans alike."
icon_state = "donkpocketbanana"
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/banana = 4)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/banana = 4, /datum/reagent/consumable/maltodextrin = 4)
cooked_type = /obj/item/reagent_containers/food/snacks/donkpocket/honk/warm
filling_color = "#XXXXXX"
tastes = list("banana" = 2, "dough" = 2, "children's antibiotics" = 1)
@@ -561,7 +567,7 @@
name = "warm Honk-pocket"
desc = "The award-winning donk-pocket, now warm and toasty."
bonus_reagents = list(/datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/laughter = 3)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/banana = 4, /datum/reagent/consumable/laughter = 3)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/banana = 4, /datum/reagent/consumable/laughter = 3, /datum/reagent/consumable/maltodextrin = 4)
tastes = list("dough" = 2, "children's antibiotics" = 1)
foodtype = GRAIN
@@ -569,7 +575,7 @@
name = "\improper Berry-pocket"
desc = "A relentlessly sweet donk-pocket first created for use in Operation Dessert Storm."
icon_state = "donkpocketberry"
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/berryjuice = 3)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/berryjuice = 3, /datum/reagent/consumable/maltodextrin = 4)
cooked_type = /obj/item/reagent_containers/food/snacks/donkpocket/berry/warm
filling_color = "#CD853F"
tastes = list("dough" = 2, "jam" = 2)
@@ -579,7 +585,7 @@
name = "warm Berry-pocket"
desc = "A relentlessly sweet donk-pocket, now warm and delicious."
bonus_reagents = list(/datum/reagent/medicine/omnizine = 1)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/berryjuice = 3)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/consumable/berryjuice = 3, /datum/reagent/consumable/maltodextrin = 4)
tastes = list("dough" = 2, "warm jam" = 2)
foodtype = GRAIN
@@ -587,7 +593,7 @@
name = "\improper Gondola-pocket"
desc = "The choice to use real gondola meat in the recipe is controversial, to say the least." //Only a monster would craft this.
icon_state = "donkpocketgondola"
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/tranquility = 5)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/tranquility = 5, /datum/reagent/consumable/maltodextrin = 4)
cooked_type = /obj/item/reagent_containers/food/snacks/donkpocket/gondola/warm
filling_color = "#CD853F"
tastes = list("meat" = 2, "dough" = 2, "inner peace" = 1)
@@ -597,7 +603,7 @@
name = "warm Gondola-pocket"
desc = "The choice to use real gondola meat in the recipe is controversial, to say the least."
bonus_reagents = list(/datum/reagent/medicine/omnizine = 1, /datum/reagent/tranquility = 5)
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/tranquility = 5)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 1, /datum/reagent/tranquility = 5, /datum/reagent/consumable/maltodextrin = 4)
tastes = list("meat" = 2, "dough" = 2, "inner peace" = 1)
foodtype = GRAIN
diff --git a/code/modules/food_and_drinks/food/snacks_vend.dm b/code/modules/food_and_drinks/food/snacks_vend.dm
index 0c3982cf4a7cf..1ba827ba63078 100644
--- a/code/modules/food_and_drinks/food/snacks_vend.dm
+++ b/code/modules/food_and_drinks/food/snacks_vend.dm
@@ -7,7 +7,7 @@
desc = "Nougat love it or hate it."
icon_state = "candy"
trash = /obj/item/trash/candy
- list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 3)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 3, /datum/reagent/consumable/maltodextrin = 3)
junkiness = 25
filling_color = "#D2691E"
tastes = list("candy" = 1)
@@ -20,7 +20,7 @@
icon_state = "sosjerky"
desc = "Beef jerky made from the finest space cows."
trash = /obj/item/trash/sosjerky
- list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 3, /datum/reagent/consumable/sodiumchloride = 2)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 3, /datum/reagent/consumable/sodiumchloride = 2, /datum/reagent/consumable/maltodextrin = 3)
junkiness = 25
filling_color = "#8B0000"
tastes = list("dried meat" = 1)
@@ -38,7 +38,7 @@
icon_state = "chips"
trash = /obj/item/trash/chips
bitesize = 1
- list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 3, /datum/reagent/consumable/sodiumchloride = 1)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 3, /datum/reagent/consumable/sodiumchloride = 1, /datum/reagent/consumable/maltodextrin = 3)
junkiness = 20
filling_color = "#FFD700"
tastes = list("salt" = 1, "crisps" = 1)
@@ -49,7 +49,7 @@
icon_state = "4no_raisins"
desc = "Best raisins in the universe. Not sure why."
trash = /obj/item/trash/raisins
- list_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/sugar = 4)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/sugar = 4, /datum/reagent/consumable/maltodextrin = 4)
junkiness = 25
filling_color = "#8B0000"
tastes = list("dried raisins" = 1)
@@ -69,7 +69,7 @@
name = "space twinkie"
icon_state = "space_twinkie"
desc = "Guaranteed to survive longer than you will."
- list_reagents = list(/datum/reagent/consumable/sugar = 4)
+ list_reagents = list(/datum/reagent/consumable/sugar = 4, /datum/reagent/consumable/maltodextrin = 2)
junkiness = 25
filling_color = "#FFD700"
foodtype = JUNKFOOD | GRAIN | SUGAR
@@ -82,7 +82,7 @@
desc = "Bite sized cheesie snacks that will honk all over your mouth."
icon_state = "cheesie_honkers"
trash = /obj/item/trash/cheesie
- list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 3)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 3, /datum/reagent/consumable/maltodextrin = 3)
junkiness = 25
filling_color = "#FFD700"
tastes = list("cheese" = 5, "crisps" = 2)
@@ -94,7 +94,7 @@
icon_state = "syndi_cakes"
desc = "An extremely moist snack cake that tastes just as good after being nuked."
trash = /obj/item/trash/syndi_cakes
- list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/doctor_delight = 5)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/doctor_delight = 5, /datum/reagent/consumable/maltodextrin = 4)
filling_color = "#F5F5DC"
tastes = list("sweetness" = 3, "cake" = 1)
foodtype = GRAIN | FRUIT | VEGETABLES
diff --git a/code/modules/food_and_drinks/kitchen_machinery/food_cart.dm b/code/modules/food_and_drinks/kitchen_machinery/food_cart.dm
index 4bad80b5a4537..b6950478f4699 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/food_cart.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/food_cart.dm
@@ -123,7 +123,7 @@
break
if(href_list["portion"])
- portion = CLAMP(input("How much drink do you want to dispense per glass?") as num, 0, 50)
+ portion = clamp(input("How much drink do you want to dispense per glass?") as num, 0, 50)
if(href_list["pour"] || href_list["m_pour"])
if(glasses-- <= 0)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
index e835d08b41dbe..34c979f870f86 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
@@ -197,7 +197,8 @@
skin = new typeofskin
log_combat(user, occupant, "gibbed")
- mob_occupant.death(1)
+ mob_occupant.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS)
+ mob_occupant.death(TRUE)
mob_occupant.ghostize()
set_occupant(null)
qdel(mob_occupant)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index 6585527e27e61..8339ff01f1e46 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -213,9 +213,9 @@
var/atom/movable/O = I
if (!QDELETED(O))
- var/md5name = rustg_hash_string(RUSTG_HASH_MD5, O.name) // This needs to happen because of a bug in a TGUI component, https://github.com/ractivejs/ractive/issues/744
- if (listofitems[md5name]) // which is fixed in a version we cannot use due to ie8 incompatibility
- listofitems[md5name]["amount"]++ // The good news is, #30519 made smartfridge UIs non-auto-updating
+ var/md5name = rustg_hash_string(RUSTG_HASH_MD5, O.name)
+ if (listofitems[md5name])
+ listofitems[md5name]["amount"]++
else
listofitems[md5name] = list("name" = O.name, "type" = O.type, "amount" = 1)
sort_list(listofitems)
diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm
index b12e76999a13c..32bf8497f2d1d 100644
--- a/code/modules/food_and_drinks/pizzabox.dm
+++ b/code/modules/food_and_drinks/pizzabox.dm
@@ -175,6 +175,17 @@
return
else
to_chat(user, "Close [open ? src : newbox] first!")
+ else if(istype(I, /obj/item/food/pizza))
+ if(open)
+ if(pizza)
+ to_chat(user, "[src] already has \a [pizza.name]!")
+ return
+ if(!user.transferItemToLoc(I, src))
+ return
+ pizza = I
+ to_chat(user, "You put [I] in [src].")
+ update_icon()
+ return
else if(istype(I, /obj/item/bombcore/miniature/pizza))
if(open && !bomb)
if(!user.transferItemToLoc(I, src))
diff --git a/code/modules/food_and_drinks/recipes/food_mixtures.dm b/code/modules/food_and_drinks/recipes/food_mixtures.dm
index 7694ec2ee5c12..44254ea74eae6 100644
--- a/code/modules/food_and_drinks/recipes/food_mixtures.dm
+++ b/code/modules/food_and_drinks/recipes/food_mixtures.dm
@@ -148,7 +148,7 @@
/datum/chemical_reaction/dough/on_reaction(datum/reagents/holder, created_volume)
var/location = get_turf(holder.my_atom)
for(var/i in 1 to created_volume)
- new /obj/item/reagent_containers/food/snacks/dough(location)
+ new /obj/item/food/dough(location)
/datum/chemical_reaction/cakebatter
name = "Cake Batter"
@@ -159,7 +159,7 @@
/datum/chemical_reaction/cakebatter/on_reaction(datum/reagents/holder, created_volume)
var/location = get_turf(holder.my_atom)
for(var/i in 1 to created_volume)
- new /obj/item/reagent_containers/food/snacks/cakebatter(location)
+ new /obj/item/food/cakebatter(location)
/datum/chemical_reaction/cakebatter/vegan
id = "vegancakebatter"
diff --git a/code/modules/food_and_drinks/recipes/processor_recipes.dm b/code/modules/food_and_drinks/recipes/processor_recipes.dm
index a11bb1866e3fe..f07884fce2c69 100644
--- a/code/modules/food_and_drinks/recipes/processor_recipes.dm
+++ b/code/modules/food_and_drinks/recipes/processor_recipes.dm
@@ -33,15 +33,15 @@
output = /obj/item/reagent_containers/food/snacks/soydope
/datum/food_processor_process/spaghetti
- input = /obj/item/reagent_containers/food/snacks/doughslice
+ input = /obj/item/food/doughslice
output = /obj/item/food/spaghetti/raw
/datum/food_processor_process/corn
input = /obj/item/reagent_containers/food/snacks/grown/corn
- output = /obj/item/reagent_containers/food/snacks/tortilla
+ output = /obj/item/food/tortilla
/datum/food_processor_process/tortilla
- input = /obj/item/reagent_containers/food/snacks/tortilla
+ input = /obj/item/food/tortilla
output = /obj/item/reagent_containers/food/snacks/cornchips
/datum/food_processor_process/parsnip
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm
index 9ce9c46b90998..ab46d52db3661 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm
@@ -88,7 +88,7 @@
/datum/crafting_recipe/food/butterbiscuit
name = "Butter Biscuit"
reqs = list(
- /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/food/bun = 1,
/obj/item/reagent_containers/food/snacks/butter = 1
)
result = /obj/item/food/butterbiscuit
@@ -97,7 +97,7 @@
/datum/crafting_recipe/food/butterdog
name = "Butterdog"
reqs = list(
- /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/food/bun = 1,
/obj/item/reagent_containers/food/snacks/butter = 3,
)
result = /obj/item/food/butterdog
@@ -120,7 +120,7 @@
name = "Hot dog"
reqs = list(
/datum/reagent/consumable/ketchup = 5,
- /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/food/bun = 1,
/obj/item/reagent_containers/food/snacks/sausage = 1
)
result = /obj/item/reagent_containers/food/snacks/hotdog
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
index be2360fe5ecc1..d494e0e607dbe 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
@@ -7,7 +7,7 @@
/datum/crafting_recipe/food/humanburger
name = "Human burger"
reqs = list(
- /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/food/bun = 1,
/obj/item/reagent_containers/food/snacks/meat/steak/plain/human = 1
)
parts = list(
@@ -20,7 +20,7 @@
name = "Burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/plain
@@ -30,7 +30,7 @@
name = "Corgi burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/slab/corgi = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/corgi
@@ -40,7 +40,7 @@
name = "Appendix burger"
reqs = list(
/obj/item/organ/appendix = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/appendix
subcategory = CAT_BURGER
@@ -49,7 +49,7 @@
name = "Brain burger"
reqs = list(
/obj/item/organ/brain = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/brain
subcategory = CAT_BURGER
@@ -58,7 +58,7 @@
name = "Xeno burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/xeno = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/xeno
subcategory = CAT_BURGER
@@ -67,7 +67,7 @@
name = "Bearger"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/bear = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/bearger
subcategory = CAT_BURGER
@@ -77,7 +77,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/carpmeat = 1,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/fish
subcategory = CAT_BURGER
@@ -86,7 +86,7 @@
name = "Tofu burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/tofu = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/tofu
subcategory = CAT_BURGER
@@ -96,7 +96,7 @@
reqs = list(
/obj/item/ectoplasm = 1,
/datum/reagent/consumable/sodiumchloride = 2,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/ghost
subcategory = CAT_BURGER
@@ -105,7 +105,7 @@
name = "Clown burger"
reqs = list(
/obj/item/clothing/mask/gas/clown_hat = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/clown
subcategory = CAT_BURGER
@@ -114,7 +114,7 @@
name = "Mime burger"
reqs = list(
/obj/item/clothing/mask/gas/mime = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/mime
subcategory = CAT_BURGER
@@ -124,7 +124,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/red = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/red
subcategory = CAT_BURGER
@@ -134,7 +134,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/orange = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/orange
subcategory = CAT_BURGER
@@ -144,7 +144,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/yellow = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/yellow
subcategory = CAT_BURGER
@@ -154,7 +154,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/green = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/green
subcategory = CAT_BURGER
@@ -164,7 +164,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/blue = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/blue
subcategory = CAT_BURGER
@@ -174,7 +174,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/purple = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/purple
subcategory = CAT_BURGER
@@ -184,7 +184,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/black = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/black
subcategory = CAT_BURGER
@@ -194,25 +194,16 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/white = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/white
subcategory = CAT_BURGER
/datum/crafting_recipe/food/spellburger
- name = "Spell burger"
- reqs = list(
- /obj/item/clothing/head/wizard/fake = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
- )
- result = /obj/item/food/burger/spell
- subcategory = CAT_BURGER
-
-/datum/crafting_recipe/food/spellburger2
name = "Spell burger"
reqs = list(
/obj/item/clothing/head/wizard = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/spell
subcategory = CAT_BURGER
@@ -222,7 +213,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 3,
/obj/item/reagent_containers/food/snacks/cheesewedge = 2,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/bigbite
subcategory = CAT_BURGER
@@ -237,7 +228,7 @@
/obj/item/reagent_containers/food/snacks/cheesewedge = 3,
/obj/item/reagent_containers/food/snacks/boiledegg = 1,
/obj/item/reagent_containers/food/snacks/meat/bacon = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/superbite
@@ -247,7 +238,7 @@
name = "Jelly burger"
reqs = list(
/datum/reagent/toxin/slimejelly = 5,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/jelly/slime
subcategory = CAT_BURGER
@@ -256,7 +247,7 @@
name = "Jelly burger"
reqs = list(
/datum/reagent/consumable/cherryjelly = 5,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/jelly/cherry
subcategory = CAT_BURGER
@@ -266,7 +257,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/reagent_containers/food/snacks/grown/ghost_chili = 2,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/fivealarm
subcategory = CAT_BURGER
@@ -275,7 +266,7 @@
name = "Rat burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/deadmouse = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/rat
subcategory = CAT_BURGER
@@ -284,7 +275,7 @@
name = "Home run baseball burger"
reqs = list(
/obj/item/melee/baseball_bat = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/baseball
subcategory = CAT_BURGER
@@ -293,7 +284,7 @@
name = "Bacon Burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/bacon = 3,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/baconburger
@@ -303,7 +294,7 @@
name = "Empowered Burger"
reqs = list(
/obj/item/stack/sheet/mineral/plasma = 2,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/empoweredburger
@@ -313,7 +304,7 @@
name = "Crab Burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/crab = 2,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/crab
@@ -324,7 +315,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/cheese
subcategory = CAT_BURGER
@@ -334,7 +325,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/soylentgreen = 1, //two full meats worth.
/obj/item/reagent_containers/food/snacks/cheesewedge = 2,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/soylent
subcategory = CAT_BURGER
@@ -344,7 +335,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/bbqribs = 1, //The sauce is already included in the ribs
/obj/item/reagent_containers/food/snacks/onion_slice = 1, //feel free to remove if too burdensome.
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/rib
subcategory = CAT_BURGER
@@ -354,7 +345,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/friedegg = 1,
/obj/item/reagent_containers/food/snacks/meat/bacon = 2,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/mcguffin
subcategory = CAT_BURGER
@@ -364,7 +355,7 @@
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/chicken = 1,
/datum/reagent/consumable/mayonnaise = 5,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/chicken
subcategory = CAT_BURGER
@@ -377,7 +368,7 @@
/datum/reagent/consumable/cooking_oil = 20,
/obj/item/reagent_containers/food/snacks/grown/nettle/death = 2, // closest thing to "grass of death"
/obj/item/reagent_containers/food/snacks/cheesewedge = 4,
- /obj/item/reagent_containers/food/snacks/bun = 1
+ /obj/item/food/bun = 1
)
result = /obj/item/food/burger/crazy
subcategory = CAT_BURGER
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
index 3844033a3fa29..9bd3052b6cf16 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
@@ -75,7 +75,7 @@
name = "Fish fingers"
reqs = list(
/datum/reagent/consumable/flour = 5,
- /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/food/bun = 1,
/obj/item/reagent_containers/food/snacks/carpmeat = 1
)
result = /obj/item/reagent_containers/food/snacks/fishfingers
@@ -125,16 +125,6 @@
result = /obj/item/reagent_containers/food/snacks/bearsteak
subcategory = CAT_MEAT
-/datum/crafting_recipe/food/enchiladas
- name = "Enchiladas"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/meat/cutlet = 2,
- /obj/item/reagent_containers/food/snacks/grown/chili = 2,
- /obj/item/reagent_containers/food/snacks/tortilla = 2
- )
- result = /obj/item/reagent_containers/food/snacks/enchiladas
- subcategory = CAT_MEAT
-
/datum/crafting_recipe/food/stewedsoymeat
name = "Stewed soymeat"
reqs = list(
@@ -165,7 +155,7 @@
/datum/crafting_recipe/food/rawkhinkali
name = "Raw Khinkali"
reqs = list(
- /obj/item/reagent_containers/food/snacks/doughslice = 1,
+ /obj/item/food/doughslice = 1,
/obj/item/reagent_containers/food/snacks/grown/garlic = 1,
/obj/item/reagent_containers/food/snacks/meatball = 1
)
@@ -175,7 +165,7 @@
/datum/crafting_recipe/food/pigblanket
name = "Pig in a Blanket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/food/bun = 1,
/obj/item/reagent_containers/food/snacks/butter = 1,
/obj/item/reagent_containers/food/snacks/meat/cutlet = 1
)
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm
new file mode 100644
index 0000000000000..f5ca4ea5a0115
--- /dev/null
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm
@@ -0,0 +1,114 @@
+// see code/module/crafting/table.dm
+
+// MEXICAN
+
+/datum/crafting_recipe/food/burrito
+ name ="Burrito"
+ reqs = list(
+ /obj/item/food/tortilla = 1,
+ /obj/item/reagent_containers/food/snacks/grown/soybeans = 2
+ )
+ result = /obj/item/food/burrito
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/cheesyburrito
+ name ="Cheesy burrito"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/cheesewedge = 2,
+ /obj/item/food/tortilla = 1,
+ /obj/item/reagent_containers/food/snacks/grown/soybeans = 1
+ )
+ result = /obj/item/food/cheesyburrito
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/carneburrito
+ name ="Carne de asada burrito"
+ reqs = list(
+ /obj/item/food/tortilla = 1,
+ /obj/item/reagent_containers/food/snacks/meat/cutlet = 2,
+ /obj/item/reagent_containers/food/snacks/grown/soybeans = 1
+ )
+ result = /obj/item/food/carneburrito
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/fuegoburrito
+ name ="Fuego plasma burrito"
+ reqs = list(
+ /obj/item/food/tortilla = 1,
+ /obj/item/reagent_containers/food/snacks/grown/ghost_chili = 2,
+ /obj/item/reagent_containers/food/snacks/grown/soybeans = 1
+ )
+ result = /obj/item/food/fuegoburrito
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/nachos
+ name ="Nachos"
+ reqs = list(
+ /datum/reagent/consumable/sodiumchloride = 1,
+ /obj/item/food/tortilla = 1
+ )
+ result = /obj/item/food/nachos
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/cheesynachos
+ name ="Cheesy nachos"
+ reqs = list(
+ /datum/reagent/consumable/sodiumchloride = 1,
+ /obj/item/reagent_containers/food/snacks/cheesewedge = 1,
+ /obj/item/food/tortilla = 1
+ )
+ result = /obj/item/food/cheesynachos
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/cubannachos
+ name ="Cuban nachos"
+ reqs = list(
+ /datum/reagent/consumable/ketchup = 5,
+ /obj/item/reagent_containers/food/snacks/grown/chili = 2,
+ /obj/item/food/tortilla = 1
+ )
+ result = /obj/item/food/cubannachos
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/taco
+ name ="Classic Taco"
+ reqs = list(
+ /obj/item/food/tortilla = 1,
+ /obj/item/reagent_containers/food/snacks/cheesewedge = 1,
+ /obj/item/reagent_containers/food/snacks/meat/cutlet = 1,
+ /obj/item/reagent_containers/food/snacks/grown/cabbage = 1,
+ )
+ result = /obj/item/food/taco
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/tacoplain
+ name ="Plain Taco"
+ reqs = list(
+ /obj/item/food/tortilla = 1,
+ /obj/item/reagent_containers/food/snacks/cheesewedge = 1,
+ /obj/item/reagent_containers/food/snacks/meat/cutlet = 1,
+ )
+ result = /obj/item/food/taco/plain
+ subcategory = CAT_MEXICAN
+
+/datum/crafting_recipe/food/enchiladas
+ name = "Enchiladas"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/meat/cutlet = 2,
+ /obj/item/reagent_containers/food/snacks/grown/chili = 2,
+ /obj/item/food/tortilla = 2
+ )
+ result = /obj/item/food/enchiladas
+ subcategory = CAT_MEAT
+
+/datum/crafting_recipe/food/stuffedlegion
+ name = "Stuffed legion"
+ time = 40
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/meat/steak/goliath = 1,
+ /obj/item/organ/regenerative_core/legion = 1,
+ /datum/reagent/consumable/ketchup = 2,
+ /datum/reagent/consumable/capsaicin = 2
+ )
+ result = /obj/item/food/stuffedlegion
+ subcategory = CAT_MEXICAN
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
index f10dc0f9a1d06..7c45a9b86b3a7 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
@@ -100,7 +100,7 @@
time = 40
reqs = list(/datum/reagent/consumable/sodiumchloride = 1,
/datum/reagent/consumable/blackpepper = 1,
- /obj/item/reagent_containers/food/snacks/pastrybase = 2
+ /obj/item/food/pastrybase = 2
)
result = /obj/item/food/baguette
subcategory = CAT_MISCFOOD
@@ -143,45 +143,6 @@
result = /obj/item/reagent_containers/food/snacks/twobread
subcategory = CAT_MISCFOOD
-/datum/crafting_recipe/food/burrito
- name ="Burrito"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/tortilla = 1,
- /obj/item/reagent_containers/food/snacks/grown/soybeans = 2
- )
- result = /obj/item/reagent_containers/food/snacks/burrito
- subcategory = CAT_MISCFOOD
-
-/datum/crafting_recipe/food/cheesyburrito
- name ="Cheesy burrito"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/tortilla = 1,
- /obj/item/reagent_containers/food/snacks/cheesewedge = 2,
- /obj/item/reagent_containers/food/snacks/grown/soybeans = 1
- )
- result = /obj/item/reagent_containers/food/snacks/cheesyburrito
- subcategory = CAT_MISCFOOD
-
-/datum/crafting_recipe/food/carneburrito
- name ="Carne de asada burrito"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/tortilla = 1,
- /obj/item/reagent_containers/food/snacks/meat/cutlet = 2,
- /obj/item/reagent_containers/food/snacks/grown/soybeans = 1
- )
- result = /obj/item/reagent_containers/food/snacks/carneburrito
- subcategory = CAT_MISCFOOD
-
-/datum/crafting_recipe/food/fuegoburrito
- name ="Fuego plasma burrito"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/tortilla = 1,
- /obj/item/reagent_containers/food/snacks/grown/ghost_chili = 2,
- /obj/item/reagent_containers/food/snacks/grown/soybeans = 1
- )
- result = /obj/item/reagent_containers/food/snacks/fuegoburrito
- subcategory = CAT_MISCFOOD
-
/datum/crafting_recipe/food/melonfruitbowl
name ="Melon fruit bowl"
reqs = list(
@@ -195,35 +156,6 @@
result = /obj/item/reagent_containers/food/snacks/melonfruitbowl
subcategory = CAT_MISCFOOD
-/datum/crafting_recipe/food/nachos
- name ="Nachos"
- reqs = list(
- /datum/reagent/consumable/sodiumchloride = 1,
- /obj/item/reagent_containers/food/snacks/tortilla = 1
- )
- result = /obj/item/reagent_containers/food/snacks/nachos
- subcategory = CAT_MISCFOOD
-
-/datum/crafting_recipe/food/cheesynachos
- name ="Cheesy nachos"
- reqs = list(
- /datum/reagent/consumable/sodiumchloride = 1,
- /obj/item/reagent_containers/food/snacks/cheesewedge = 1,
- /obj/item/reagent_containers/food/snacks/tortilla = 1
- )
- result = /obj/item/reagent_containers/food/snacks/cheesynachos
- subcategory = CAT_MISCFOOD
-
-/datum/crafting_recipe/food/cubannachos
- name ="Cuban nachos"
- reqs = list(
- /datum/reagent/consumable/ketchup = 5,
- /obj/item/reagent_containers/food/snacks/grown/chili = 2,
- /obj/item/reagent_containers/food/snacks/tortilla = 1
- )
- result = /obj/item/reagent_containers/food/snacks/cubannachos
- subcategory = CAT_MISCFOOD
-
/datum/crafting_recipe/food/melonkeg
name ="Melon keg"
reqs = list(
@@ -244,24 +176,11 @@
result = /obj/item/reagent_containers/food/snacks/honeybar
subcategory = CAT_MISCFOOD
-
-/datum/crafting_recipe/food/stuffedlegion
- name = "Stuffed legion"
- time = 40
- reqs = list(
- /obj/item/reagent_containers/food/snacks/meat/steak/goliath = 1,
- /obj/item/organ/regenerative_core/legion = 1,
- /datum/reagent/consumable/ketchup = 2,
- /datum/reagent/consumable/capsaicin = 2
- )
- result = /obj/item/reagent_containers/food/snacks/stuffedlegion
- subcategory = CAT_MISCFOOD
-
/datum/crafting_recipe/food/powercrepe
name = "Powercrepe"
time = 40
reqs = list(
- /obj/item/reagent_containers/food/snacks/flatdough = 1,
+ /obj/item/food/flatdough = 1,
/datum/reagent/consumable/milk = 1,
/datum/reagent/consumable/cherryjelly = 5,
/obj/item/stock_parts/cell/super =1,
@@ -270,27 +189,6 @@
result = /obj/item/reagent_containers/food/snacks/powercrepe
subcategory = CAT_MISCFOOD
-/datum/crafting_recipe/food/taco
- name ="Classic Taco"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/tortilla = 1,
- /obj/item/reagent_containers/food/snacks/cheesewedge = 1,
- /obj/item/reagent_containers/food/snacks/meat/cutlet = 1,
- /obj/item/reagent_containers/food/snacks/grown/cabbage = 1,
- )
- result = /obj/item/reagent_containers/food/snacks/taco
- subcategory = CAT_MISCFOOD
-
-/datum/crafting_recipe/food/tacoplain
- name ="Plain Taco"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/tortilla = 1,
- /obj/item/reagent_containers/food/snacks/cheesewedge = 1,
- /obj/item/reagent_containers/food/snacks/meat/cutlet = 1,
- )
- result = /obj/item/reagent_containers/food/snacks/taco/plain
- subcategory = CAT_MISCFOOD
-
/datum/crafting_recipe/food/branrequests
name = "Bran Requests Cereal"
reqs = list(
@@ -326,7 +224,7 @@
/datum/crafting_recipe/food/crab_rangoon
name = "Crab Rangoon"
reqs = list(
- /obj/item/reagent_containers/food/snacks/doughslice = 1,
+ /obj/item/food/doughslice = 1,
/datum/reagent/consumable/cream = 5,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
/obj/item/reagent_containers/food/snacks/meat/rawcrab = 1
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
index e1f698a345f6c..a208118cde8ba 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
@@ -8,7 +8,7 @@
name = "Donut"
reqs = list(
/datum/reagent/consumable/sugar = 1,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/donut/plain
subcategory = CAT_PASTRY
@@ -19,7 +19,7 @@
reqs = list(
/datum/reagent/consumable/frostoil = 5,
/datum/reagent/consumable/capsaicin = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/donut/chaos
@@ -28,7 +28,7 @@
name = "Meat donut"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/rawcutlet = 1,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/donut/meat
@@ -36,7 +36,7 @@
name = "Jelly donut"
reqs = list(
/datum/reagent/consumable/berryjuice = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/donut/jelly/plain
@@ -44,7 +44,7 @@
name = "Slime jelly donut"
reqs = list(
/datum/reagent/toxin/slimejelly = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/donut/jelly/slimejelly/plain
@@ -254,7 +254,7 @@
time = 15
name = "Waffles"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 2
+ /obj/item/food/pastrybase = 2
)
result = /obj/item/reagent_containers/food/snacks/waffles
subcategory = CAT_PASTRY
@@ -263,7 +263,7 @@
/datum/crafting_recipe/food/soylenviridians
name = "Soylent viridians"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 2,
+ /obj/item/food/pastrybase = 2,
/obj/item/reagent_containers/food/snacks/grown/soybeans = 1
)
result = /obj/item/reagent_containers/food/snacks/soylenviridians
@@ -272,7 +272,7 @@
/datum/crafting_recipe/food/soylentgreen
name = "Soylent green"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 2,
+ /obj/item/food/pastrybase = 2,
/obj/item/reagent_containers/food/snacks/meat/slab/human = 2
)
result = /obj/item/reagent_containers/food/snacks/soylentgreen
@@ -283,7 +283,7 @@
name = "Roffle waffles"
reqs = list(
/datum/reagent/drug/mushroomhallucinogen = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 2
+ /obj/item/food/pastrybase = 2
)
result = /obj/item/reagent_containers/food/snacks/rofflewaffles
subcategory = CAT_PASTRY
@@ -291,7 +291,7 @@
/datum/crafting_recipe/food/pancakes
name = "Pancake"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/pancakes
subcategory = CAT_PASTRY
@@ -299,7 +299,7 @@
/datum/crafting_recipe/food/bbpancakes
name = "Blueberry pancake"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/berries = 1
)
result = /obj/item/reagent_containers/food/snacks/pancakes/blueberry
@@ -308,7 +308,7 @@
/datum/crafting_recipe/food/ccpancakes
name = "Chocolate chip pancake"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/chocolatebar = 1
)
result = /obj/item/reagent_containers/food/snacks/pancakes/chocolatechip
@@ -321,7 +321,7 @@
time = 15
name = "Donk-pocket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/meatball = 1
)
result = /obj/item/reagent_containers/food/snacks/donkpocket
@@ -331,7 +331,7 @@
time = 15
name = "Dank-pocket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/cannabis = 1
)
result = /obj/item/reagent_containers/food/snacks/donkpocket/dank
@@ -341,7 +341,7 @@
time = 15
name = "Spicy-pocket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/chili = 1
)
result = /obj/item/reagent_containers/food/snacks/donkpocket/spicy
@@ -351,7 +351,7 @@
time = 15
name = "Teriyaki-pocket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/datum/reagent/consumable/soysauce = 3
)
result = /obj/item/reagent_containers/food/snacks/donkpocket/teriyaki
@@ -361,7 +361,7 @@
time = 15
name = "Pizza-pocket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/tomato = 1
)
result = /obj/item/reagent_containers/food/snacks/donkpocket/pizza
@@ -371,7 +371,7 @@
time = 15
name = "Honk-Pocket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/banana = 1,
/datum/reagent/consumable/sugar = 3
)
@@ -382,7 +382,7 @@
time = 15
name = "Berry-pocket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/berries = 1
)
result = /obj/item/reagent_containers/food/snacks/donkpocket/berry
@@ -392,7 +392,7 @@
time = 15
name = "Gondola-pocket"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/datum/reagent/tranquility = 5
)
result = /obj/item/reagent_containers/food/snacks/donkpocket/gondola
@@ -405,7 +405,7 @@
name = "Muffin"
reqs = list(
/datum/reagent/consumable/milk = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/muffin
subcategory = CAT_PASTRY
@@ -414,7 +414,7 @@
name = "Berry muffin"
reqs = list(
/datum/reagent/consumable/milk = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/berries = 1
)
result = /obj/item/reagent_containers/food/snacks/muffin/berry
@@ -424,7 +424,7 @@
name = "Booberry muffin"
reqs = list(
/datum/reagent/consumable/milk = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/berries = 1,
/obj/item/ectoplasm = 1
)
@@ -435,7 +435,7 @@
name = "Moffin"
reqs = list(
/datum/reagent/consumable/milk = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/stack/sheet/cotton/cloth = 1,
)
result = /obj/item/reagent_containers/food/snacks/muffin/moffin
@@ -458,7 +458,7 @@
name = "Meat bun"
reqs = list(
/datum/reagent/consumable/soysauce = 5,
- /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/food/bun = 1,
/obj/item/reagent_containers/food/snacks/meatball = 1,
/obj/item/reagent_containers/food/snacks/grown/cabbage = 1
)
@@ -480,7 +480,7 @@
name = "Sugar cookie"
reqs = list(
/datum/reagent/consumable/sugar = 5,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/sugarcookie
subcategory = CAT_PASTRY
@@ -489,7 +489,7 @@
time = 15
name = "Fortune cookie"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/paper = 1
)
parts = list(
@@ -503,7 +503,7 @@
name = "Poppy pretzel"
reqs = list(
/obj/item/seeds/flower/poppy = 1,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ /obj/item/food/pastrybase = 1
)
result = /obj/item/reagent_containers/food/snacks/poppypretzel
subcategory = CAT_PASTRY
@@ -512,7 +512,7 @@
time = 15
name = "Plumphelmet biscuit"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/mushroom/plumphelmet = 1
)
result = /obj/item/reagent_containers/food/snacks/plumphelmetbiscuit
@@ -523,7 +523,7 @@
name = "Cracker"
reqs = list(
/datum/reagent/consumable/sodiumchloride = 1,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
)
result = /obj/item/reagent_containers/food/snacks/cracker
subcategory = CAT_PASTRY
@@ -532,7 +532,7 @@
name = "Choco cornet"
reqs = list(
/datum/reagent/consumable/sodiumchloride = 1,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/chocolatebar = 1
)
result = /obj/item/reagent_containers/food/snacks/chococornet
@@ -541,7 +541,7 @@
/datum/crafting_recipe/food/oatmealcookie
name = "Oatmeal cookie"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/oat = 1
)
result = /obj/item/reagent_containers/food/snacks/oatmealcookie
@@ -551,7 +551,7 @@
name = "Raisin cookie"
reqs = list(
/obj/item/reagent_containers/food/snacks/no_raisin = 1,
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/oat = 1
)
result = /obj/item/reagent_containers/food/snacks/raisincookie
@@ -560,7 +560,7 @@
/datum/crafting_recipe/food/cherrycupcake
name = "Cherry cupcake"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/cherries = 1
)
result = /obj/item/reagent_containers/food/snacks/cherrycupcake
@@ -569,7 +569,7 @@
/datum/crafting_recipe/food/bluecherrycupcake
name = "Blue cherry cupcake"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/reagent_containers/food/snacks/grown/bluecherries = 1
)
result = /obj/item/reagent_containers/food/snacks/cherrycupcake/blue
@@ -578,7 +578,7 @@
/datum/crafting_recipe/food/honeybun
name = "Honey bun"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/datum/reagent/consumable/honey = 5
)
result = /obj/item/reagent_containers/food/snacks/honeybun
@@ -587,7 +587,7 @@
/datum/crafting_recipe/food/ravtart
name = "Rav'tart"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/food/pastrybase = 1,
/obj/item/stack/sheet/bronze = 1,
/obj/item/reagent_containers/food/snacks/grown/berries = 2,
/obj/item/reagent_containers/food/snacks/grown/citrus/orange = 1
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pie.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pie.dm
index af06b908d6012..296f522cb3d07 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pie.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pie.dm
@@ -201,7 +201,7 @@
name = "Baklava pie"
reqs = list(
/obj/item/reagent_containers/food/snacks/butter = 2,
- /obj/item/reagent_containers/food/snacks/tortilla = 4, //Layers
+ /obj/item/food/tortilla = 4, //Layers
/obj/item/seeds/wheat/oat = 4
)
result = /obj/item/reagent_containers/food/snacks/pie/baklava
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pizza.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pizza.dm
index 89206e1ad7da8..d4e4d08465e9f 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pizza.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pizza.dm
@@ -6,7 +6,7 @@
/datum/crafting_recipe/food/margheritapizza
name = "Margherita pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/cheesewedge = 4,
/obj/item/reagent_containers/food/snacks/grown/tomato = 1
)
@@ -16,7 +16,7 @@
/datum/crafting_recipe/food/meatpizza
name = "Meat pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/meat/cutlet = 4,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
/obj/item/reagent_containers/food/snacks/grown/tomato = 1
@@ -27,7 +27,7 @@
/datum/crafting_recipe/food/arnold
name = "Arnold pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/meat/cutlet = 3,
/obj/item/ammo_casing/c9mm = 8,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
@@ -39,7 +39,7 @@
/datum/crafting_recipe/food/mushroompizza
name = "Mushroom pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/grown/mushroom = 5
)
result = /obj/item/food/pizza/mushroom
@@ -48,7 +48,7 @@
/datum/crafting_recipe/food/vegetablepizza
name = "Vegetable pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/grown/eggplant = 1,
/obj/item/reagent_containers/food/snacks/grown/carrot = 1,
/obj/item/reagent_containers/food/snacks/grown/corn = 1,
@@ -60,7 +60,7 @@
/datum/crafting_recipe/food/donkpocketpizza
name = "Donkpocket pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/donkpocket/warm = 3,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
/obj/item/reagent_containers/food/snacks/grown/tomato = 1
@@ -71,7 +71,7 @@
/datum/crafting_recipe/food/dankpizza
name = "Dank pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/grown/ambrosia/vulgaris = 3,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
/obj/item/reagent_containers/food/snacks/grown/tomato = 1
@@ -82,7 +82,7 @@
/datum/crafting_recipe/food/sassysagepizza
name = "Sassysage pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/meatball = 3,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
/obj/item/reagent_containers/food/snacks/grown/tomato = 1
@@ -93,7 +93,7 @@
/datum/crafting_recipe/food/pineapplepizza
name = "Hawaiian pizza"
reqs = list(
- /obj/item/reagent_containers/food/snacks/pizzabread = 1,
+ /obj/item/food/pizzabread = 1,
/obj/item/reagent_containers/food/snacks/meat/cutlet = 2,
/obj/item/reagent_containers/food/snacks/pineappleslice = 3,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
diff --git a/code/modules/games/tarot.dm b/code/modules/games/tarot.dm
new file mode 100644
index 0000000000000..8be9bf1676e22
--- /dev/null
+++ b/code/modules/games/tarot.dm
@@ -0,0 +1,29 @@
+//Some silly tarot cards for predicting when the Clown will die. Ported from TG. https://github.com/tgstation/tgstation/pull/51318/
+/obj/item/toy/cards/deck/tarot
+ name = "Tarot Card Deck"
+ desc = "A full 78 card deck of Tarot Cards, no refunds on false predicitons."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "deck_tarot_full"
+ deckstyle = "tarot"
+
+/obj/item/toy/cards/deck/tarot/populate_deck()
+ for(var/suit in list("Cups", "Wands", "Swords", "Coins"))
+ for(var/i in 1 to 10)
+ cards += "[i] of [suit]"
+ for(var/person in list("Page", "Champion", "Queen", "King"))
+ cards += "[person] of [suit]"
+ for(var/trump in list("The Magician", "The High Priestess", "The Empress", "The Emperor", "The Hierophant", "The Lover", "The Chariot", "Justice", "The Hermit", "The Wheel of Fortune", "Strength", "The Hanged Man", "Death", "Temperance", "The Devil", "The Tower", "The Star", "The Moon", "The Sun", "Judgement", "The World", "The Fool"))
+ cards += "[trump]"
+
+/obj/item/toy/cards/deck/tarot/draw_card(mob/user)
+ . = ..()
+ if(prob(50))
+ var/obj/item/toy/cards/singlecard/C = .
+ if(!C)
+ return FALSE
+
+ var/matrix/M = matrix()
+ M.Turn(180)
+ C.transform = M
+
+
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index 7daf32062ecda..e9037774051b1 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -27,18 +27,18 @@
juice_results = list(/datum/reagent/consumable/banana = 0)
distill_reagent = /datum/reagent/consumable/ethanol/bananahonk
-/obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user)
+/obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/living/user)
user.visible_message("[user] is aiming [src] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1)
sleep(25)
if(!user)
- return (OXYLOSS)
+ return OXYLOSS
user.say("BANG!", forced = /datum/reagent/consumable/banana)
sleep(25)
if(!user)
- return (OXYLOSS)
+ return OXYLOSS
user.visible_message("[user] laughs so hard they begin to suffocate!")
- return (OXYLOSS)
+ return OXYLOSS
//Banana Peel
/obj/item/grown/bananapeel
@@ -54,10 +54,10 @@
throw_speed = 3
throw_range = 7
-/obj/item/grown/bananapeel/suicide_act(mob/user)
+/obj/item/grown/bananapeel/suicide_act(mob/living/user)
user.visible_message("[user] is deliberately slipping on [src]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/misc/slip.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
// Mimana - invisible sprites are totally a feature!
diff --git a/code/modules/hydroponics/grown/cotton.dm b/code/modules/hydroponics/grown/cotton.dm
index 34ff4696efd1e..07cfee24cab52 100644
--- a/code/modules/hydroponics/grown/cotton.dm
+++ b/code/modules/hydroponics/grown/cotton.dm
@@ -48,7 +48,7 @@
//reinforced mutated variant
/obj/item/seeds/cotton/durathread
name = "pack of durathread seeds"
- desc = "A pack of seeds that'll grow into an extremely durable thread that could easily rival plasteel if woven properly."
+ desc = "A pack of seeds that'll grow into an extremely durable thread that could easily rival plasteel if woven properly. In its woven state, it is incredibly effective at resisting high-energy ballistic attacks making it sought after by organisations that specialise in personal defense."
icon_state = "seed-durathread"
species = "durathread"
plantname = "Durathread"
diff --git a/code/modules/hydroponics/grown/kudzu.dm b/code/modules/hydroponics/grown/kudzu.dm
index c3aa666ccc97f..799a3aca66511 100644
--- a/code/modules/hydroponics/grown/kudzu.dm
+++ b/code/modules/hydroponics/grown/kudzu.dm
@@ -21,10 +21,10 @@
S.mutations = mutations.Copy()
return S
-/obj/item/seeds/kudzu/suicide_act(mob/user)
+/obj/item/seeds/kudzu/suicide_act(mob/living/user)
user.visible_message("[user] swallows the pack of kudzu seeds! It looks like [user.p_theyre()] trying to commit suicide!")
plant(user)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/seeds/kudzu/proc/plant(mob/user)
if(isspaceturf(user.loc))
diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm
index ff19627c3d6c2..7c2851e06426f 100644
--- a/code/modules/hydroponics/grown/melon.dm
+++ b/code/modules/hydroponics/grown/melon.dm
@@ -14,7 +14,7 @@
mutatelist = list(/obj/item/seeds/watermelon/holy, /obj/item/seeds/watermelon/ballolon)
reagents_add = list(/datum/reagent/water = 0.2, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.2)
-/obj/item/seeds/watermelon/suicide_act(mob/user)
+/obj/item/seeds/watermelon/suicide_act(mob/living/user)
user.visible_message("[user] is swallowing [src]! It looks like [user.p_theyre()] trying to commit suicide!")
user.gib()
new product(drop_location())
diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm
index 154a3cdbcda33..ca826554c87cc 100644
--- a/code/modules/hydroponics/grown/nettle.dm
+++ b/code/modules/hydroponics/grown/nettle.dm
@@ -45,7 +45,7 @@
throw_range = 3
attack_verb = list("stung")
-/obj/item/reagent_containers/food/snacks/grown/nettle/suicide_act(mob/user)
+/obj/item/reagent_containers/food/snacks/grown/nettle/suicide_act(mob/living/user)
user.visible_message("[user] is eating some of [src]! It looks like [user.p_theyre()] trying to commit suicide!")
return (BRUTELOSS|TOXLOSS)
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 98ae2bc0a3533..1b364a9d23c96 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -27,9 +27,9 @@
volume = 100
list_reagents = list(/datum/reagent/toxin/plantbgone/weedkiller = 100)
-/obj/item/reagent_containers/spray/weedspray/suicide_act(mob/user)
+/obj/item/reagent_containers/spray/weedspray/suicide_act(mob/living/user)
user.visible_message("[user] is huffing [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (TOXLOSS)
+ return TOXLOSS
/obj/item/reagent_containers/spray/pestspray // -- Skie
desc = "It's some pest eliminator spray! Do not inhale!"
@@ -42,9 +42,9 @@
volume = 100
list_reagents = list(/datum/reagent/toxin/pestkiller = 100)
-/obj/item/reagent_containers/spray/pestspray/suicide_act(mob/user)
+/obj/item/reagent_containers/spray/pestspray/suicide_act(mob/living/user)
user.visible_message("[user] is huffing [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (TOXLOSS)
+ return TOXLOSS
/obj/item/cultivator
name = "cultivator"
@@ -62,9 +62,9 @@
attack_verb = list("slashed", "sliced", "cut", "clawed")
hitsound = 'sound/weapons/bladeslice.ogg'
-/obj/item/cultivator/suicide_act(mob/user)
+/obj/item/cultivator/suicide_act(mob/living/user)
user.visible_message("[user] is scratching [user.p_their()] back as hard as [user.p_they()] can with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/hatchet
name = "hatchet"
@@ -90,10 +90,10 @@
. = ..()
AddComponent(/datum/component/butchering, 70, 100)
-/obj/item/hatchet/suicide_act(mob/user)
+/obj/item/hatchet/suicide_act(mob/living/user)
user.visible_message("[user] is chopping at [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(src, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/scythe
icon_state = "scythe0"
@@ -118,7 +118,7 @@
. = ..()
AddComponent(/datum/component/butchering, 90, 105)
-/obj/item/scythe/suicide_act(mob/user)
+/obj/item/scythe/suicide_act(mob/living/user)
user.visible_message("[user] is beheading [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
if(iscarbon(user))
var/mob/living/carbon/C = user
@@ -126,7 +126,7 @@
if(BP)
BP.drop_limb()
playsound(src,pick('sound/misc/desecration-01.ogg','sound/misc/desecration-02.ogg','sound/misc/desecration-01.ogg') ,50, 1, -1)
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/scythe/pre_attack(atom/A, mob/living/user, params)
if(swiping || !istype(A, /obj/structure/spacevine) || get_turf(A) == get_turf(user))
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index bbc176043c518..6d82f397c7884 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -939,26 +939,26 @@
/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds.///
/obj/machinery/hydroponics/proc/adjustNutri(adjustamt)
- nutrilevel = CLAMP(nutrilevel + adjustamt, 0, maxnutri)
+ nutrilevel = clamp(nutrilevel + adjustamt, 0, maxnutri)
/obj/machinery/hydroponics/proc/adjustWater(adjustamt)
- waterlevel = CLAMP(waterlevel + adjustamt, 0, maxwater)
+ waterlevel = clamp(waterlevel + adjustamt, 0, maxwater)
if(adjustamt>0)
adjustToxic(-round(adjustamt/4))//Toxicity dilutation code. The more water you put in, the lesser the toxin concentration.
/obj/machinery/hydroponics/proc/adjustHealth(adjustamt)
if(myseed && !dead)
- plant_health = CLAMP(plant_health + adjustamt, 0, myseed.endurance)
+ plant_health = clamp(plant_health + adjustamt, 0, myseed.endurance)
/obj/machinery/hydroponics/proc/adjustToxic(adjustamt)
- toxic = CLAMP(toxic + adjustamt, 0, 100)
+ toxic = clamp(toxic + adjustamt, 0, 100)
/obj/machinery/hydroponics/proc/adjustPests(adjustamt)
- pestlevel = CLAMP(pestlevel + adjustamt, 0, 10)
+ pestlevel = clamp(pestlevel + adjustamt, 0, 10)
/obj/machinery/hydroponics/proc/adjustWeeds(adjustamt)
- weedlevel = CLAMP(weedlevel + adjustamt, 0, 10)
+ weedlevel = clamp(weedlevel + adjustamt, 0, 10)
/obj/machinery/hydroponics/proc/spawnplant() // why would you put strange reagent in a hydro tray you monster I bet you also feed them blood
var/list/livingplants = list(/mob/living/simple_animal/hostile/tree, /mob/living/simple_animal/hostile/killertomato)
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 5987fc61442c9..bbeac338500b1 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -253,7 +253,7 @@
/// Setters procs ///
/obj/item/seeds/proc/adjust_yield(adjustamt)
if(yield != -1) // Unharvestable shouldn't suddenly turn harvestable
- yield = CLAMP(yield + adjustamt, 0, 10)
+ yield = clamp(yield + adjustamt, 0, 10)
if(yield <= 0 && get_gene(/datum/plant_gene/trait/plant_type/fungal_metabolism))
yield = 1 // Mushrooms always have a minimum yield of 1.
@@ -262,39 +262,39 @@
C.value = yield
/obj/item/seeds/proc/adjust_lifespan(adjustamt)
- lifespan = CLAMP(lifespan + adjustamt, 10, 100)
+ lifespan = clamp(lifespan + adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/lifespan)
if(C)
C.value = lifespan
/obj/item/seeds/proc/adjust_endurance(adjustamt)
- endurance = CLAMP(endurance + adjustamt, 10, 100)
+ endurance = clamp(endurance + adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/endurance)
if(C)
C.value = endurance
/obj/item/seeds/proc/adjust_production(adjustamt)
if(yield != -1)
- production = CLAMP(production + adjustamt, 1, 10)
+ production = clamp(production + adjustamt, 1, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/production)
if(C)
C.value = production
/obj/item/seeds/proc/adjust_potency(adjustamt)
if(potency != -1)
- potency = CLAMP(potency + adjustamt, 0, 100)
+ potency = clamp(potency + adjustamt, 0, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/potency)
if(C)
C.value = potency
/obj/item/seeds/proc/adjust_weed_rate(adjustamt)
- weed_rate = CLAMP(weed_rate + adjustamt, 0, 10)
+ weed_rate = clamp(weed_rate + adjustamt, 0, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_rate)
if(C)
C.value = weed_rate
/obj/item/seeds/proc/adjust_weed_chance(adjustamt)
- weed_chance = CLAMP(weed_chance + adjustamt, 0, 67)
+ weed_chance = clamp(weed_chance + adjustamt, 0, 67)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_chance)
if(C)
C.value = weed_chance
@@ -303,7 +303,7 @@
/obj/item/seeds/proc/set_yield(adjustamt)
if(yield != -1) // Unharvestable shouldn't suddenly turn harvestable
- yield = CLAMP(adjustamt, 0, 10)
+ yield = clamp(adjustamt, 0, 10)
if(yield <= 0 && get_gene(/datum/plant_gene/trait/plant_type/fungal_metabolism))
yield = 1 // Mushrooms always have a minimum yield of 1.
@@ -312,39 +312,39 @@
C.value = yield
/obj/item/seeds/proc/set_lifespan(adjustamt)
- lifespan = CLAMP(adjustamt, 10, 100)
+ lifespan = clamp(adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/lifespan)
if(C)
C.value = lifespan
/obj/item/seeds/proc/set_endurance(adjustamt)
- endurance = CLAMP(adjustamt, 10, 100)
+ endurance = clamp(adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/endurance)
if(C)
C.value = endurance
/obj/item/seeds/proc/set_production(adjustamt)
if(yield != -1)
- production = CLAMP(adjustamt, 1, 10)
+ production = clamp(adjustamt, 1, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/production)
if(C)
C.value = production
/obj/item/seeds/proc/set_potency(adjustamt)
if(potency != -1)
- potency = CLAMP(adjustamt, 0, 100)
+ potency = clamp(adjustamt, 0, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/potency)
if(C)
C.value = potency
/obj/item/seeds/proc/set_weed_rate(adjustamt)
- weed_rate = CLAMP(adjustamt, 0, 10)
+ weed_rate = clamp(adjustamt, 0, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_rate)
if(C)
C.value = weed_rate
/obj/item/seeds/proc/set_weed_chance(adjustamt)
- weed_chance = CLAMP(adjustamt, 0, 67)
+ weed_chance = clamp(adjustamt, 0, 67)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_chance)
if(C)
C.value = weed_chance
diff --git a/code/modules/instruments/items.dm b/code/modules/instruments/items.dm
index 8f8e716f63cce..dde806fa765e5 100644
--- a/code/modules/instruments/items.dm
+++ b/code/modules/instruments/items.dm
@@ -27,9 +27,9 @@
/obj/item/instrument/proc/should_stop_playing(mob/user)
return user.incapacitated() || !((loc == user) || (isturf(loc) && Adjacent(user))) // sorry, no more TK playing.
-/obj/item/instrument/suicide_act(mob/user)
+/obj/item/instrument/suicide_act(mob/living/user)
user.visible_message("[user] begins to play 'Gloomy Sunday'! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
+ return BRUTELOSS
/obj/item/instrument/attack_self(mob/user)
if(!user.IsAdvancedToolUser())
diff --git a/code/modules/jobs/job_exp.dm b/code/modules/jobs/job_exp.dm
index 8596a9af07e2b..89ef4ced24114 100644
--- a/code/modules/jobs/job_exp.dm
+++ b/code/modules/jobs/job_exp.dm
@@ -56,6 +56,12 @@ GLOBAL_PROTECT(exp_to_update)
for(var/job in typelist["titles"])
if(job in explist)
amount += explist[job]
+ // Removed job support
+ typelist = GLOB.exp_removed_jobsmap[exptype]
+ if(typelist)
+ for(var/job in typelist["titles"])
+ if(job in explist)
+ amount += explist[job]
return amount
/client/proc/get_exp_living(pure_numeric = FALSE)
@@ -107,6 +113,9 @@ GLOBAL_PROTECT(exp_to_update)
for(var/rtype in SSjob.name_occupations)
if(!play_records[rtype])
play_records[rtype] = 0
+ for(var/rtype in GLOB.exp_removed_jobs)
+ if(!play_records[rtype])
+ play_records[rtype] = 0
for(var/rtype in GLOB.exp_specialmap)
if(!play_records[rtype])
play_records[rtype] = 0
diff --git a/code/modules/jobs/job_report.dm b/code/modules/jobs/job_report.dm
index 49f50f72c64de..4a404e3a8a7f4 100644
--- a/code/modules/jobs/job_report.dm
+++ b/code/modules/jobs/job_report.dm
@@ -29,12 +29,17 @@
var/list/data = list()
data["jobPlaytimes"] = list()
+ data["jobRemovedPlaytimes"] = list()
data["specialPlaytimes"] = list()
for (var/job_name in SSjob.name_occupations)
var/playtime = play_records[job_name] ? text2num(play_records[job_name]) : 0
data["jobPlaytimes"][job_name] = playtime
+ for (var/job_name in GLOB.exp_removed_jobs)
+ var/playtime = play_records[job_name] ? text2num(play_records[job_name]) : 0
+ data["jobRemovedPlaytimes"][job_name] = playtime
+
for (var/special_name in GLOB.exp_specialmap[EXP_TYPE_SPECIAL])
var/playtime = play_records[special_name] ? text2num(play_records[special_name]) : 0
data["specialPlaytimes"][special_name] = playtime
diff --git a/code/modules/jobs/job_types/deputy.dm b/code/modules/jobs/job_types/deputy.dm
index ba3acbdce2f97..79fd85d2776d0 100644
--- a/code/modules/jobs/job_types/deputy.dm
+++ b/code/modules/jobs/job_types/deputy.dm
@@ -24,7 +24,7 @@
payment_per_department = list(ACCOUNT_SEC_ID = PAYCHECK_EASY)
mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM)
- display_order = JOB_DISPLAY_ORDER_DEPUTY //see code/__DEFINES/jobs.dm
+ show_in_prefs = FALSE
/datum/outfit/job/deputy
name = JOB_NAME_DEPUTY
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index 88885ba498262..804918e162d3d 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -163,6 +163,11 @@ GLOBAL_LIST_INIT(available_depts, list(SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, S
chameleon_extras = list(/obj/item/gun/energy/disabler, /obj/item/clothing/glasses/hud/security/sunglasses, /obj/item/clothing/head/helmet)
//The helmet is necessary because /obj/item/clothing/head/helmet/sec is overwritten in the chameleon list by the standard helmet, which has the same name and icon state
+/datum/outfit/job/security_officer/bulletproof
+ name = "Security Officer (Bulletproof)"
+ head = /obj/item/clothing/head/helmet/alt
+ suit = /obj/item/clothing/suit/armor/bulletproof
+
/obj/item/radio/headset/headset_sec/alt/department/Initialize(mapload)
. = ..()
diff --git a/code/modules/jobs/jobs.dm b/code/modules/jobs/jobs.dm
index 08d8da75aa13a..0c3764e702b3d 100644
--- a/code/modules/jobs/jobs.dm
+++ b/code/modules/jobs/jobs.dm
@@ -228,7 +228,18 @@ GLOBAL_LIST_INIT(security_positions_hud, list(
JOB_HUD_DEPUTY,
JOB_HUD_RAWSECURITY))
+/// Put any removed jobs here so they can still show in playtime listings.
+GLOBAL_LIST_INIT(exp_removed_jobs, list(
+// "Virologist",
+))
+GLOBAL_PROTECT(exp_removed_jobs)
+/// Put any removed jobs here so they can still show in playtime listings.
+GLOBAL_LIST_INIT(exp_removed_jobsmap, list(
+// EXP_TYPE_CREW = list("titles" = list("Virologist")),
+// EXP_TYPE_MEDICAL = list("titles" = list("Virologist")),
+))
+GLOBAL_PROTECT(exp_removed_jobsmap)
GLOBAL_LIST_INIT(exp_jobsmap, list(
EXP_TYPE_CREW = list("titles" = command_positions | engineering_positions | medical_positions | science_positions | supply_positions | security_positions | civilian_positions | gimmick_positions | list(JOB_NAME_AI,JOB_NAME_CYBORG)), // crew positions
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index c6fd689d57a2c..40bf496b3246d 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -19,15 +19,22 @@
icon_state = "oldcomp"
icon_screen = "library"
icon_keyboard = null
+
+ //these muthafuckas arent supposed to smooth
+ base_icon_state = null
+ smoothing_flags = null
+ smoothing_groups = null
+ canSmoothWith = null
+
circuit = /obj/item/circuitboard/computer/libraryconsole
desc = "Checked out books MUST be returned on time."
+ clockwork = TRUE //it'd look weird
+ broken_overlay_emissive = TRUE
var/screenstate = 0
var/title
var/category = "Any"
var/author
var/search_page = 0
- clockwork = TRUE //it'd look weird
- broken_overlay_emissive = TRUE
/obj/machinery/computer/libraryconsole/ui_interact(mob/user)
. = ..()
@@ -297,7 +304,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
dat += "(Order book by SS13BN)
"
dat += ""
dat += "AUTHOR | TITLE | CATEGORY | |
"
- dat += libcomp_menu[CLAMP(page,1,libcomp_menu.len)]
+ dat += libcomp_menu[clamp(page,1,libcomp_menu.len)]
dat += "<<<< | | | >>>> |
"
dat += "
"
dat += "
(Return to main menu)
"
@@ -336,6 +343,13 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
dat += "\[Bible\]
"
dat += "\[Space Law\]
"
dat += "\[Poster\]
"
+ dat += "\[Command SOP\]
"
+ dat += "\[Security SOP\]
"
+ dat += "\[Engineering SOP\]
"
+ dat += "\[Supply SOP\]
"
+ dat += "\[Science SOP\]
"
+ dat += "\[Medical SOP\]
"
+ dat += "\[Service SOP\]
"
dat += "(Return to main menu)
"
if(8)
dat += "Accessing Forbidden Lore Vault v 1.3
"
@@ -540,6 +554,55 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
cooldown = world.time + PRINTER_COOLDOWN
else
say("Printer currently unavailable, please wait a moment.")
+ if(href_list["printsopcmd"])
+ if(cooldown < world.time)
+ new /obj/item/book/manual/wiki/sopcommand(src.loc)
+ cooldown = world.time + PRINTER_COOLDOWN
+ else
+ say("Printer currently unavailable, please wait a moment.")
+
+ if(href_list["printsopsec"])
+ if(cooldown < world.time)
+ new /obj/item/book/manual/wiki/sopsecurity(src.loc)
+ cooldown = world.time + PRINTER_COOLDOWN
+ else
+ say("Printer currently unavailable, please wait a moment.")
+
+ if(href_list["printsopeng"])
+ if(cooldown < world.time)
+ new /obj/item/book/manual/wiki/sopengineering(src.loc)
+ cooldown = world.time + PRINTER_COOLDOWN
+ else
+ say("Printer currently unavailable, please wait a moment.")
+
+ if(href_list["printsopsup"])
+ if(cooldown < world.time)
+ new /obj/item/book/manual/wiki/sopsupply(src.loc)
+ cooldown = world.time + PRINTER_COOLDOWN
+ else
+ say("Printer currently unavailable, please wait a moment.")
+
+ if(href_list["printsopsci"])
+ if(cooldown < world.time)
+ new /obj/item/book/manual/wiki/sopscience(src.loc)
+ cooldown = world.time + PRINTER_COOLDOWN
+ else
+ say("Printer currently unavailable, please wait a moment.")
+
+ if(href_list["printsopmed"])
+ if(cooldown < world.time)
+ new /obj/item/book/manual/wiki/sopmedical(src.loc)
+ cooldown = world.time + PRINTER_COOLDOWN
+ else
+ say("Printer currently unavailable, please wait a moment.")
+
+ if(href_list["printsopsvc"])
+ if(cooldown < world.time)
+ new /obj/item/book/manual/wiki/sopservice(src.loc)
+ cooldown = world.time + PRINTER_COOLDOWN
+ else
+ say("Printer currently unavailable, please wait a moment.")
+
add_fingerprint(usr)
updateUsrDialog()
diff --git a/code/modules/mapping/mapping_items/job_scaling_loot_spawners.dm b/code/modules/mapping/mapping_items/job_scaling_loot_spawners.dm
index 581d2eecbfb28..830f6227b1483 100644
--- a/code/modules/mapping/mapping_items/job_scaling_loot_spawners.dm
+++ b/code/modules/mapping/mapping_items/job_scaling_loot_spawners.dm
@@ -23,7 +23,7 @@
for (var/job_name in jobs)
var/datum/job/located = SSjob.GetJob(job_name)
total += located.current_positions
- total = CEILING(CLAMP(total * linear_scaling_rate, minimum, maximum), 1)
+ total = CEILING(clamp(total * linear_scaling_rate, minimum, maximum), 1)
lootcount = total
if(!length(loot))
qdel(src)
diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm
index 031c27d016f8f..03a8b3704e911 100644
--- a/code/modules/mining/aux_base.dm
+++ b/code/modules/mining/aux_base.dm
@@ -15,6 +15,10 @@
name = "auxillary base management console"
icon = 'icons/obj/terminals.dmi'
icon_state = "dorm_available"
+ base_icon_state = null
+ smoothing_flags = NONE
+ smoothing_groups = null
+ canSmoothWith = null
var/shuttleId = "colony_drop"
desc = "Allows a deployable expedition base to be dropped from the station to a designated mining location. It can also \
interface with the mining shuttle at the landing site if a mobile beacon is also deployed."
diff --git a/code/modules/mining/coins.dm b/code/modules/mining/coins.dm
index ffa3762eb7c22..04fc89ab5c7c6 100644
--- a/code/modules/mining/coins.dm
+++ b/code/modules/mining/coins.dm
@@ -49,10 +49,10 @@
/obj/item/coin/proc/manual_suicide(mob/living/user)
var/index = sideslist.Find(coinflip)
- if (index==2)//tails
+ if (index == 2)//tails
user.visible_message("\the [src] lands on [coinflip]! [user] promptly falls over, dead!")
user.adjustOxyLoss(200)
- user.death(0)
+ user.death(FALSE)
user.set_suicide(TRUE)
user.suicide_log()
else
diff --git a/code/modules/mining/equipment/regenerative_core.dm b/code/modules/mining/equipment/regenerative_core.dm
index 108dc6d6e6ac6..1198114e63252 100644
--- a/code/modules/mining/equipment/regenerative_core.dm
+++ b/code/modules/mining/equipment/regenerative_core.dm
@@ -128,16 +128,16 @@
/obj/item/organ/regenerative_core/legion/Initialize(mapload)
. = ..()
- update_icon()
+ update_appearance()
-/obj/item/organ/regenerative_core/update_icon()
+/obj/item/organ/regenerative_core/update_icon_state()
icon_state = inert ? "legion_soul_inert" : "legion_soul"
- cut_overlays()
+ return ..()
+
+/obj/item/organ/regenerative_core/update_overlays()
+ . = ..()
if(!inert && !preserved)
- add_overlay("legion_soul_crackle")
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ . += "legion_soul_crackle"
/obj/item/organ/regenerative_core/legion/go_inert()
..()
diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm
index 2f62f52412d6b..23087b95ac556 100644
--- a/code/modules/mining/fulton.dm
+++ b/code/modules/mining/fulton.dm
@@ -75,7 +75,8 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons)
if(isliving(A))
var/mob/living/M = A
M.Paralyze(320) // Keep them from moving during the duration of the extraction
- M.buckled?.unbuckle_mob(M, TRUE) // Unbuckle them to prevent anchoring problems
+ if(M.buckled)
+ M.buckled.unbuckle_mob(M, TRUE) // Unbuckle them to prevent anchoring problems
else
A.anchored = TRUE
A.set_density(FALSE)
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 0c1f07b4577f7..c7a98b9fb6479 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -734,7 +734,7 @@
"Both modes will build up existing bleed effects, doing a burst of high damage if the bleed is built up high enough.\n"+\
"Transforming it immediately after an attack causes the next attack to come out faster."
-/obj/item/melee/transforming/cleaving_saw/suicide_act(mob/user)
+/obj/item/melee/transforming/cleaving_saw/suicide_act(mob/living/user)
user.visible_message("[user] is [active ? "closing [src] on [user.p_their()] neck" : "opening [src] into [user.p_their()] chest"]! It looks like [user.p_theyre()] trying to commit suicide!")
transform_cooldown = 0
transform_weapon(user, TRUE)
@@ -891,13 +891,13 @@
force = 0
var/ghost_counter = ghost_check()
- force = CLAMP((ghost_counter * 4), 0, 75)
+ force = clamp((ghost_counter * 4), 0, 75)
user.visible_message("[user] strikes with the force of [ghost_counter] vengeful spirits!")
..()
/obj/item/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
var/ghost_counter = ghost_check()
- final_block_chance += CLAMP((ghost_counter * 5), 0, 75)
+ final_block_chance += clamp((ghost_counter * 5), 0, 75)
owner.visible_message("[owner] is protected by a ring of [ghost_counter] ghosts!")
return ..()
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index 9fd05c70674ee..eeadddad65ceb 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -155,7 +155,7 @@
machine.toggle_auto_shutdown()
if("set_smelt_amount")
- machine.smelt_amount_limit = CLAMP(text2num(params["amount"]), 1, 100)
+ machine.smelt_amount_limit = clamp(text2num(params["amount"]), 1, 100)
/obj/machinery/mineral/processing_unit_console/Destroy()
machine.console = null
diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm
index 9c5326fb4fc57..7a8a6a40fcb1c 100644
--- a/code/modules/mining/machine_silo.dm
+++ b/code/modules/mining/machine_silo.dm
@@ -130,7 +130,7 @@ GLOBAL_LIST_EMPTY(silo_access_logs)
var/list/logs = GLOB.silo_access_logs[REF(src)]
var/len = LAZYLEN(logs)
var/num_pages = 1 + round((len - 1) / 30)
- var/page = CLAMP(log_page, 1, num_pages)
+ var/page = clamp(log_page, 1, num_pages)
if(num_pages > 1)
for(var/i in 1 to num_pages)
if(i == page)
diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm
index ab0f6af9a3c04..8362eec68acb6 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories.dm
@@ -2113,6 +2113,14 @@
name = "Moon Fly"
icon_state = "moonfly"
+/datum/sprite_accessory/moth_wings/witchwingi
+ name = "Witch Wing"
+ icon_state = "witchwing"
+
+/datum/sprite_accessory/moth_wingsopen/witchwing
+ name = "Witch Wing"
+ icon_state = "witchwing"
+
/datum/sprite_accessory/moth_wings/snow
name = "Snow"
icon_state = "snow"
@@ -2204,6 +2212,10 @@
name = "Snow"
icon_state = "snow"
+/datum/sprite_accessory/moth_antennae/witchwing
+ name = "Witch Wing"
+ icon_state = "witchwing"
+
/datum/sprite_accessory/moth_markings // the markings that moths can have. finally something other than the boring tan
icon = 'icons/mob/moth_markings.dmi'
color_src = null
@@ -2257,6 +2269,10 @@
name = "Moon Fly"
icon_state = "moonfly"
+/datum/sprite_accessory/moth_markings/witchwing
+ name = "Witch Wing"
+ icon_state = "witchwing"
+
// IPC accessories.
/datum/sprite_accessory/ipc_screens
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index c59a2060159d8..310ed36a29751 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -308,7 +308,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(stat != DEAD)
succumb()
if(stat == DEAD)
- ghostize(1)
+ ghostize(TRUE)
else
var/response = tgui_alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)", "Are you sure you want to ghost?", list("Ghost", "Stay in body"))
if(response != "Ghost")
diff --git a/code/modules/mob/living/basic/basic_defense.dm b/code/modules/mob/living/basic/basic_defense.dm
index ac5c261a85a6f..0e4c2e221b3f5 100644
--- a/code/modules/mob/living/basic/basic_defense.dm
+++ b/code/modules/mob/living/basic/basic_defense.dm
@@ -157,6 +157,7 @@
if(prob(bomb_armor))
adjustBruteLoss(500)
else
+ investigate_log("has been gibbed by an explosion.", INVESTIGATE_DEATHS)
gib()
return
if (EXPLODE_HEAVY)
diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm
index c0577c6a6dfb3..9edaa6d1706db 100644
--- a/code/modules/mob/living/bloodcrawl.dm
+++ b/code/modules/mob/living/bloodcrawl.dm
@@ -127,7 +127,9 @@
src.revive(full_heal = 1)
// No defib possible after laughter
- victim.adjustBruteLoss(1000)
+ victim.apply_damage(1000, BRUTE)
+ if(victim.stat != DEAD)
+ victim.investigate_log("has been killed by being consumed by a slaugter demon.", INVESTIGATE_DEATHS)
victim.death()
bloodcrawl_swallow(victim)
return TRUE
diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm
index 3536574d11252..7718d6f255f3c 100644
--- a/code/modules/mob/living/brain/brain.dm
+++ b/code/modules/mob/living/brain/brain.dm
@@ -26,8 +26,8 @@
/mob/living/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
- if(stat!=DEAD) //If not dead.
- death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
+ if(stat != DEAD)
+ death(TRUE)
if(mind) //You aren't allowed to return to brains that don't exist
mind.set_current(null)
ghostize() //Ghostize checks for key so nothing else is necessary.
diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm
index e9be3a75242ab..d251ef72d5936 100644
--- a/code/modules/mob/living/brain/brain_item.dm
+++ b/code/modules/mob/living/brain/brain_item.dm
@@ -178,6 +178,7 @@
/obj/item/organ/brain/on_life()
if(damage >= BRAIN_DAMAGE_DEATH) //rip
to_chat(owner, "The last spark of life in your brain fizzles out.")
+ owner.investigate_log("has been killed by brain damage.", INVESTIGATE_DEATHS)
owner.death()
brain_death = TRUE
diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm
index 4ac6dad9bb3e7..b9c664f5252f5 100644
--- a/code/modules/mob/living/carbon/alien/larva/larva.dm
+++ b/code/modules/mob/living/carbon/alien/larva/larva.dm
@@ -9,6 +9,7 @@
maxHealth = 25
health = 25
+ hardcrit_threshold = HEALTH_THRESHOLD_CRIT
var/amount_grown = 0
var/max_grown = 100
diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm
index b26d2978befaf..fe53dfa71772e 100644
--- a/code/modules/mob/living/carbon/alien/larva/life.dm
+++ b/code/modules/mob/living/carbon/alien/larva/life.dm
@@ -18,15 +18,12 @@
if(health<= -maxHealth || !getorgan(/obj/item/organ/brain))
death()
return
- if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || health <= crit_threshold)
- if(stat == CONSCIOUS)
- set_stat(UNCONSCIOUS)
- become_blind(UNCONSCIOUS_BLIND)
- update_mobility()
+ if((HAS_TRAIT(src, TRAIT_KNOCKEDOUT)))
+ set_stat(UNCONSCIOUS)
else
if(stat == UNCONSCIOUS)
- set_stat(CONSCIOUS)
- cure_blind(UNCONSCIOUS_BLIND)
set_resting(FALSE)
+ set_stat(CONSCIOUS)
+ update_mobility()
update_damage_hud()
update_health_hud()
diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
index 8500172811799..c91f2cb9b9b88 100644
--- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
+++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
@@ -54,9 +54,6 @@
STOP_PROCESSING(SSobj, src)
/obj/item/organ/body_egg/alien_embryo/egg_process()
- var/mob/living/L = owner
- if(IS_IN_STASIS(L))
- return
if(!next_stage_time)
COOLDOWN_START(src, next_stage_time, 30 SECONDS)
return
@@ -78,8 +75,6 @@
return
AttemptGrow()
-
-
/obj/item/organ/body_egg/alien_embryo/proc/AttemptGrow(kill_on_success = TRUE)
if(!owner || bursting)
return
@@ -132,6 +127,7 @@
new_xeno.visible_message("[new_xeno] wriggles out of [owner]!", "You exit [owner], your previous host.")
owner.adjustBruteLoss(40)
host.cut_overlay(overlay)
+ owner.investigate_log("has been killed by an alien larva chestburst.", INVESTIGATE_DEATHS)
qdel(src)
diff --git a/code/modules/mob/living/carbon/alien/status_procs.dm b/code/modules/mob/living/carbon/alien/status_procs.dm
index 7fd1d31872346..0affc187a12f0 100644
--- a/code/modules/mob/living/carbon/alien/status_procs.dm
+++ b/code/modules/mob/living/carbon/alien/status_procs.dm
@@ -17,4 +17,4 @@
/mob/living/carbon/alien/AdjustStun(amount, updating = 1, ignore_canstun = 0)
. = ..()
if(!.)
- move_delay_add = CLAMP(move_delay_add + round(amount/2), 0, 10)
+ move_delay_add = clamp(move_delay_add + round(amount/2), 0, 10)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 22784852973bd..608db51f5a737 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -404,7 +404,7 @@
return 0
return ..()
-/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, toxic = FALSE)
+/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, toxic = VOMIT_TOXIC, purge = FALSE)
if(HAS_TRAIT(src, TRAIT_NOHUNGER))
return 1
@@ -452,10 +452,10 @@
adjustBruteLoss(3)
else if(src.reagents.has_reagent(/datum/reagent/consumable/ethanol/blazaam, needs_metabolizing = TRUE))
if(T)
- T.add_vomit_floor(src, VOMIT_PURPLE)
+ T.add_vomit_floor(src, toxic || VOMIT_PURPLE, purge)
else
if(T)
- T.add_vomit_floor(src, VOMIT_TOXIC)//toxic barf looks different
+ T.add_vomit_floor(src, toxic, purge)//toxic barf looks different
T = get_step(T, dir)
if (T.is_blocked_turf())
break
@@ -496,7 +496,7 @@
total_brute += (BP.brute_dam * BP.body_damage_coeff)
total_burn += (BP.burn_dam * BP.body_damage_coeff)
total_stamina += (BP.stamina_dam * BP.stam_damage_coeff)
- health = round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION)
+ set_health(round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION))
staminaloss = round(total_stamina, DAMAGE_PRECISION)
update_stat()
update_mobility()
@@ -513,11 +513,12 @@
/mob/living/carbon/update_stamina(extend_stam_crit = FALSE)
var/stam = getStaminaLoss()
if(stam >= DAMAGE_PRECISION && (maxHealth - stam) <= crit_threshold && !stat && !HAS_TRAIT(src, TRAIT_NOSTAMCRIT))
- if(extend_stam_crit || !stam_paralyzed)
+ if(extend_stam_crit || !HAS_TRAIT_FROM(src, TRAIT_INCAPACITATED, STAMINA))
enter_stamcrit()
- else if(stam_paralyzed)
- stam_paralyzed = FALSE
- REMOVE_TRAIT(src,TRAIT_INCAPACITATED, STAMINA)
+ else if(HAS_TRAIT_FROM(src, TRAIT_INCAPACITATED, STAMINA))
+ REMOVE_TRAIT(src, TRAIT_INCAPACITATED, STAMINA)
+ REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, STAMINA)
+ /*REMOVE_TRAIT(src, TRAIT_FLOORED, STAMINA)*/
else
return
update_health_hud()
@@ -724,28 +725,34 @@
if(hud_used && hud_used.internals)
hud_used.internals.icon_state = "internal[internal_state]"
+/mob/living/carbon/set_health(new_value)
+ . = ..()
+ if(. > hardcrit_threshold)
+ if(health <= hardcrit_threshold && !HAS_TRAIT(src, TRAIT_NOHARDCRIT))
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, CRIT_HEALTH_TRAIT)
+ else if(health > hardcrit_threshold)
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, CRIT_HEALTH_TRAIT)
+ if(CONFIG_GET(flag/near_death_experience))
+ if(. > HEALTH_THRESHOLD_NEARDEATH)
+ if(health <= HEALTH_THRESHOLD_NEARDEATH && !HAS_TRAIT(src, TRAIT_NODEATH))
+ ADD_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
+ else if(health > HEALTH_THRESHOLD_NEARDEATH)
+ REMOVE_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
+
/mob/living/carbon/update_stat()
if(status_flags & GODMODE)
return
if(stat != DEAD)
if(health <= HEALTH_THRESHOLD_DEAD && !HAS_TRAIT(src, TRAIT_NODEATH))
death()
- cure_blind(UNCONSCIOUS_BLIND)
return
- if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT)))
+ if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT))
set_stat(UNCONSCIOUS)
- become_blind(UNCONSCIOUS_BLIND)
- if(CONFIG_GET(flag/near_death_experience) && health <= HEALTH_THRESHOLD_NEARDEATH && !HAS_TRAIT(src, TRAIT_NODEATH))
- ADD_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
- else
- REMOVE_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
else
if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT))
set_stat(SOFT_CRIT)
else
set_stat(CONSCIOUS)
- cure_blind(UNCONSCIOUS_BLIND)
- REMOVE_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
update_mobility()
update_damage_hud()
update_health_hud()
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 939c17e615e57..6da3904611ec1 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -434,3 +434,24 @@
var/obj/item/organ/ears/ears = getorganslot(ORGAN_SLOT_EARS)
if(istype(ears) && !ears.deaf)
. = TRUE
+
+/mob/living/carbon/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE)
+ . = ..()
+ if(isnull(.))
+ return
+ if(. <= 50)
+ if(getOxyLoss() > 50)
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+ else if(getOxyLoss() <= 50)
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+
+
+/mob/living/carbon/setOxyLoss(amount, updating_health = TRUE, forced = FALSE)
+ . = ..()
+ if(isnull(.))
+ return
+ if(. <= 50)
+ if(getOxyLoss() > 50)
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+ else if(getOxyLoss() <= 50)
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index 53a95b17b1244..22b8bf553a97a 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -72,7 +72,6 @@
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
var/stam_regen_start_time = 0 //used to halt stamina regen temporarily
- var/stam_paralyzed = FALSE //knocks you down
var/stam_heal = 10 //Stamina healed per 2 seconds overall. When the mob has taken more than 60 stamina damage, the rate of stamina regeneration will be increased, up to 20 per second when the mob has taken 120 stamina damage.
/// Timer id of any transformation
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 0de5ea66f2428..83277ddece517 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -91,6 +91,27 @@
//Death
dust(TRUE)
return
+ if(key) // Prevents log spamming of keyless mob deaths (like xenobio monkeys)
+ investigate_log("has died at [loc_name(src)].
\
+ BRUTE: [src.getBruteLoss()] BURN: [src.getFireLoss()] TOX: [src.getToxLoss()] OXY: [src.getOxyLoss()] CLONE: [src.getCloneLoss()] STAM: [src.getStaminaLoss()]
\
+ Brain damage: [src.getOrganLoss(ORGAN_SLOT_BRAIN) || "0"]
\
+ Blood volume: [src.blood_volume]cl ([round((src.blood_volume / BLOOD_VOLUME_NORMAL) * 100, 0.1)]%)
\
+ Reagents:
[reagents_readout()]", INVESTIGATE_DEATHS)
+ to_chat(src, "You have died. Barring complete bodyloss, you can in most cases be revived by other players. If you do not wish to be brought back, use the \"Do Not Resuscitate\" verb in the ghost tab.")
+
+/mob/living/carbon/human/proc/reagents_readout()
+ var/readout = "Blood:"
+ for(var/datum/reagent/reagent in reagents?.reagent_list)
+ readout += "