| [ailment.name] | "
var/list/ailment_cures = list()
diff --git a/code/modules/organs/ailments/ailments_medical.dm b/code/modules/organs/ailments/ailments_medical.dm
index 4cf930ac0f95..c9d3dad97511 100644
--- a/code/modules/organs/ailments/ailments_medical.dm
+++ b/code/modules/organs/ailments/ailments_medical.dm
@@ -1,5 +1,5 @@
/datum/ailment/head
- category = /datum/ailment/head
+ abstract_type = /datum/ailment/head
applies_to_organ = list(BP_HEAD)
/datum/ailment/head/headache
diff --git a/code/modules/organs/ailments/faults/_fault.dm b/code/modules/organs/ailments/faults/_fault.dm
index 8219540a8dc1..52a9b747a84e 100644
--- a/code/modules/organs/ailments/faults/_fault.dm
+++ b/code/modules/organs/ailments/faults/_fault.dm
@@ -1,7 +1,7 @@
/datum/ailment/fault
applies_to_robotics = TRUE
applies_to_prosthetics = TRUE
- category = /datum/ailment/fault
+ abstract_type = /datum/ailment/fault
treated_by_item_type = list(
/obj/item/stack/nanopaste,
/obj/item/stack/tape_roll/duct_tape
diff --git a/code/modules/organs/external/_external.dm b/code/modules/organs/external/_external.dm
index 7b6ef08b85bb..c65f7e18f4d9 100644
--- a/code/modules/organs/external/_external.dm
+++ b/code/modules/organs/external/_external.dm
@@ -62,7 +62,7 @@
var/artery_name = "artery" // Flavour text for cartoid artery, aorta, etc.
var/arterial_bleed_severity = 1 // Multiplier for bleeding in a limb.
var/tendon_name = "tendon" // Flavour text for Achilles tendon, etc.
- var/cavity_name = "cavity"
+ var/cavity_name = "intramuscular cavity"
// Surgery vars.
var/cavity_max_w_class = ITEM_SIZE_TINY //this is increased if bigger organs spawn by default inside
@@ -70,8 +70,6 @@
var/stage = 0
var/cavity = 0
- var/list/unarmed_attacks
-
var/atom/movable/applied_pressure
var/atom/movable/splinted
@@ -141,10 +139,6 @@
_icon_cache_key = null
. = ..()
skin_blend = bodytype.limb_blend
- for(var/attack_type in species.unarmed_attacks)
- var/decl/natural_attack/attack = GET_DECL(attack_type)
- if(istype(attack) && (organ_tag in attack.usable_with_limbs))
- LAZYADD(unarmed_attacks, attack_type)
update_icon()
/obj/item/organ/external/set_bodytype(decl/bodytype/new_bodytype, override_material = null, apply_to_internal_organs = TRUE)
@@ -318,7 +312,7 @@
//Handles removing internal organs/implants/items still in the detached limb.
/obj/item/organ/external/proc/try_remove_internal_item(var/obj/item/used_item, var/mob/user)
- if(stage == 0 && used_item.sharp)
+ if(stage == 0 && used_item.is_sharp())
user.visible_message(SPAN_NOTICE("\The [user] cuts \the [src] open with \the [used_item]."))
stage++
return TRUE
@@ -328,7 +322,7 @@
stage++
return TRUE
- if(stage == 2 && (used_item.sharp || IS_HEMOSTAT(used_item) || IS_WIRECUTTER(used_item)))
+ if(stage == 2 && (used_item.is_sharp() || IS_HEMOSTAT(used_item) || IS_WIRECUTTER(used_item)))
var/list/radial_buttons = make_item_radial_menu_choices(get_contents_recursive())
if(LAZYLEN(radial_buttons))
var/obj/item/removing = show_radial_menu(user, src, radial_buttons, radius = 42, require_near = TRUE, use_labels = RADIAL_LABELS_OFFSET, check_locs = list(src))
diff --git a/code/modules/organs/external/head.dm b/code/modules/organs/external/head.dm
index 1d6b432822ce..b16d8919e296 100644
--- a/code/modules/organs/external/head.dm
+++ b/code/modules/organs/external/head.dm
@@ -12,7 +12,7 @@
amputation_point = "neck"
encased = "skull"
artery_name = "carotid artery"
- cavity_name = "cranial"
+ cavity_name = "cranial cavity"
limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_HEALS_OVERKILL | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE
var/glowing_eyes = FALSE
@@ -20,6 +20,24 @@
var/forehead_graffiti
var/graffiti_style
+/obj/item/organ/external/head/get_natural_attacks()
+ if(!can_intake_reagents)
+ return null
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/bite)
+ return unarmed_attack
+
+/obj/item/organ/external/head/sharp_bite/get_natural_attacks()
+ if(!can_intake_reagents)
+ return null
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/bite/sharp)
+ return unarmed_attack
+
+/obj/item/organ/external/head/strong_bite/get_natural_attacks()
+ if(!can_intake_reagents)
+ return null
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/bite/strong)
+ return unarmed_attack
+
/obj/item/organ/external/head/proc/get_organ_eyes_overlay()
if(!glowing_eyes && !owner?.has_chemical_effect(CE_GLOWINGEYES, 1))
return
diff --git a/code/modules/organs/external/standard.dm b/code/modules/organs/external/standard.dm
index 2beef64083b1..84cb21e75a31 100644
--- a/code/modules/organs/external/standard.dm
+++ b/code/modules/organs/external/standard.dm
@@ -17,7 +17,7 @@
parent_organ = null
encased = "ribcage"
artery_name = "aorta"
- cavity_name = "thoracic"
+ cavity_name = "thoracic cavity"
limb_flags = ORGAN_FLAG_HEALS_OVERKILL | ORGAN_FLAG_CAN_BREAK
/obj/item/organ/external/chest/proc/get_current_skin()
@@ -41,7 +41,7 @@
amputation_point = "lumbar"
joint = "hip"
artery_name = "iliac artery"
- cavity_name = "abdominal"
+ cavity_name = "abdominal cavity"
limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_BREAK
/obj/item/organ/external/groin/die()
@@ -113,6 +113,13 @@
limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_STAND | ORGAN_FLAG_HAS_TENDON | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE
organ_category = ORGAN_CATEGORY_STANCE
+/obj/item/organ/external/foot/get_natural_attacks()
+ var/static/list/unarmed_attacks = list(
+ GET_DECL(/decl/natural_attack/stomp),
+ GET_DECL(/decl/natural_attack/kick)
+ )
+ return unarmed_attacks
+
/obj/item/organ/external/foot/right
organ_tag = BP_R_FOOT
name = "right foot"
@@ -139,6 +146,10 @@
is_washable = TRUE
var/gripper_type = /datum/inventory_slot/gripper/left_hand
+/obj/item/organ/external/hand/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/punch)
+ return unarmed_attack
+
/obj/item/organ/external/hand/do_install(mob/living/human/target, affected, in_place, update_icon, detached)
. = ..()
if(. && owner && gripper_type)
@@ -158,3 +169,11 @@
joint = "right wrist"
amputation_point = "right wrist"
gripper_type = /datum/inventory_slot/gripper/right_hand
+
+/obj/item/organ/external/hand/clawed/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/claws)
+ return unarmed_attack
+
+/obj/item/organ/external/hand/right/clawed/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/claws)
+ return unarmed_attack
diff --git a/code/modules/organs/external/wounds/wound.dm b/code/modules/organs/external/wounds/wound.dm
index 2c2746cd154c..60219be1f1a4 100644
--- a/code/modules/organs/external/wounds/wound.dm
+++ b/code/modules/organs/external/wounds/wound.dm
@@ -79,7 +79,7 @@
return 0
return (wound_damage() <= autoheal_cutoff) ? 1 : is_treated()
-// checks whether the wound has been appropriately treated
+/// checks whether the wound has been appropriately treated
/datum/wound/proc/is_treated()
if(!LAZYLEN(embedded_objects))
switch(damage_type)
@@ -88,7 +88,7 @@
if(BURN)
return salved
- // Checks whether other other can be merged into src.
+/// Checks whether other can be merged into src.
/datum/wound/proc/can_merge_wounds(var/datum/wound/other)
if (other.type != src.type) return 0
if (other.current_stage != src.current_stage) return 0
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index 31cede40eaec..84d4cbc4155e 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -484,9 +484,11 @@
return
var/global/list/ailment_reference_cache = list()
-/proc/get_ailment_reference(var/ailment_type)
+/proc/get_ailment_reference(var/datum/ailment/ailment_type)
if(!ispath(ailment_type, /datum/ailment))
return
+ if(TYPE_IS_ABSTRACT(ailment_type))
+ return
if(!global.ailment_reference_cache[ailment_type])
global.ailment_reference_cache[ailment_type] = new ailment_type
return global.ailment_reference_cache[ailment_type]
@@ -497,7 +499,7 @@ var/global/list/ailment_reference_cache = list()
return .
for(var/ailment_type in subtypesof(/datum/ailment))
var/datum/ailment/ailment = ailment_type
- if(initial(ailment.category) == ailment_type)
+ if(TYPE_IS_ABSTRACT(ailment))
continue
ailment = get_ailment_reference(ailment_type)
if(ailment.can_apply_to(src))
diff --git a/code/modules/overmap/contacts/_contacts.dm b/code/modules/overmap/contacts/_contacts.dm
index e4cab812e76f..bde9a41d1717 100644
--- a/code/modules/overmap/contacts/_contacts.dm
+++ b/code/modules/overmap/contacts/_contacts.dm
@@ -29,7 +29,6 @@
radar = image(loc = effect, icon = 'icons/obj/overmap.dmi', icon_state = "sensor_range")
radar.color = source.color
- radar.tag = "radar"
radar.add_filter("blur", 1, list(type = "blur", size = 1))
radar.appearance_flags |= RESET_TRANSFORM | KEEP_APART
radar.appearance_flags &= ~PIXEL_SCALE
diff --git a/code/modules/overmap/overmap_shuttle.dm b/code/modules/overmap/overmap_shuttle.dm
index 408db04970a3..2a7e5b3fb646 100644
--- a/code/modules/overmap/overmap_shuttle.dm
+++ b/code/modules/overmap/overmap_shuttle.dm
@@ -7,7 +7,7 @@
var/fuel_consumption = 0 //Amount of moles of gas consumed per trip; If zero, then shuttle is magic and does not need fuel
var/list/obj/structure/fuel_port/fuel_ports //the fuel ports of the shuttle (but usually just one)
- category = /datum/shuttle/autodock/overmap
+ abstract_type = /datum/shuttle/autodock/overmap
var/skill_needed = SKILL_BASIC
var/landing_skill_needed = SKILL_EXPERT
var/operator_skill = SKILL_MIN
diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm
index 89f88cf959a8..a5b56cf128fb 100644
--- a/code/modules/paperwork/papershredder.dm
+++ b/code/modules/paperwork/papershredder.dm
@@ -89,7 +89,7 @@
/obj/machinery/papershredder/proc/is_bin_empty()
return !(length(shredder_bin) > 0 && cached_total_matter)
-/obj/machinery/papershredder/proc/can_shred(var/obj/item/I, var/mob/user = null)
+/obj/machinery/papershredder/proc/can_shred_document(var/obj/item/I, var/mob/user = null)
if(!istype(I))
if(user)
to_chat(user, SPAN_WARNING("\The [I] cannot be shredded by \the [src]!"))
@@ -120,7 +120,7 @@
empty_bin(user, used_item)
return TRUE
- else if(!trying_to_smack && can_shred(used_item))
+ else if(!trying_to_smack && can_shred_document(used_item))
shred(used_item, user)
return TRUE
return ..()
diff --git a/code/modules/paperwork/pen/fancy.dm b/code/modules/paperwork/pen/fancy.dm
index 9c7e149a7be8..098033965e66 100644
--- a/code/modules/paperwork/pen/fancy.dm
+++ b/code/modules/paperwork/pen/fancy.dm
@@ -1,7 +1,7 @@
/obj/item/pen/fancy
name = "fountain pen"
icon = 'icons/obj/items/pens/pen_fancy.dmi'
- sharp = 1 //pointy
+ sharp = TRUE
stroke_color = "#1c1713" //dark ashy brownish
stroke_color_name = "dark ashy brownish"
material = /decl/material/solid/metal/steel
diff --git a/code/modules/paperwork/pen/quill_and_ink.dm b/code/modules/paperwork/pen/quill_and_ink.dm
index 4944165f4e5b..f643b9d12472 100644
--- a/code/modules/paperwork/pen/quill_and_ink.dm
+++ b/code/modules/paperwork/pen/quill_and_ink.dm
@@ -1,7 +1,7 @@
/obj/item/pen/fancy/quill
name = "quill pen"
icon = 'icons/obj/items/pens/pen_quill.dmi'
- sharp = 0
+ sharp = FALSE
material = /decl/material/solid/organic/skin/feathers
pen_quality = TOOL_QUALITY_DEFAULT
max_uses = 5 // gotta re-ink it often!
diff --git a/code/modules/paperwork/pen/reagent_pen.dm b/code/modules/paperwork/pen/reagent_pen.dm
index 67dfcad441c6..7334323851a1 100644
--- a/code/modules/paperwork/pen/reagent_pen.dm
+++ b/code/modules/paperwork/pen/reagent_pen.dm
@@ -1,7 +1,7 @@
/obj/item/pen/reagent
atom_flags = ATOM_FLAG_OPEN_CONTAINER
origin_tech = @'{"materials":2,"esoteric":5}'
- sharp = 1
+ sharp = TRUE
pen_quality = TOOL_QUALITY_MEDIOCRE
/obj/item/pen/reagent/Initialize()
diff --git a/code/modules/persistence/graffiti.dm b/code/modules/persistence/graffiti.dm
index 1ed8a188417e..0bd85389b6f4 100644
--- a/code/modules/persistence/graffiti.dm
+++ b/code/modules/persistence/graffiti.dm
@@ -43,7 +43,7 @@
user.visible_message(SPAN_NOTICE("\The [user] clears away some graffiti."))
qdel(src)
return TRUE
- else if(thing.sharp && !user.check_intent(I_FLAG_HELP)) //Check intent so you don't go insane trying to unscrew a light fixture over a graffiti
+ else if(thing.is_sharp() && !user.check_intent(I_FLAG_HELP)) //Check intent so you don't go insane trying to unscrew a light fixture over a graffiti
if(jobban_isbanned(user, "Graffiti"))
to_chat(user, SPAN_WARNING("You are banned from leaving persistent information across rounds."))
return TRUE
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 1f6254eea46a..6e2b63b82fa9 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -491,21 +491,20 @@ var/global/list/all_apcs = list()
/obj/machinery/power/apc/physical_attack_hand(mob/user)
//Human mob special interaction goes here.
- if(ishuman(user))
- var/mob/living/human/H = user
-
- if(H.species.can_shred(H))
- user.visible_message("\The [user] slashes at \the [src]!", "You slash at \the [src]!")
- playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
-
- var/allcut = wires.IsAllCut()
- if(beenhit >= pick(3, 4) && allcut == 0)
- wires.CutAll()
- src.update_icon()
- src.visible_message("\The [src]'s wires are shredded!")
- else
- beenhit += 1
- return TRUE
+ if(user.can_shred())
+ user.visible_message(
+ SPAN_DANGER("\The [user] slashes at \the [src]!"),
+ SPAN_DANGER("You slash at \the [src]!")
+ )
+ playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
+ var/allcut = wires.IsAllCut()
+ if(beenhit >= pick(3, 4) && allcut == 0)
+ wires.CutAll()
+ update_icon()
+ visible_message(SPAN_DANGER("\The [src]'s wires are shredded!"))
+ else
+ beenhit += 1
+ return TRUE
return FALSE
/obj/machinery/power/apc/interface_interact(mob/user)
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 78f587767eef..655e27664973 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -188,9 +188,10 @@ By design, d1 is the smallest direction and d2 is the highest
to_chat(user, SPAN_WARNING("\The [src] is not powered."))
return TRUE
- if(used_item.edge)
+ else if(used_item.has_edge())
+
var/delay_holder
- if(used_item.get_attack_force(user) < 5)
+ if(used_item.expend_attack_force(user) < 5)
visible_message(SPAN_WARNING("[user] starts sawing away roughly at \the [src] with \the [used_item]."))
delay_holder = 8 SECONDS
else
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 48abeb8383a3..a60fab7f939a 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -85,7 +85,8 @@
to_chat(user, "The charge meter reads [round(src.percent(), 0.1)]%.")
/obj/item/cell/emp_act(severity)
- //remove this once emp changes on dev are merged in
+ // remove this if EMPs are ever rebalanced so that they don't instantly drain borg cells
+ // todo: containers (partially) shielding contents?
if(isrobot(loc))
var/mob/living/silicon/robot/R = loc
severity *= R.cell_emp_mult
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index e3b47f5c5d10..624425a51215 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -264,7 +264,7 @@
else if(lightbulb && (lightbulb.status != LIGHT_BROKEN) && !user.check_intent(I_FLAG_HELP))
- if(prob(1 + W.get_attack_force(user) * 5))
+ if(prob(1 + W.expend_attack_force(user) * 5))
user.visible_message("[user.name] smashed the light!", "You smash the light!", "You hear a tinkle of breaking glass.")
if(on && (W.obj_flags & OBJ_FLAG_CONDUCTIBLE))
@@ -316,12 +316,13 @@
to_chat(user, "There is no [get_fitting_name()] in this light.")
return TRUE
- if(ishuman(user))
- var/mob/living/human/H = user
- if(H.species.can_shred(H))
- visible_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass.")
- broken()
- return TRUE
+ if(user.can_shred())
+ visible_message(
+ SPAN_DANGER("\The [user] smashes the light!"),
+ blind_message = "You hear a tinkle of breaking glass."
+ )
+ broken()
+ return TRUE
// make it burn hands if not wearing fire-insulated gloves
if(on)
@@ -604,7 +605,7 @@
if(status == LIGHT_OK || status == LIGHT_BURNED)
src.visible_message("[name] shatters.","You hear a small glass object shatter.")
status = LIGHT_BROKEN
- sharp = 1
+ set_sharp(TRUE)
set_base_attack_force(5)
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
update_icon()
@@ -612,13 +613,7 @@
/obj/item/light/proc/switch_on()
switchcount++
if(rigged)
- log_and_message_admins("Rigged light explosion, last touched by [fingerprintslast]")
- var/turf/T = get_turf(src.loc)
- spawn(0)
- sleep(2)
- explosion(T, 0, 0, 3, 5)
- sleep(1)
- qdel(src)
+ addtimer(CALLBACK(src, PROC_REF(do_rigged_explosion)), 0.2 SECONDS)
status = LIGHT_BROKEN
else if(prob(min(60, switchcount*switchcount*0.01)))
status = LIGHT_BURNED
@@ -626,6 +621,15 @@
playsound(src, sound_on, 75)
return status
+/obj/item/light/proc/do_rigged_explosion()
+ if(!rigged)
+ return
+ log_and_message_admins("Rigged light explosion, last touched by [fingerprintslast]")
+ var/turf/T = get_turf(src)
+ explosion(T, 0, 0, 3, 5)
+ if(!QDELETED(src))
+ QDEL_IN(src, 1)
+
/obj/machinery/light/do_simple_ranged_interaction(var/mob/user)
if(lightbulb)
remove_bulb()
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index ca4b205e6b00..8afd72314cea 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -179,11 +179,14 @@
return net1
//Determines how strong could be shock, deals damage to mob, uses power.
-//M is a mob who touched wire/whatever
+//victim is a mob who touched wire/whatever
//power_source is a source of electricity, can be powercell, area, apc, cable, powernet or null
//source is an object caused electrocuting (airlock, grille, etc)
//No animations will be performed by this proc.
-/proc/electrocute_mob(mob/living/M, var/power_source, var/obj/source, var/siemens_coeff = 1.0)
+/proc/electrocute_mob(mob/living/victim, power_source, obj/source, siemens_coeff = 1.0, coverage_flags = SLOT_HANDS)
+
+ coverage_flags = victim?.get_active_hand_bodypart_flags() || coverage_flags
+
var/area/source_area
if(istype(power_source,/area))
source_area = power_source
@@ -208,19 +211,16 @@
else if (!power_source)
return 0
else
- log_admin("ERROR: /proc/electrocute_mob([M], [power_source], [source]): wrong power_source")
+ log_admin("ERROR: /proc/electrocute_mob([victim], [power_source], [source]): wrong power_source")
return 0
+
//Triggers powernet warning, but only for 5 ticks (if applicable)
//If following checks determine user is protected we won't alarm for long.
if(PN)
PN.trigger_warning(5)
- if(ishuman(M))
- var/mob/living/human/H = M
- if(H.species.get_shock_vulnerability(H) <= 0)
- return
- var/obj/item/clothing/gloves/G = H.get_equipped_item(slot_gloves_str)
- if(istype(G) && G.siemens_coefficient == 0)
- return 0 //to avoid spamming with insulated glvoes on
+
+ if(victim.get_siemens_coefficient_for_coverage(coverage_flags) <= 0)
+ return
//Checks again. If we are still here subject will be shocked, trigger standard 20 tick warning
//Since this one is longer it will override the original one.
@@ -242,7 +242,7 @@
else
power_source = cell
shock_damage = cell_damage
- var/drained_hp = M.electrocute_act(shock_damage, source, siemens_coeff) //zzzzzzap!
+ var/drained_hp = victim.electrocute_act(shock_damage, source, siemens_coeff) //zzzzzzap!
var/drained_energy = drained_hp*20
if (source_area)
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 233b66d985f9..c2b62b6059ff 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -11,7 +11,7 @@
active_power_usage = 100 KILOWATTS
var/efficiency = 0.3 // Energy efficiency. 30% at this time, so 100kW load means 30kW laser pulses.
- var/minimum_power = 10 KILOWATTS // The minimum power the emitter will still fire at it it doesn't have enough power available.
+ var/minimum_power = 10 KILOWATTS // The minimum power below which the emitter will turn off; different than the power needed to fire.
var/active = 0
var/fire_delay = 100
var/max_burst_delay = 100
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index bd129184831a..a941debb006a 100644
--- a/code/modules/power/solar.dm
+++ b/code/modules/power/solar.dm
@@ -88,7 +88,7 @@ var/global/list/solars_list = list()
return TRUE
else if (W)
add_fingerprint(user)
- current_health -= W.get_attack_force(user)
+ current_health -= W.expend_attack_force(user)
healthcheck()
return ..()
diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm
index 9230d872fd56..613ae77ae768 100644
--- a/code/modules/projectiles/ammunition.dm
+++ b/code/modules/projectiles/ammunition.dm
@@ -48,12 +48,11 @@
. = BB
BB = null
set_dir(pick(global.alldirs)) //spin spent casings
-
// Aurora forensics port, gunpowder residue.
if(leaves_residue)
leave_residue()
-
update_icon()
+ update_name()
/obj/item/ammo_casing/Crossed(atom/movable/AM)
..()
@@ -123,6 +122,11 @@
else if(spent_icon && !BB)
icon_state = spent_icon
+/obj/item/ammo_casing/update_name()
+ . = ..()
+ if(!BB)
+ SetName("spent [name]")
+
/obj/item/ammo_casing/examine(mob/user)
. = ..()
if(caliber)
diff --git a/code/modules/projectiles/ammunition/chemdart.dm b/code/modules/projectiles/ammunition/chemdart.dm
index bd8710bef92d..fa7647a4dcf1 100644
--- a/code/modules/projectiles/ammunition/chemdart.dm
+++ b/code/modules/projectiles/ammunition/chemdart.dm
@@ -2,7 +2,7 @@
name = "dart"
icon_state = "dart"
damage = 5
- sharp = 1
+ sharp = TRUE
embed = 1 //the dart is shot fast enough to pierce space suits, so I guess splintering inside the target can be a thing. Should be rare due to low damage.
life_span = 15 //shorter range
muzzle_type = null
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index d01aa247e4b0..d99abdef1e63 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -45,6 +45,7 @@
drop_sound = 'sound/foley/drop1.ogg'
pickup_sound = 'sound/foley/pickup2.ogg'
can_be_twohanded = TRUE // also checks one_hand_penalty
+ needs_attack_dexterity = DEXTERITY_WEAPONS
var/fire_verb = "fire"
var/waterproof = FALSE
@@ -193,15 +194,20 @@
/obj/item/gun/proc/special_check(var/mob/user)
if(!isliving(user))
- return 0
- if(!user.check_dexterity(DEXTERITY_WEAPONS))
- return 0
+ return FALSE
+
+ if(!user.check_dexterity(get_required_attack_dexterity(user)))
+ return FALSE
+
+ if(is_secure_gun() && !free_fire() && (!authorized_modes[sel_mode] || !registered_owner))
+ audible_message(SPAN_WARNING("\The [src] buzzes, refusing to fire."), hearing_distance = 3)
+ playsound(loc, 'sound/machines/buzz-sigh.ogg', 10, 0)
+ return FALSE
var/mob/living/M = user
if(!safety() && world.time > last_safety_check + 5 MINUTES && !user.skill_check(SKILL_WEAPONS, SKILL_BASIC))
if(prob(30))
toggle_safety()
- return 1
if(M.has_genetic_condition(GENE_COND_CLUMSY) && prob(40)) //Clumsy handling
var/obj/P = consume_next_projectile()
@@ -218,8 +224,9 @@
M.try_unequip(src)
else
handle_click_empty(user)
- return 0
- return 1
+ return FALSE
+
+ return TRUE
/obj/item/gun/emp_act(severity)
for(var/obj/O in contents)
diff --git a/code/modules/projectiles/guns/launcher/bows/arrow.dm b/code/modules/projectiles/guns/launcher/bows/arrow.dm
index 1fb6cc358678..073c4d5928ba 100644
--- a/code/modules/projectiles/guns/launcher/bows/arrow.dm
+++ b/code/modules/projectiles/guns/launcher/bows/arrow.dm
@@ -5,8 +5,8 @@
plural_icon_state = ICON_STATE_WORLD + "-mult"
max_icon_state = ICON_STATE_WORLD + "-max"
w_class = ITEM_SIZE_NORMAL
- sharp = 1
- edge = 0
+ sharp = TRUE
+ edge = FALSE
lock_picking_level = 3
material = /decl/material/solid/organic/wood/oak
material_alteration = MAT_FLAG_ALTERATION_COLOR | MAT_FLAG_ALTERATION_NAME | MAT_FLAG_ALTERATION_DESC
diff --git a/code/modules/projectiles/guns/launcher/syringe_gun.dm b/code/modules/projectiles/guns/launcher/syringe_gun.dm
index d44be24924d5..69fa0078472d 100644
--- a/code/modules/projectiles/guns/launcher/syringe_gun.dm
+++ b/code/modules/projectiles/guns/launcher/syringe_gun.dm
@@ -30,7 +30,7 @@
return TRUE
syringe = I
to_chat(user, "You carefully insert [syringe] into [src].")
- sharp = TRUE
+ set_sharp(TRUE)
name = "syringe dart"
update_icon()
return TRUE
@@ -41,7 +41,7 @@
to_chat(user, "You remove [syringe] from [src].")
user.put_in_hands(syringe)
syringe = null
- sharp = initial(sharp)
+ set_sharp(initial(sharp))
SetName(initial(name))
update_icon()
diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm
index d4da8ee50454..e34fd58e0619 100644
--- a/code/modules/projectiles/guns/projectile.dm
+++ b/code/modules/projectiles/guns/projectile.dm
@@ -80,8 +80,8 @@
if(handle_casings == HOLD_CASINGS)
ammo_magazine.stored_ammo += chambered
ammo_magazine.initial_ammo--
- else if(ammo_magazine.stored_ammo.len)
- chambered = ammo_magazine.stored_ammo[ammo_magazine.stored_ammo.len]
+ else if(length(ammo_magazine.stored_ammo))
+ chambered = ammo_magazine.stored_ammo[length(ammo_magazine.stored_ammo)]
if(handle_casings != HOLD_CASINGS)
ammo_magazine.stored_ammo -= chambered
@@ -340,9 +340,9 @@
/obj/item/gun/projectile/proc/get_ammo_indicator()
var/base_state = get_world_inventory_state()
- if(!ammo_magazine || !LAZYLEN(ammo_magazine.stored_ammo))
+ if(!ammo_magazine || !ammo_magazine.get_stored_ammo_count())
return mutable_appearance(icon, "[base_state]_ammo_bad")
- else if(LAZYLEN(ammo_magazine.stored_ammo) <= 0.5 * ammo_magazine.max_ammo)
+ else if(LAZYLEN(ammo_magazine.get_stored_ammo_count()) <= 0.5 * ammo_magazine.max_ammo)
return mutable_appearance(icon, "[base_state]_ammo_warn")
else
return mutable_appearance(icon, "[base_state]_ammo_ok")
diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm
index 7505d0152aa7..802b1f93863c 100644
--- a/code/modules/projectiles/guns/projectile/automatic.dm
+++ b/code/modules/projectiles/guns/projectile/automatic.dm
@@ -35,7 +35,7 @@
/obj/item/gun/projectile/automatic/smg/on_update_icon()
..()
if(ammo_magazine)
- add_overlay("[get_world_inventory_state()]mag-[round(length(ammo_magazine.stored_ammo),5)]")
+ add_overlay("[get_world_inventory_state()]mag-[round(ammo_magazine.get_stored_ammo_count(),5)]")
/obj/item/gun/projectile/automatic/assault_rifle
name = "assault rifle"
diff --git a/code/modules/projectiles/guns/projectile/dartgun.dm b/code/modules/projectiles/guns/projectile/dartgun.dm
index 6c00e6c25942..ee2edcdcfaed 100644
--- a/code/modules/projectiles/guns/projectile/dartgun.dm
+++ b/code/modules/projectiles/guns/projectile/dartgun.dm
@@ -37,13 +37,13 @@
/obj/item/gun/projectile/dartgun/on_update_icon()
..()
if(ammo_magazine)
- icon_state = "[get_world_inventory_state()]-[clamp(length(ammo_magazine.get_stored_ammo_count()), 0, 5)]"
+ icon_state = "[get_world_inventory_state()]-[clamp(ammo_magazine.get_stored_ammo_count(), 0, 5)]"
else
icon_state = get_world_inventory_state()
/obj/item/gun/projectile/dartgun/adjust_mob_overlay(mob/living/user_mob, bodytype, image/overlay, slot, bodypart, use_fallback_if_icon_missing = TRUE)
if(overlay && (slot in user_mob?.get_held_item_slots()) && ammo_magazine)
- overlay.icon_state += "-[clamp(length(ammo_magazine.get_stored_ammo_count()), 0, 5)]"
+ overlay.icon_state += "-[clamp(ammo_magazine.get_stored_ammo_count(), 0, 5)]"
. = ..()
/obj/item/gun/projectile/dartgun/consume_next_projectile()
diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm
index 638376989eeb..e64e7c3f731e 100644
--- a/code/modules/projectiles/guns/projectile/pistol.dm
+++ b/code/modules/projectiles/guns/projectile/pistol.dm
@@ -17,7 +17,7 @@
/obj/item/gun/projectile/pistol/update_base_icon_state()
. = ..()
- if(!length(ammo_magazine?.stored_ammo))
+ if(!ammo_magazine?.get_stored_ammo_count())
var/empty_state = "[icon_state]-e"
if(check_state_in_icon(empty_state, icon))
icon_state = empty_state
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index dc643dcdc3b2..8df181e9195e 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -7,7 +7,7 @@
pass_flags = PASS_FLAG_TABLE | PASS_FLAG_GLASS | PASS_FLAG_GRILLE
damage = 40
atom_damage_type = BURN
- sharp = 1 //concentrated burns
+ sharp = TRUE //concentrated burns
damage_flags = DAM_LASER
eyeblur = 4
hitscan = 1
@@ -210,7 +210,7 @@
icon_state = "stun"
fire_sound = 'sound/weapons/Taser.ogg'
damage_flags = 0
- sharp = 0 //not a laser
+ sharp = FALSE //not a laser
damage = 1//flavor burn! still not a laser, dmg will be reduce by energy resistance not laser resistances
atom_damage_type = BURN
eyeblur = 1//Some feedback that you've been hit
@@ -241,8 +241,8 @@
icon_state = "omnilaser"
fire_sound = 'sound/weapons/plasma_cutter.ogg'
damage = 15
- sharp = 1
- edge = 1
+ sharp = TRUE
+ edge = TRUE
atom_damage_type = BURN
life_span = 5
pass_flags = PASS_FLAG_TABLE
@@ -317,7 +317,7 @@
name = "dark matter wave"
icon_state = "darkt"
damage_flags = 0
- sharp = 0 //not a laser
+ sharp = FALSE //not a laser
agony = 40
atom_damage_type = STUN
muzzle_type = /obj/effect/projectile/muzzle/darkmattertaser
diff --git a/code/modules/projectiles/secure.dm b/code/modules/projectiles/secure.dm
index 241a0e0a8aff..6902b3bddb1e 100644
--- a/code/modules/projectiles/secure.dm
+++ b/code/modules/projectiles/secure.dm
@@ -99,14 +99,6 @@
var/decl/security_state/security_state = GET_DECL(global.using_map.security_state)
return security_state.current_security_level_is_same_or_higher_than(security_state.high_security_level)
-/obj/item/gun/special_check()
- if(is_secure_gun() && !free_fire() && (!authorized_modes[sel_mode] || !registered_owner))
- audible_message(SPAN_WARNING("\The [src] buzzes, refusing to fire."), hearing_distance = 3)
- playsound(loc, 'sound/machines/buzz-sigh.ogg', 10, 0)
- return 0
-
- . = ..()
-
/obj/item/gun/get_next_firemode()
if(!is_secure_gun())
return ..()
diff --git a/code/modules/prometheus_metrics/metric_family.dm b/code/modules/prometheus_metrics/metric_family.dm
index 373130e297a4..0054e97a257e 100644
--- a/code/modules/prometheus_metrics/metric_family.dm
+++ b/code/modules/prometheus_metrics/metric_family.dm
@@ -1,11 +1,11 @@
// Datum used for gathering a set of prometheus metrics.
-/datum/metric_family
+/decl/metric_family
var/name = null
var/metric_type = null
var/help = null
// Collect should return a list of lists with two entries, one being a list and the other being a number.
-/datum/metric_family/proc/collect()
+/decl/metric_family/proc/collect()
var/list/out = list()
out[++out.len] = list(list("foo" = "bar"), 3.14)
@@ -15,9 +15,9 @@
// _to_proto will call the collect() method and format its result in a list
// suitable for encoding as a JSON protobuf mapping.
-/datum/metric_family/proc/_to_proto()
+/decl/metric_family/proc/_to_proto()
var/list/collected = collect()
-
+
var/list/out = list(
"name" = name,
"type" = metric_type,
@@ -36,7 +36,7 @@
label_pairs[++label_pairs.len] = list("name" = k, "value" = m[1][k])
metrics[++metrics.len] = list("label" = label_pairs, PROMETHEUS_METRIC_NAME(metric_type) = list("value" = m[2]))
-
+
if(metrics.len == 0)
return null
out["metric"] = metrics
diff --git a/code/modules/prometheus_metrics/metrics.dm b/code/modules/prometheus_metrics/metrics.dm
index 95e2f8190027..ad98b6c178f9 100644
--- a/code/modules/prometheus_metrics/metrics.dm
+++ b/code/modules/prometheus_metrics/metrics.dm
@@ -1,24 +1,15 @@
-var/global/datum/prometheus_metrics/prometheus_metrics = new
-
// prometheus_metrics holds a list of metric_family datums and uses them to
// create a json protobuf.
-/datum/prometheus_metrics
+/decl/prometheus_metrics
var/list/metric_families
-/datum/prometheus_metrics/New()
- metric_families = list()
- for(var/T in subtypesof(/datum/metric_family))
- var/datum/metric_family/mf = T
- if(initial(mf.name) == null || initial(mf.metric_type) == null)
- continue
- metric_families += new T
-
-/datum/prometheus_metrics/proc/collect()
+/decl/prometheus_metrics/proc/collect()
var/list/out = list()
- for(var/datum/metric_family/MF in metric_families)
- var/proto = MF._to_proto()
+ for(var/decl/metric_family/metric_family in decls_repository.get_decls_of_type_unassociated(/decl/metric_family))
+ var/proto = metric_family._to_proto()
if(proto != null)
- out[++out.len] = MF._to_proto()
-
+ // out += proto will try to merge the lists, we have to insert it at the end instead
+ out[++out.len] = proto
+
return json_encode(out)
diff --git a/code/modules/prometheus_metrics/metrics/byond.dm b/code/modules/prometheus_metrics/metrics/byond.dm
index 232bce38fafe..3aa58ba942d3 100644
--- a/code/modules/prometheus_metrics/metrics/byond.dm
+++ b/code/modules/prometheus_metrics/metrics/byond.dm
@@ -1,29 +1,29 @@
// byond-specific metrics
-/datum/metric_family/byond_time
+/decl/metric_family/byond_time
name = "byond_world_time_seconds"
metric_type = PROMETHEUS_METRIC_COUNTER
help = "Counter of 'game-time' seconds since server startup"
-/datum/metric_family/byond_time/collect()
+/decl/metric_family/byond_time/collect()
return list(list(null, world.time / 10))
-/datum/metric_family/byond_tick_lag
+/decl/metric_family/byond_tick_lag
name = "byond_tick_lag"
metric_type = PROMETHEUS_METRIC_GAUGE
help = "Current value of world.tick_lag"
-/datum/metric_family/byond_tick_lag/collect()
+/decl/metric_family/byond_tick_lag/collect()
return list(list(null, world.tick_lag))
-/datum/metric_family/byond_players
+/decl/metric_family/byond_players
name = "byond_players"
metric_type = PROMETHEUS_METRIC_GAUGE
help = "Number of players currently connected to the server"
-/datum/metric_family/byond_players/collect()
+/decl/metric_family/byond_players/collect()
var/c = 0
for(var/client/C)
if(C.connection == "seeker" || C.connection == "web")
@@ -31,10 +31,10 @@
return list(list(null, c))
-/datum/metric_family/byond_cpu
+/decl/metric_family/byond_cpu
name = "byond_cpu"
metric_type = PROMETHEUS_METRIC_GAUGE
help = "Current value of world.cpu"
-/datum/metric_family/byond_cpu/collect()
+/decl/metric_family/byond_cpu/collect()
return list(list(null, world.cpu))
diff --git a/code/modules/prometheus_metrics/metrics/ss13.dm b/code/modules/prometheus_metrics/metrics/ss13.dm
index 5c6d315b04d0..f686f1d1bed7 100644
--- a/code/modules/prometheus_metrics/metrics/ss13.dm
+++ b/code/modules/prometheus_metrics/metrics/ss13.dm
@@ -1,11 +1,11 @@
// ss13-specific metrics
-/datum/metric_family/ss13_controller_time_seconds
+/decl/metric_family/ss13_controller_time_seconds
name = "ss13_controller_time_seconds"
metric_type = PROMETHEUS_METRIC_COUNTER
help = "Counter of time spent in a controller in seconds"
-/datum/metric_family/ss13_controller_time_seconds/collect()
+/decl/metric_family/ss13_controller_time_seconds/collect()
var/list/out = list()
if(Master)
for(var/name in Master.total_run_times)
@@ -14,23 +14,23 @@
return out
-/datum/metric_family/ss13_master_runlevel
+/decl/metric_family/ss13_master_runlevel
name = "ss13_master_runlevel"
metric_type = PROMETHEUS_METRIC_GAUGE
help = "Current MC runlevel"
-/datum/metric_family/ss13_master_runlevel/collect()
+/decl/metric_family/ss13_master_runlevel/collect()
if(Master)
return list(list(null, Master.current_runlevel))
return list()
-/datum/metric_family/ss13_garbage_queue_length
+/decl/metric_family/ss13_garbage_queue_length
name = "ss13_garbage_queue_length"
metric_type = PROMETHEUS_METRIC_GAUGE
help = "Length of SSgarbage queues"
-/datum/metric_family/ss13_garbage_queue_length/collect()
+/decl/metric_family/ss13_garbage_queue_length/collect()
var/list/out = list()
if(SSgarbage)
@@ -40,12 +40,12 @@
return out
-/datum/metric_family/ss13_garbage_queue_results
+/decl/metric_family/ss13_garbage_queue_results
name = "ss13_garbage_queue_results"
metric_type = PROMETHEUS_METRIC_COUNTER
help = "Counter of pass/fail results for SSgarbage queues"
-/datum/metric_family/ss13_garbage_queue_results/collect()
+/decl/metric_family/ss13_garbage_queue_results/collect()
var/list/out = list()
if(SSgarbage)
@@ -56,12 +56,12 @@
return out
-/datum/metric_family/ss13_garbage_total_cleaned
+/decl/metric_family/ss13_garbage_total_cleaned
name = "ss13_garbage_total_cleaned"
metric_type = PROMETHEUS_METRIC_COUNTER
help = "Counter for number of objects deleted/GCed by SSgarbage"
-/datum/metric_family/ss13_garbage_total_cleaned/collect()
+/decl/metric_family/ss13_garbage_total_cleaned/collect()
var/list/out = list()
if(SSgarbage)
diff --git a/code/modules/random_map/automata/caves.dm b/code/modules/random_map/automata/caves.dm
index d12f5a79204d..91044cd99d54 100644
--- a/code/modules/random_map/automata/caves.dm
+++ b/code/modules/random_map/automata/caves.dm
@@ -2,7 +2,7 @@
iterations = 5
descriptor = "moon caves"
wall_type = /turf/wall/natural
- floor_type = /turf/floor
+ floor_type = /turf/floor/barren
target_turf_type = /turf/unsimulated/mask
var/sparse_mineral_turf = /turf/wall/natural/random
diff --git a/code/modules/random_map/drop/droppod.dm b/code/modules/random_map/drop/droppod.dm
index ac23a7b14e80..926ed6b2d0bd 100644
--- a/code/modules/random_map/drop/droppod.dm
+++ b/code/modules/random_map/drop/droppod.dm
@@ -136,7 +136,6 @@
drop = pick(supplied_drop_types)
supplied_drop_types -= drop
if(istype(drop))
- drop.tag = null
if(drop.buckled)
drop.buckled = null
drop.forceMove(T)
@@ -168,7 +167,6 @@
return
for(var/i=0;i Description: "
if(detailed_blood && istype(reagent, /decl/material/liquid/blood))
var/blood_data = REAGENT_DATA(beaker?.reagents, /decl/material/liquid/blood)
- . += "Blood Type: [LAZYACCESS(blood_data, DATA_BLOOD_TYPE)] DNA: [LAZYACCESS(blood_data, "blood.DNA")]"
+ . += "Blood Type: [LAZYACCESS(blood_data, DATA_BLOOD_TYPE)] DNA: [LAZYACCESS(blood_data, DATA_BLOOD_DNA)]"
else
. += "[reagent.lore_text]"
. += "
(Back)"
diff --git a/code/modules/reagents/chems/chems_blood.dm b/code/modules/reagents/chems/chems_blood.dm
index 1e4696e3ffec..ab5f8e6dd8ec 100644
--- a/code/modules/reagents/chems/chems_blood.dm
+++ b/code/modules/reagents/chems/chems_blood.dm
@@ -72,7 +72,7 @@
/decl/material/liquid/blood/get_reagent_color(datum/reagents/holder)
var/list/blood_data = REAGENT_DATA(holder, type)
- return blood_data?["blood_color"] || ..()
+ return blood_data?[DATA_BLOOD_COLOR] || ..()
/decl/material/liquid/coagulated_blood
name = "coagulated blood"
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index db9048920333..de18007e761a 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -200,9 +200,17 @@
//
// Interactions
//
+/obj/item/chems/get_quick_interaction_handler(mob/user)
+ var/static/interaction = GET_DECL(/decl/interaction_handler/set_transfer/chems)
+ return interaction
+
/obj/item/chems/get_alt_interactions(var/mob/user)
. = ..()
- LAZYADD(., /decl/interaction_handler/set_transfer/chems)
+ var/static/list/chem_interactions = list(
+ /decl/interaction_handler/set_transfer/chems,
+ /decl/interaction_handler/empty/chems
+ )
+ LAZYADD(., chem_interactions)
/decl/interaction_handler/set_transfer/chems
expected_target_type = /obj/item/chems
diff --git a/code/modules/reagents/reagent_containers/_glass.dm b/code/modules/reagents/reagent_containers/_glass.dm
index aee39d399219..f381c8a44bba 100644
--- a/code/modules/reagents/reagent_containers/_glass.dm
+++ b/code/modules/reagents/reagent_containers/_glass.dm
@@ -82,7 +82,7 @@
return ..()
/obj/item/chems/glass/use_on_mob(mob/living/target, mob/living/user, animate = TRUE)
- if(get_attack_force(user) && !(item_flags & ITEM_FLAG_NO_BLUDGEON) && user.check_intent(I_FLAG_HARM))
+ if(expend_attack_force(user) && !(item_flags & ITEM_FLAG_NO_BLUDGEON) && user.check_intent(I_FLAG_HARM))
return ..()
return FALSE
diff --git a/code/modules/reagents/reagent_containers/drinks.dm b/code/modules/reagents/reagent_containers/drinks.dm
index 695412409f84..d80b593cf60f 100644
--- a/code/modules/reagents/reagent_containers/drinks.dm
+++ b/code/modules/reagents/reagent_containers/drinks.dm
@@ -148,7 +148,7 @@
add_to_reagents(/decl/material/liquid/drink/milk/chocolate, reagents.maximum_volume)
/obj/item/chems/drinks/coffee
- name = "\improper Robust Coffee"
+ name = "cup of coffee"
desc = "Careful, the beverage you're about to enjoy is extremely hot."
icon_state = "coffee"
center_of_mass = @'{"x":15,"y":10}'
@@ -269,16 +269,14 @@
//tea and tea accessories
/obj/item/chems/drinks/tea
- name = "cup of tea master item"
+ name = "cup of tea"
desc = "A tall plastic cup full of the concept and ideal of tea."
icon_state = "coffee"
item_state = "coffee"
center_of_mass = @'{"x":16,"y":14}'
filling_states = @"[100]"
- base_name = "cup"
base_icon = "cup"
volume = 30
- presentation_flags = PRESENTATION_FLAG_NAME
/obj/item/chems/drinks/tea/black
name = "cup of black tea"
diff --git a/code/modules/reagents/reagent_containers/drinks/bottle.dm b/code/modules/reagents/reagent_containers/drinks/bottle.dm
index 5d0776020c41..56e5f6b47206 100644
--- a/code/modules/reagents/reagent_containers/drinks/bottle.dm
+++ b/code/modules/reagents/reagent_containers/drinks/bottle.dm
@@ -168,7 +168,7 @@
user.visible_message(SPAN_DANGER("\The [user] smashes \the [src] into [H]'s [affecting.name]!"))
// You are going to knock someone out for longer if they are not wearing a helmet.
var/blocked = target.get_blocked_ratio(hit_zone, BRUTE, damage = 10) * 100
- var/weaken_duration = smash_duration + min(0, get_attack_force(user) - blocked + 10)
+ var/weaken_duration = smash_duration + min(0, expend_attack_force(user) - blocked + 10)
if(weaken_duration)
target.apply_effect(min(weaken_duration, 5), WEAKEN, blocked) // Never weaken more than a flash!
else
@@ -228,8 +228,7 @@
throw_range = 5
item_state = "beer"
attack_verb = list("stabbed", "slashed", "attacked")
- sharp = 1
- edge = 0
+ sharp = TRUE
obj_flags = OBJ_FLAG_HOLLOW
material = /decl/material/solid/glass
_base_attack_force = 9
diff --git a/code/modules/reagents/reagent_containers/food.dm b/code/modules/reagents/reagent_containers/food.dm
index c28d70364f65..55309ff3d2cc 100644
--- a/code/modules/reagents/reagent_containers/food.dm
+++ b/code/modules/reagents/reagent_containers/food.dm
@@ -142,7 +142,7 @@
/obj/item/food/Destroy()
QDEL_NULL(plate)
trash = null
- if(contents)
+ if(length(contents))
for(var/atom/movable/something in contents)
something.dropInto(loc)
. = ..()
diff --git a/code/modules/reagents/reagent_containers/food/fish.dm b/code/modules/reagents/reagent_containers/food/fish.dm
index d4a3a57106ba..fd8ec91188e0 100644
--- a/code/modules/reagents/reagent_containers/food/fish.dm
+++ b/code/modules/reagents/reagent_containers/food/fish.dm
@@ -70,7 +70,7 @@
qdel(src)
/obj/item/mollusc/attackby(var/obj/item/thing, var/mob/user)
- if(thing.sharp || thing.edge)
+ if(thing.is_sharp() || thing.has_edge())
user.visible_message(SPAN_NOTICE("\The [user] cracks open \the [src] with \the [thing]."))
crack_shell(user)
return TRUE
diff --git a/code/modules/reagents/reagent_containers/inhaler.dm b/code/modules/reagents/reagent_containers/inhaler.dm
index 275a3bac13dd..19eaaa9cd1d0 100644
--- a/code/modules/reagents/reagent_containers/inhaler.dm
+++ b/code/modules/reagents/reagent_containers/inhaler.dm
@@ -62,7 +62,7 @@
if(user == target)
user.visible_message(
SPAN_NOTICE("\The [user] inhales from \the [src]."),
- SPAN_NOTICE("You stick the \the [src] in your mouth and press the injection button.")
+ SPAN_NOTICE("You stick \the [src] in your mouth and press the injection button.")
)
else
user.visible_message(
diff --git a/code/modules/reagents/reagent_containers/mortar.dm b/code/modules/reagents/reagent_containers/mortar.dm
index fe85a5c09fee..b19a7340e236 100644
--- a/code/modules/reagents/reagent_containers/mortar.dm
+++ b/code/modules/reagents/reagent_containers/mortar.dm
@@ -28,7 +28,7 @@
var/decl/material/attacking_material = using_item.get_material()
var/decl/material/crushing_material = crushing_item?.get_material()
var/skill_factor = CLAMP01(1 + 0.3*(user.get_skill_value(SKILL_CHEMISTRY) - SKILL_EXPERT)/(SKILL_EXPERT - SKILL_MIN))
- if(using_item.get_attack_force(user) <= 0 || !attacking_material || !crushing_material)
+ if(using_item.expend_attack_force(user) <= 0 || !attacking_material || !crushing_material)
return TRUE
if(attacking_material.hardness <= crushing_material.hardness)
to_chat(user, SPAN_NOTICE("\The [using_item] is not hard enough to crush \the [crushing_item]."))
diff --git a/code/modules/reagents/reagent_containers/packets.dm b/code/modules/reagents/reagent_containers/packets.dm
index c46af37998fb..391c3440471b 100644
--- a/code/modules/reagents/reagent_containers/packets.dm
+++ b/code/modules/reagents/reagent_containers/packets.dm
@@ -7,7 +7,14 @@
amount_per_transfer_from_this = 1
volume = 10
-/obj/item/chems/packet/afterattack(var/obj/target, var/mob/user, var/proximity)
+/obj/item/chems/packet/attack_self(mob/user)
+ if(!ATOM_IS_OPEN_CONTAINER(src))
+ atom_flags |= ATOM_FLAG_OPEN_CONTAINER
+ to_chat(user, SPAN_NOTICE("You tear \the [src] open."))
+ return TRUE
+ return ..()
+
+/obj/item/chems/packet/afterattack(obj/target, mob/user, proximity)
if(!proximity)
return ..()
if(standard_dispenser_refill(user, target))
@@ -54,6 +61,14 @@
icon = 'icons/obj/food/condiments/packets/packet_medium.dmi'
/obj/item/chems/packet/honey/populate_reagents()
+ add_to_reagents(/decl/material/liquid/nutriment/honey, reagents.maximum_volume)
+
+/obj/item/chems/packet/honey_fake
+ name = "'honey' packet"
+ desc = "Contains 10u of allergen-free non-GMO 'honey'."
+ icon = 'icons/obj/food/condiments/packets/packet_medium.dmi'
+
+/obj/item/chems/packet/honey_fake/populate_reagents()
add_to_reagents(/decl/material/liquid/nutriment/sugar, reagents.maximum_volume)
/obj/item/chems/packet/capsaicin
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index f55288be25ec..6af31c901452 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -17,7 +17,7 @@
volume = 15
w_class = ITEM_SIZE_TINY
slot_flags = SLOT_EARS
- sharp = 1
+ sharp = TRUE
item_flags = ITEM_FLAG_NO_BLUDGEON
var/mode = SYRINGE_DRAW
diff --git a/code/modules/recycling/disposalholder.dm b/code/modules/recycling/disposalholder.dm
index 4f3546d06a64..7a95d7d2ce28 100644
--- a/code/modules/recycling/disposalholder.dm
+++ b/code/modules/recycling/disposalholder.dm
@@ -82,11 +82,11 @@
if(!curr)
last.expel(src, loc, dir)
- // find the turf which should contain the next pipe
+/// find the turf which should contain the next pipe
/obj/structure/disposalholder/proc/nextloc()
return get_step(loc,dir)
-// find a matching pipe on a turf
+/// find a matching pipe on a turf
/obj/structure/disposalholder/proc/findpipe(var/turf/containing_turf)
if(!containing_turf)
return null
@@ -98,8 +98,8 @@
// if no matching pipe, return null
return null
-// merge two holder objects
-// used when a a holder meets a stuck holder
+/// merge two holder objects
+/// used when a holder meets a stuck holder
/obj/structure/disposalholder/proc/merge(var/obj/structure/disposalholder/other)
for(var/atom/movable/other_movable in other)
other_movable.forceMove(src) // move everything in other holder to this one
@@ -119,7 +119,7 @@
else
partialTag = new_tag
-// called when player tries to move while in a pipe
+/// called when player tries to move while in a pipe
/obj/structure/disposalholder/relaymove(mob/user)
if(!isliving(user))
return
diff --git a/code/modules/recycling/disposalpipe.dm b/code/modules/recycling/disposalpipe.dm
index e035da8b8254..88e11fbbdc60 100644
--- a/code/modules/recycling/disposalpipe.dm
+++ b/code/modules/recycling/disposalpipe.dm
@@ -184,8 +184,7 @@
if(H)
expel(H, T, 0)
- spawn(2) // delete pipe after 2 ticks to ensure expel proc finished
- qdel(src)
+ QDEL_IN(src, 2) // delete pipe after 2 ticks to ensure expel proc finished
// pipe affected by explosion
@@ -235,11 +234,6 @@
/obj/structure/disposalpipe/hides_under_flooring()
return 1
-// *** TEST verb
-//client/verb/dispstop()
-// for(var/obj/structure/disposalholder/H in world)
-// H.active = 0
-
// a straight or bent segment
/obj/structure/disposalpipe/segment
icon_state = "pipe-s" // Sadly this var stores state. "pipe-c" is corner. Should be changed, but requires huge map diff.
diff --git a/code/modules/recycling/wrapped_package.dm b/code/modules/recycling/wrapped_package.dm
index 57261df802b3..da2a33bfd701 100644
--- a/code/modules/recycling/wrapped_package.dm
+++ b/code/modules/recycling/wrapped_package.dm
@@ -195,7 +195,7 @@
update_icon()
return TRUE
- else if(W.sharp && user.check_intent(I_FLAG_HELP))
+ else if(W.is_sharp() && user.check_intent(I_FLAG_HELP))
//You can alternative cut the wrapper off with a sharp item
unwrap(user)
return TRUE
diff --git a/code/modules/shield_generators/shield.dm b/code/modules/shield_generators/shield.dm
index 0b97dd24cbf0..b39816fdce51 100644
--- a/code/modules/shield_generators/shield.dm
+++ b/code/modules/shield_generators/shield.dm
@@ -37,7 +37,7 @@
if(update_neighbors)
for(var/obj/effect/shield/shield in T)
shield.update_icon(FALSE)
- add_overlay(image(icon = icon, icon_state = "[icon_state]_edge", dir = direction))
+ add_overlay(image(icon = icon, icon_state = "[icon_state]edge", dir = direction))
// Prevents shuttles, singularities and pretty much everything else from moving the field segments away.
// The only thing that is allowed to move us is the Destroy() proc.
@@ -217,7 +217,7 @@
if(!gen.check_flag(MODEFLAG_HYPERKINETIC))
user.visible_message("\The [user] tries to attack \the [src] with \the [weapon], but it passes through!")
return TRUE
- var/force = weapon.get_attack_force(user)
+ var/force = weapon.expend_attack_force(user)
user.visible_message("\The [user] [pick(weapon.attack_verb)] \the [src] with \the [weapon]!")
switch(weapon.atom_damage_type)
if(BURN)
diff --git a/code/modules/shieldgen/emergency_shield.dm b/code/modules/shieldgen/emergency_shield.dm
index f76892be8a40..0cb3ee417b94 100644
--- a/code/modules/shieldgen/emergency_shield.dm
+++ b/code/modules/shieldgen/emergency_shield.dm
@@ -55,7 +55,7 @@
//Calculate damage
switch(W.atom_damage_type)
if(BRUTE, BURN)
- current_health -= W.get_attack_force(user)
+ current_health -= W.expend_attack_force(user)
else
return FALSE
diff --git a/code/modules/shieldgen/shieldwallgen.dm b/code/modules/shieldgen/shieldwallgen.dm
index 126820437525..0ca75384784e 100644
--- a/code/modules/shieldgen/shieldwallgen.dm
+++ b/code/modules/shieldgen/shieldwallgen.dm
@@ -289,7 +289,7 @@
/obj/machinery/shieldwall/attackby(var/obj/item/I, var/mob/user)
var/obj/machinery/shieldwallgen/G = prob(50) ? gen_primary : gen_secondary
- G.storedpower -= I.get_attack_force(user)*2500
+ G.storedpower -= I.expend_attack_force(user)*2500
user.visible_message("\The [user] hits \the [src] with \the [I]!")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.do_attack_animation(src)
diff --git a/code/modules/shuttles/escape_pods.dm b/code/modules/shuttles/escape_pods.dm
index c12dc6e38d90..bd13d30c417b 100644
--- a/code/modules/shuttles/escape_pods.dm
+++ b/code/modules/shuttles/escape_pods.dm
@@ -3,7 +3,7 @@ var/global/list/escape_pods_by_name = list()
/datum/shuttle/autodock/ferry/escape_pod
var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/arming_controller
- category = /datum/shuttle/autodock/ferry/escape_pod
+ abstract_type = /datum/shuttle/autodock/ferry/escape_pod
move_time = 100
/datum/shuttle/autodock/ferry/escape_pod/New(map_hash)
diff --git a/code/modules/shuttles/shuttle.dm b/code/modules/shuttles/shuttle.dm
index 794f0736f127..85ee565817b5 100644
--- a/code/modules/shuttles/shuttle.dm
+++ b/code/modules/shuttles/shuttle.dm
@@ -12,7 +12,7 @@
var/arrive_time = 0 //the time at which the shuttle arrives when long jumping
var/flags = 0
var/process_state = IDLE_STATE //Used with SHUTTLE_FLAGS_PROCESS, as well as to store current state.
- var/category = /datum/shuttle
+ abstract_type = /datum/shuttle
var/multiz = 0 //how many multiz levels, starts at 0
var/ceiling_type = /turf/unsimulated/floor/shuttle_ceiling
diff --git a/code/modules/shuttles/shuttle_autodock.dm b/code/modules/shuttles/shuttle_autodock.dm
index 74c157df8fed..f2003eb0129d 100644
--- a/code/modules/shuttles/shuttle_autodock.dm
+++ b/code/modules/shuttles/shuttle_autodock.dm
@@ -16,7 +16,7 @@
var/obj/effect/shuttle_landmark/landmark_transition //This variable is type-abused initially: specify the landmark_tag, not the actual landmark.
var/move_time = 240 //the time spent in the transition area
- category = /datum/shuttle/autodock
+ abstract_type = /datum/shuttle/autodock
flags = SHUTTLE_FLAGS_PROCESS | SHUTTLE_FLAGS_ZERO_G
/datum/shuttle/autodock/New(var/map_hash, var/obj/effect/shuttle_landmark/start_waypoint)
diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm
index 2bdc11d22846..f6efaa4a8645 100644
--- a/code/modules/shuttles/shuttle_emergency.dm
+++ b/code/modules/shuttles/shuttle_emergency.dm
@@ -1,5 +1,5 @@
/datum/shuttle/autodock/ferry/emergency
- category = /datum/shuttle/autodock/ferry/emergency
+ abstract_type = /datum/shuttle/autodock/ferry/emergency
move_time = 10 MINUTES
flags = SHUTTLE_FLAGS_PROCESS | SHUTTLE_FLAGS_ZERO_G | SHUTTLE_FLAGS_NO_CODE
var/datum/evacuation_controller/shuttle/emergency_controller
diff --git a/code/modules/shuttles/shuttle_ferry.dm b/code/modules/shuttles/shuttle_ferry.dm
index 4f23361de2b3..ebe0a7cf54f6 100644
--- a/code/modules/shuttles/shuttle_ferry.dm
+++ b/code/modules/shuttles/shuttle_ferry.dm
@@ -7,7 +7,7 @@
var/obj/effect/shuttle_landmark/waypoint_station //This variable is type-abused initially: specify the landmark_tag, not the actual landmark.
var/obj/effect/shuttle_landmark/waypoint_offsite //This variable is type-abused initially: specify the landmark_tag, not the actual landmark.
- category = /datum/shuttle/autodock/ferry
+ abstract_type = /datum/shuttle/autodock/ferry
/datum/shuttle/autodock/ferry/New(map_hash)
if(map_hash)
diff --git a/code/modules/shuttles/shuttle_specops.dm b/code/modules/shuttles/shuttle_specops.dm
index 41778075e990..90a54b1eab08 100644
--- a/code/modules/shuttles/shuttle_specops.dm
+++ b/code/modules/shuttles/shuttle_specops.dm
@@ -14,10 +14,7 @@
var/reset_time = 0 //the world.time at which the shuttle will be ready to move again.
var/launch_prep = 0
var/cancel_countdown = 0
- category = /datum/shuttle/autodock/ferry/specops
-
-/datum/shuttle/autodock/ferry/specops/New()
- ..()
+ abstract_type = /datum/shuttle/autodock/ferry/specops
/datum/shuttle/autodock/ferry/specops/launch(var/user)
if (!can_launch())
@@ -98,7 +95,7 @@
return ..()
/datum/shuttle/autodock/ferry/specops/proc/sleep_until_launch()
- var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
+ var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a list with potential time values.
var/launch_time = world.time + specops_countdown_time
var/time_until_launch
diff --git a/code/modules/shuttles/shuttle_supply.dm b/code/modules/shuttles/shuttle_supply.dm
index 175924860dcb..f38e5fef5b31 100644
--- a/code/modules/shuttles/shuttle_supply.dm
+++ b/code/modules/shuttles/shuttle_supply.dm
@@ -3,7 +3,7 @@
var/late_chance = 80
var/max_late_time = (30 SECONDS)
flags = SHUTTLE_FLAGS_PROCESS|SHUTTLE_FLAGS_SUPPLY|SHUTTLE_FLAGS_NO_CODE
- category = /datum/shuttle/autodock/ferry/supply
+ abstract_type = /datum/shuttle/autodock/ferry/supply
ceiling_type = /turf/floor/shuttle_ceiling
/datum/shuttle/autodock/ferry/supply/short_jump(var/area/destination)
diff --git a/code/modules/shuttles/shuttles_multi.dm b/code/modules/shuttles/shuttles_multi.dm
index 35e00c68be6d..71e144e02e27 100644
--- a/code/modules/shuttles/shuttles_multi.dm
+++ b/code/modules/shuttles/shuttles_multi.dm
@@ -2,7 +2,7 @@
var/list/destination_tags
var/list/destinations_cache = list()
var/last_cache_rebuild_time = 0
- category = /datum/shuttle/autodock/multi
+ abstract_type = /datum/shuttle/autodock/multi
/datum/shuttle/autodock/multi/New(map_hash)
..()
@@ -42,7 +42,7 @@
var/arrival_message
var/departure_message
- category = /datum/shuttle/autodock/multi/antag
+ abstract_type = /datum/shuttle/autodock/multi/antag
/datum/shuttle/autodock/multi/antag/New(map_hash)
..()
diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm
index 32980d3c189e..6ef37bd2681e 100644
--- a/code/modules/species/species.dm
+++ b/code/modules/species/species.dm
@@ -79,10 +79,6 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200
// Combat vars.
var/total_health = DEFAULT_SPECIES_HEALTH // Point at which the mob will enter crit.
- var/list/unarmed_attacks = list( // Possible unarmed attacks that the mob will use in combat,
- /decl/natural_attack,
- /decl/natural_attack/bite
- )
var/brute_mod = 1 // Physical damage multiplier.
var/burn_mod = 1 // Burn damage multiplier.
@@ -492,23 +488,6 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200
return TRUE //We could tie it to stamina
return FALSE
-// Called when using the shredding behavior.
-/decl/species/proc/can_shred(var/mob/living/human/H, var/ignore_intent, var/ignore_antag)
-
- if((!ignore_intent && !H.check_intent(I_FLAG_HARM)) || H.pulling_punches)
- return 0
-
- if(!ignore_antag && H.mind && !player_is_antag(H.mind))
- return 0
-
- for(var/attack_type in unarmed_attacks)
- var/decl/natural_attack/attack = GET_DECL(attack_type)
- if(!istype(attack) || !attack.is_usable(H))
- continue
- if(attack.shredding)
- return 1
- return 0
-
/decl/species/proc/handle_vision(var/mob/living/human/H)
var/list/vision = H.get_accumulated_vision_handlers()
H.update_sight()
diff --git a/code/modules/species/species_attack.dm b/code/modules/species/species_attack.dm
index d2daf2daa062..0fffa9846431 100644
--- a/code/modules/species/species_attack.dm
+++ b/code/modules/species/species_attack.dm
@@ -2,8 +2,8 @@
attack_verb = list("bit", "chomped on")
attack_sound = 'sound/weapons/bite.ogg'
shredding = 0
- sharp = 1
- edge = 1
+ sharp = TRUE
+ edge = TRUE
name = "sharp bite"
/decl/natural_attack/claws
@@ -14,8 +14,8 @@
eye_attack_text_victim = "sharp claws"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
- sharp = 1
- edge = 1
+ sharp = TRUE
+ edge = TRUE
name = "claws"
usable_with_limbs = list(BP_L_HAND, BP_R_HAND)
var/blocked_by_gloves = TRUE
diff --git a/code/modules/species/species_helpers.dm b/code/modules/species/species_helpers.dm
index 5bd257fa5bcd..efd996aaf266 100644
--- a/code/modules/species/species_helpers.dm
+++ b/code/modules/species/species_helpers.dm
@@ -1,14 +1,9 @@
var/global/list/stored_shock_by_ref = list()
/mob/living/proc/apply_stored_shock_to(var/mob/living/target)
- if(stored_shock_by_ref["\ref[src]"])
- target.electrocute_act(stored_shock_by_ref["\ref[src]"]*0.9, src)
- stored_shock_by_ref["\ref[src]"] = 0
-
-/decl/species/proc/toggle_stance(var/mob/living/human/H)
- if(!H.incapacitated())
- H.pulling_punches = !H.pulling_punches
- to_chat(H, "You are now [H.pulling_punches ? "pulling your punches" : "not pulling your punches"].")
+ if(global.stored_shock_by_ref["\ref[src]"])
+ target.electrocute_act(global.stored_shock_by_ref["\ref[src]"]*0.9, src)
+ global.stored_shock_by_ref["\ref[src]"] = 0
/decl/species/proc/fluid_act(var/mob/living/human/H, var/datum/reagents/fluids)
SHOULD_CALL_PARENT(TRUE)
diff --git a/code/modules/species/species_hud.dm b/code/modules/species/species_hud.dm
index f63a7bc37bf1..7add078db3ac 100644
--- a/code/modules/species/species_hud.dm
+++ b/code/modules/species/species_hud.dm
@@ -1,6 +1,5 @@
/datum/hud_data
- /// Set to draw intent box.
- var/show_intent_selector = 1
+
/// Set to draw move intent box.
var/has_m_intent = 1
/// Set to draw environment warnings.
diff --git a/code/modules/species/station/golem.dm b/code/modules/species/station/golem.dm
index 9f571d66c608..93dc4786eaeb 100644
--- a/code/modules/species/station/golem.dm
+++ b/code/modules/species/station/golem.dm
@@ -16,7 +16,6 @@
available_bodytypes = list(/decl/bodytype/crystalline/golem)
- unarmed_attacks = list(/decl/natural_attack/stomp, /decl/natural_attack/kick, /decl/natural_attack/punch)
species_flags = SPECIES_FLAG_NO_POISON
spawn_flags = SPECIES_IS_RESTRICTED
shock_vulnerability = 0
diff --git a/code/modules/species/station/human.dm b/code/modules/species/station/human.dm
index 6264a7b20482..2ee92427f41f 100644
--- a/code/modules/species/station/human.dm
+++ b/code/modules/species/station/human.dm
@@ -2,12 +2,6 @@
name = SPECIES_HUMAN
name_plural = "Humans"
primitive_form = SPECIES_MONKEY
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite
- )
description = "A medium-sized creature prone to great ambition. If you are reading this, you are probably a human."
hidden_from_codex = FALSE
spawn_flags = SPECIES_CAN_JOIN
diff --git a/code/modules/species/station/monkey.dm b/code/modules/species/station/monkey.dm
index 9159f5eadc3c..1871219744e5 100644
--- a/code/modules/species/station/monkey.dm
+++ b/code/modules/species/station/monkey.dm
@@ -15,7 +15,6 @@
dusted_anim = "dust-m"
death_message = "lets out a faint chimper as it collapses and stops moving..."
- unarmed_attacks = list(/decl/natural_attack/bite, /decl/natural_attack/claws, /decl/natural_attack/punch)
inherent_verbs = list(/mob/living/proc/ventcrawl)
species_hud = /datum/hud_data/monkey
butchery_data = /decl/butchery_data/humanoid/monkey
diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm
index 1b8ef1751a04..be2f0f6b69dc 100644
--- a/code/modules/surgery/implant.dm
+++ b/code/modules/surgery/implant.dm
@@ -21,6 +21,12 @@
affected.take_external_damage(20, 0, (DAM_SHARP|DAM_EDGE), used_weapon = tool)
..()
+/decl/surgery_step/cavity/get_skill_reqs(mob/living/user, mob/living/target, obj/item/tool, target_zone)
+ var/obj/item/organ/external/affected = GET_EXTERNAL_ORGAN(target, target_zone)
+ if(!affected || !BP_IS_PROSTHETIC(affected) || BP_IS_CRYSTAL(affected))
+ return ..()
+ return SURGERY_SKILLS_ROBOTIC
+
//////////////////////////////////////////////////////////////////
// create implant space surgery step
//////////////////////////////////////////////////////////////////
@@ -38,16 +44,16 @@
/decl/surgery_step/cavity/make_space/begin_step(mob/user, mob/living/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = GET_EXTERNAL_ORGAN(target, target_zone)
- user.visible_message("[user] starts making some space inside [target]'s [affected.cavity_name] cavity with \the [tool].", \
- "You start making some space inside [target]'s [affected.cavity_name] cavity with \the [tool]." )
+ user.visible_message("[user] starts making some space inside [target]'s [affected.cavity_name] with \the [tool].", \
+ "You start making some space inside [target]'s [affected.cavity_name] with \the [tool]." )
target.custom_pain("The pain in your chest is living hell!",1,affecting = affected)
affected.cavity = TRUE
..()
/decl/surgery_step/cavity/make_space/end_step(mob/living/user, mob/living/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = GET_EXTERNAL_ORGAN(target, target_zone)
- user.visible_message("[user] makes some space inside [target]'s [affected.cavity_name] cavity with \the [tool].", \
- "You make some space inside [target]'s [affected.cavity_name] cavity with \the [tool]." )
+ user.visible_message("[user] makes some space inside [target]'s \the [affected.cavity_name] with \the [tool].", \
+ "You make some space inside [target]'s \the [affected.cavity_name] with \the [tool]." )
..()
//////////////////////////////////////////////////////////////////
@@ -70,15 +76,15 @@
/decl/surgery_step/cavity/close_space/begin_step(mob/user, mob/living/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = GET_EXTERNAL_ORGAN(target, target_zone)
- user.visible_message("[user] starts mending [target]'s [affected.cavity_name] cavity wall with \the [tool].", \
- "You start mending [target]'s [affected.cavity_name] cavity wall with \the [tool]." )
+ user.visible_message("[user] starts mending [target]'s \the [affected.cavity_name] wall with \the [tool].", \
+ "You start mending [target]'s \the [affected.cavity_name] wall with \the [tool]." )
target.custom_pain("The pain in your chest is living hell!",1,affecting = affected)
..()
/decl/surgery_step/cavity/close_space/end_step(mob/living/user, mob/living/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = GET_EXTERNAL_ORGAN(target, target_zone)
- user.visible_message("[user] mends [target]'s [affected.cavity_name] cavity walls with \the [tool].", \
- "You mend [target]'s [affected.cavity_name] cavity walls with \the [tool]." )
+ user.visible_message("[user] mends [target]'s \the [affected.cavity_name] walls with \the [tool].", \
+ "You mend [target]'s \the [affected.cavity_name] walls with \the [tool]." )
affected.cavity = FALSE
..()
@@ -109,7 +115,7 @@
if(affected && affected.cavity)
var/max_volume = BASE_STORAGE_CAPACITY(affected.cavity_max_w_class) + affected.internal_organs_size
if(tool.w_class > affected.cavity_max_w_class)
- to_chat(user, SPAN_WARNING("\The [tool] is too big for [affected.cavity_name] cavity."))
+ to_chat(user, SPAN_WARNING("\The [tool] is too big for \the [affected.cavity_name]."))
return FALSE
var/total_volume = tool.get_storage_cost()
for(var/obj/item/I in affected.implants)
@@ -119,14 +125,14 @@
for(var/obj/item/organ/internal/org in affected.internal_organs)
max_volume -= org.get_storage_cost()
if(total_volume > max_volume)
- to_chat(user, SPAN_WARNING("There isn't enough space left in [affected.cavity_name] cavity for [tool]."))
+ to_chat(user, SPAN_WARNING("There isn't enough space left in \the [affected.cavity_name] for [tool]."))
return FALSE
return TRUE
/decl/surgery_step/cavity/place_item/begin_step(mob/user, mob/living/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = GET_EXTERNAL_ORGAN(target, target_zone)
- user.visible_message("[user] starts putting \the [tool] inside [target]'s [affected.cavity_name] cavity.", \
- "You start putting \the [tool] inside [target]'s [affected.cavity_name] cavity." )
+ user.visible_message("[user] starts putting \the [tool] inside [target]'s \the [affected.cavity_name].", \
+ "You start putting \the [tool] inside [target]'s \the [affected.cavity_name]." )
target.custom_pain("The pain in your chest is living hell!",1,affecting = affected)
..()
@@ -134,8 +140,8 @@
var/obj/item/organ/external/affected = GET_EXTERNAL_ORGAN(target, target_zone)
if(!user.try_unequip(tool, affected))
return
- user.visible_message("[user] puts \the [tool] inside [target]'s [affected.cavity_name] cavity.", \
- "You put \the [tool] inside [target]'s [affected.cavity_name] cavity." )
+ user.visible_message("[user] puts \the [tool] inside [target]'s \the [affected.cavity_name].", \
+ "You put \the [tool] inside [target]'s \the [affected.cavity_name]." )
if (tool.w_class > affected.cavity_max_w_class/2 && prob(50) && !BP_IS_PROSTHETIC(affected) && affected.sever_artery())
to_chat(user, "You tear some blood vessels trying to fit such a big object in this cavity.")
affected.owner.custom_pain("You feel something rip in your [affected.name]!", 1,affecting = affected)
diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm
index 916db17c1d2b..76b37e9eb8dd 100644
--- a/code/modules/surgery/organs_internal.dm
+++ b/code/modules/surgery/organs_internal.dm
@@ -262,7 +262,7 @@
return FALSE
if(O.w_class > affected.cavity_max_w_class)
- to_chat(user, SPAN_WARNING("\The [O.name] [pronouns.is] too big for [affected.cavity_name] cavity!"))
+ to_chat(user, SPAN_WARNING("\The [O.name] [pronouns.is] too big for \the [affected.cavity_name]!"))
return FALSE
var/obj/item/organ/internal/I = GET_INTERNAL_ORGAN(target, O.organ_tag)
diff --git a/code/modules/tools/archetypes/tool_archetype_definitions.dm b/code/modules/tools/archetypes/tool_archetype_definitions.dm
index 25df48e3afda..2b2b2f14f4d6 100644
--- a/code/modules/tools/archetypes/tool_archetype_definitions.dm
+++ b/code/modules/tools/archetypes/tool_archetype_definitions.dm
@@ -70,16 +70,16 @@
/decl/tool_archetype/knife/get_default_quality(obj/item/tool)
if(tool)
- if(tool.sharp && tool.edge)
+ if(tool.is_sharp() && tool.has_edge())
return TOOL_QUALITY_DEFAULT
- else if(tool.sharp || tool.edge)
+ else if(tool.is_sharp() || tool.has_edge())
return TOOL_QUALITY_MEDIOCRE
return ..()
/decl/tool_archetype/knife/get_default_speed(obj/item/tool)
if(tool)
- if(tool.sharp && tool.edge)
+ if(tool.is_sharp() && tool.has_edge())
return TOOL_SPEED_DEFAULT
- else if(tool.sharp || tool.edge)
+ else if(tool.is_sharp() || tool.has_edge())
return TOOL_SPEED_MEDIOCRE
return ..()
diff --git a/code/modules/tools/subtypes/hammers.dm b/code/modules/tools/subtypes/hammers.dm
index 79e5e26956dc..ff5d1ef19892 100644
--- a/code/modules/tools/subtypes/hammers.dm
+++ b/code/modules/tools/subtypes/hammers.dm
@@ -2,8 +2,6 @@
name = "hammer"
desc = "A simple hammer. Ancient technology once thought lost."
icon = 'icons/obj/items/tool/hammers/hammer.dmi'
- sharp = 0
- edge = 0
attack_verb = list(
"bludgeons",
"slaps",
diff --git a/code/modules/tools/subtypes/xenoarchaeology_picks.dm b/code/modules/tools/subtypes/xenoarchaeology_picks.dm
index 9db2d59f5418..2a335b9fa4ca 100644
--- a/code/modules/tools/subtypes/xenoarchaeology_picks.dm
+++ b/code/modules/tools/subtypes/xenoarchaeology_picks.dm
@@ -7,7 +7,7 @@
material = /decl/material/solid/metal/chromium
matter = list(/decl/material/solid/metal/steel = MATTER_AMOUNT_SECONDARY)
w_class = ITEM_SIZE_SMALL
- sharp = 1
+ sharp = TRUE
abstract_type = /obj/item/tool/xeno
material_alteration = 0
handle_material = /decl/material/solid/organic/plastic
@@ -36,18 +36,18 @@
to_chat(user, "This tool has a [get_tool_property(TOOL_PICK, TOOL_PROP_EXCAVATION_DEPTH) || 0] centimetre excavation depth.")
/obj/item/tool/xeno/brush
- name = "wire brush"
- icon_state = "pick_brush"
- slot_flags = SLOT_EARS
- _base_attack_force = 1
- attack_verb = list("prodded", "attacked")
- desc = "A wood-handled brush with thick metallic wires for clearing away dust and loose scree."
- sharp = 0
- material = /decl/material/solid/metal/steel
- handle_material = /decl/material/solid/organic/wood/oak
- excavation_amount = 1
- excavation_sound = "sweeping"
- excavation_verb = "brushing"
+ name = "wire brush"
+ icon_state = "pick_brush"
+ slot_flags = SLOT_EARS
+ _base_attack_force = 1
+ attack_verb = list("prodded", "attacked")
+ desc = "A wood-handled brush with thick metallic wires for clearing away dust and loose scree."
+ sharp = FALSE
+ material = /decl/material/solid/metal/steel
+ handle_material = /decl/material/solid/organic/wood/oak
+ excavation_amount = 1
+ excavation_sound = "sweeping"
+ excavation_verb = "brushing"
/obj/item/tool/xeno/one_pick
name = "2cm pick"
diff --git a/code/modules/tools/tool.dm b/code/modules/tools/tool.dm
index 889d2ab199d9..953a751ebbb2 100644
--- a/code/modules/tools/tool.dm
+++ b/code/modules/tools/tool.dm
@@ -6,7 +6,6 @@
w_class = ITEM_SIZE_NORMAL
origin_tech = @'{"materials":1,"engineering":1}'
attack_verb = list("hit", "pierced", "sliced", "attacked")
- sharp = 0
abstract_type = /obj/item/tool
material_alteration = MAT_FLAG_ALTERATION_COLOR | MAT_FLAG_ALTERATION_NAME | MAT_FLAG_ALTERATION_DESC
_base_attack_force = 10
diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm
index edfc8efaba4a..1098bd2bf01b 100644
--- a/code/modules/vehicles/vehicle.dm
+++ b/code/modules/vehicles/vehicle.dm
@@ -115,10 +115,10 @@
// physical damage types that can impart force; swinging a bat or energy sword
switch(weapon.atom_damage_type)
if(BURN)
- current_health -= weapon.get_attack_force(user) * fire_dam_coeff
+ current_health -= weapon.expend_attack_force(user) * fire_dam_coeff
. = TRUE
if(BRUTE)
- current_health -= weapon.get_attack_force(user) * brute_dam_coeff
+ current_health -= weapon.expend_attack_force(user) * brute_dam_coeff
. = TRUE
else
. = FALSE
@@ -144,23 +144,17 @@
healthcheck()
/obj/vehicle/emp_act(severity)
- var/was_on = on
+ addtimer(CALLBACK(src, PROC_REF(end_emp), on), severity * 30 SECONDS)
stat |= EMPED
- var/obj/effect/overlay/pulse2 = new /obj/effect/overlay(loc)
- pulse2.icon = 'icons/effects/effects.dmi'
- pulse2.icon_state = "empdisable"
- pulse2.SetName("emp sparks")
- pulse2.anchored = TRUE
- pulse2.set_dir(pick(global.cardinal))
-
- spawn(10)
- qdel(pulse2)
+ var/obj/effect/temp_visual/emp_burst/burst = new /obj/effect/temp_visual/emp_burst(loc)
+ burst.set_dir(pick(global.cardinal))
if(on)
turn_off()
- spawn(severity*300)
- stat &= ~EMPED
- if(was_on)
- turn_on()
+
+/obj/vehicle/proc/end_emp(was_on)
+ stat &= ~EMPED
+ if(was_on)
+ turn_on()
/obj/vehicle/attack_ai(mob/living/silicon/ai/user)
return
diff --git a/code/modules/xenoarcheaology/artifacts/triggers/force.dm b/code/modules/xenoarcheaology/artifacts/triggers/force.dm
index c8003f314e72..97a771745f11 100644
--- a/code/modules/xenoarcheaology/artifacts/triggers/force.dm
+++ b/code/modules/xenoarcheaology/artifacts/triggers/force.dm
@@ -7,7 +7,7 @@
var/obj/item/projectile/hit_projectile = hit_with
return (hit_projectile.atom_damage_type == BRUTE)
else if(istype(hit_with, /obj/item))
- return (hit_with.get_attack_force(user) >= 10)
+ return (hit_with.expend_attack_force(user) >= 10)
/datum/artifact_trigger/force/on_explosion(severity)
return TRUE
diff --git a/code/modules/xenoarcheaology/tools/core_sampler.dm b/code/modules/xenoarcheaology/tools/core_sampler.dm
index 01b4f1401e5d..21d5bd0cb6dd 100644
--- a/code/modules/xenoarcheaology/tools/core_sampler.dm
+++ b/code/modules/xenoarcheaology/tools/core_sampler.dm
@@ -51,7 +51,7 @@
icon_state = "sliver1"
randpixel = 8
w_class = ITEM_SIZE_TINY
- sharp = 1
+ sharp = TRUE
material = /decl/material/solid/stone/sandstone
material_health_multiplier = 0.25
diff --git a/code/unit_tests/_template.dm b/code/unit_tests/_template.dm
index 556941cb1ce5..36dc0ddfa189 100644
--- a/code/unit_tests/_template.dm
+++ b/code/unit_tests/_template.dm
@@ -7,8 +7,8 @@
/datum/unit_test/template
name = "Test Template - Change My name"
- template = /datum/unit_test/template // Set this var equal to the test path to treat it as a template, i.e. it should not be run
- async = 1 // Set if we should continue testing elsewhere and come back and check on the results.
+ abstract_type = /datum/unit_test/template // Set this var equal to the test path to treat it as a template, i.e. it should not be run
+ async = 1 // Set if we should continue testing elsewhere and come back and check on the results.
/datum/unit_test/template/start_test()
diff --git a/code/unit_tests/atmospherics_tests.dm b/code/unit_tests/atmospherics_tests.dm
index 5a9c69c15cf1..46837d818bf5 100644
--- a/code/unit_tests/atmospherics_tests.dm
+++ b/code/unit_tests/atmospherics_tests.dm
@@ -2,7 +2,7 @@
Unit tests for ATMOSPHERICS primitives
*/
/datum/unit_test/atmos_machinery
- template = /datum/unit_test/atmos_machinery
+ abstract_type = /datum/unit_test/atmos_machinery
var/list/test_cases = list()
/datum/unit_test/atmos_machinery/proc/create_gas_mixes(gas_mix_data)
@@ -60,7 +60,7 @@
pass("[case_name]: conserved moles of each gas ID.")
/datum/unit_test/atmos_machinery/conserve_moles
- template = /datum/unit_test/atmos_machinery/conserve_moles
+ abstract_type = /datum/unit_test/atmos_machinery/conserve_moles
test_cases = list(
uphill = list(
source = list(
diff --git a/code/unit_tests/chemistry_tests.dm b/code/unit_tests/chemistry_tests.dm
index bb6e9d904773..cdc9dae00d42 100644
--- a/code/unit_tests/chemistry_tests.dm
+++ b/code/unit_tests/chemistry_tests.dm
@@ -1,6 +1,6 @@
/datum/unit_test/chemistry
name = "CHEMISTRY: Reagent Template"
- template = /datum/unit_test/chemistry
+ abstract_type = /datum/unit_test/chemistry
var/container_volume = 45
var/donor_type = /obj/item
diff --git a/code/unit_tests/del_the_world.dm b/code/unit_tests/del_the_world.dm
index 93591ed1d01e..411ef21b8d33 100644
--- a/code/unit_tests/del_the_world.dm
+++ b/code/unit_tests/del_the_world.dm
@@ -39,58 +39,52 @@
continue
qdel(to_del, force = TRUE) // I hate borg stacks I hate borg stacks
AM = null // this counts as a reference to the last item if we don't explicitly clear it??
+ del_candidates.Cut() // this also??
// Check for hanging references.
SSticker.delay_end = TRUE // Don't end the round while we wait!
- // No harddels during this test.
- SSgarbage.collection_timeout[GC_QUEUE_HARDDELETE] = 6 HOURS // github CI timeout length
+ // Drastically lower the amount of time it takes to GC, since we don't have clients that can hold it up.
+ SSgarbage.collection_timeout[GC_QUEUE_CHECK] = 10 SECONDS
cached_contents.Cut()
+ var/list/queues_we_care_about = list()
+ // All of em, I want hard deletes too, since we rely on the debug info from them
+ for(var/i in 1 to GC_QUEUE_HARDDELETE)
+ queues_we_care_about += i
+
+ //Now that we've qdel'd everything, let's sleep until the gc has processed all the shit we care about
+ // + 2 seconds to ensure that everything gets in the queue.
+ var/time_needed = 2 SECONDS
+ for(var/index in queues_we_care_about)
+ time_needed += SSgarbage.collection_timeout[index]
+
// track start time so we know anything deleted after this point isn't ours
var/start_time = world.time
- // spin until the first item in the filter queue is older than start_time
- var/filter_queue_finished = FALSE
- var/list/filter_queue = SSgarbage.queues[GC_QUEUE_FILTER]
- while(!filter_queue_finished)
- if(!length(filter_queue))
- filter_queue_finished = TRUE
- break
- var/list/oldest_packet = filter_queue[1]
- //Pull out the time we inserted at
- var/qdel_time = oldest_packet[GC_QUEUE_ITEM_GCD_DESTROYED]
- if(qdel_time > start_time) // Everything is in the check queue now!
- filter_queue_finished = TRUE
- break
- if(world.time > start_time + 2 MINUTES)
- fail("Something has gone horribly wrong, the filter queue has been processing for well over 2 minutes. What the hell did you do??")
- break
- // We want to fire every time.
- SSgarbage.next_fire = 1
- sleep(2 SECONDS)
- // We need to check the check queue now.
- start_time = world.time
- // sleep until SSgarbage has run through the queue
- var/time_needed = SSgarbage.collection_timeout[GC_QUEUE_CHECK]
- sleep(time_needed)
- // taken verbatim from TG's Del The World
+ var/real_start_time = REALTIMEOFDAY
var/garbage_queue_processed = FALSE
- var/list/check_queue = SSgarbage.queues[GC_QUEUE_CHECK]
+
+ sleep(time_needed)
while(!garbage_queue_processed)
- //How the hell did you manage to empty this? Good job!
- if(!length(check_queue))
- garbage_queue_processed = TRUE
- break
+ var/oldest_packet_creation = INFINITY
+ for(var/index in queues_we_care_about)
+ var/list/queue_to_check = SSgarbage.queues[index]
+ if(!length(queue_to_check))
+ continue
+
+ var/list/oldest_packet = queue_to_check[1]
+ //Pull out the time we inserted at
+ var/qdeld_at = oldest_packet[GC_QUEUE_ITEM_GCD_DESTROYED]
+
+ oldest_packet_creation = min(qdeld_at, oldest_packet_creation)
- var/list/oldest_packet = check_queue[1]
- //Pull out the time we inserted at
- var/qdeld_at = oldest_packet[GC_QUEUE_ITEM_GCD_DESTROYED]
//If we've found a packet that got del'd later then we finished, then all our shit has been processed
- if(qdeld_at > start_time)
+ //That said, if there are any pending hard deletes you may NOT sleep, we gotta handle that shit
+ if(oldest_packet_creation > start_time && !length(SSgarbage.queues[GC_QUEUE_HARDDELETE]))
garbage_queue_processed = TRUE
break
- if(world.time > start_time + time_needed + 8 MINUTES)
- fail("The garbage queue has been processing for well over 10 minutes. Something is likely broken.")
+ if(REALTIMEOFDAY > real_start_time + time_needed + 30 MINUTES) //If this gets us gitbanned I'm going to laugh so hard
+ fail("Something has gone horribly wrong, the garbage queue has been processing for well over 30 minutes. What the hell did you do")
break
//Immediately fire the gc right after
diff --git a/code/unit_tests/equipment_tests.dm b/code/unit_tests/equipment_tests.dm
index 25146ab9251b..dac446856e8b 100644
--- a/code/unit_tests/equipment_tests.dm
+++ b/code/unit_tests/equipment_tests.dm
@@ -1,42 +1,37 @@
/datum/unit_test/vision_glasses
name = "EQUIPMENT: Vision Template"
- template = /datum/unit_test/vision_glasses
- var/mob/living/human/H = null
+ abstract_type = /datum/unit_test/vision_glasses
+ var/mob/living/human/subject = null
var/expectation = SEE_INVISIBLE_NOLIGHTING
var/glasses_type = null
async = 1
/datum/unit_test/vision_glasses/start_test()
- var/list/test = create_test_mob_with_mind(get_safe_turf(), /mob/living/human)
- if(isnull(test))
- fail("Check Runtimed in Mob creation")
-
- if(test["result"] == FAILURE)
- fail(test["msg"])
- async = 0
- return 0
-
- H = locate(test["mobref"])
- H.equip_to_slot(new glasses_type(H), slot_glasses_str)
+ subject = new(get_safe_turf(), SPECIES_HUMAN) // force human so default map species doesn't mess with anything
+ subject.equip_to_slot(new glasses_type(subject), slot_glasses_str)
return 1
/datum/unit_test/vision_glasses/check_result()
- if(isnull(H) || H.life_tick < 2)
+ if(isnull(subject) || subject.life_tick < 2)
return 0
- if(isnull(H.get_equipped_item(slot_glasses_str)))
+ if(isnull(subject.get_equipped_item(slot_glasses_str)))
fail("Mob doesn't have glasses on")
- H.handle_vision() // Because Life has a client check that bypasses updating vision
+ subject.handle_vision() // Because Life has a client check that bypasses updating vision
- if(H.see_invisible == expectation)
- pass("Mob See invisible is [H.see_invisible]")
+ if(subject.see_invisible == expectation)
+ pass("Mob See invisible is [subject.see_invisible]")
else
- fail("Mob See invisible is [H.see_invisible] / expected [expectation]")
+ fail("Mob See invisible is [subject.see_invisible] / expected [expectation]")
return 1
+/datum/unit_test/vision_glasses/teardown_test()
+ QDEL_NULL(subject)
+ . = ..()
+
/datum/unit_test/vision_glasses/NVG
name = "EQUIPMENT: NVG see_invis"
glasses_type = /obj/item/clothing/glasses/night
diff --git a/code/unit_tests/extension_tests.dm b/code/unit_tests/extension_tests.dm
index 49f9769fa431..2a7724e3cc7b 100644
--- a/code/unit_tests/extension_tests.dm
+++ b/code/unit_tests/extension_tests.dm
@@ -1,6 +1,6 @@
/datum/unit_test/extensions
name = "EXTENSIONS template"
- template = /datum/unit_test/extensions
+ abstract_type = /datum/unit_test/extensions
async = 0
/datum/unit_test/extensions/basic_extension_shall_lazy_initalize_as_expected
diff --git a/code/unit_tests/foundation_tests.dm b/code/unit_tests/foundation_tests.dm
index 66fb31643b33..27196ec37ff8 100644
--- a/code/unit_tests/foundation_tests.dm
+++ b/code/unit_tests/foundation_tests.dm
@@ -3,7 +3,7 @@
*/
/datum/unit_test/foundation
name = "FOUNDATION template"
- template = /datum/unit_test/foundation
+ abstract_type = /datum/unit_test/foundation
async = 0
/datum/unit_test/foundation/step_shall_return_true_on_success
diff --git a/code/unit_tests/graph_tests.dm b/code/unit_tests/graph_tests.dm
index 1d1cd69b6219..47cdb388f629 100644
--- a/code/unit_tests/graph_tests.dm
+++ b/code/unit_tests/graph_tests.dm
@@ -430,7 +430,7 @@
* Base Test Setup *
******************/
/datum/unit_test/graph_test
- template = /datum/unit_test/graph_test
+ abstract_type = /datum/unit_test/graph_test
async = TRUE
var/list/graphs
@@ -489,6 +489,7 @@
/atom/movable/graph_test/Destroy()
QDEL_NULL(node)
+ neighboursByDirection.Cut()
return ..()
/atom/movable/graph_test/forceMove()
@@ -524,7 +525,7 @@
var/on_split_was_called
var/issues
-/datum/graph/testing/New(var/node, var/edges, var/name)
+/datum/graph/testing/New(var/node, var/edges, var/previous_owner, var/name)
..()
src.name = name || "Graph"
issues = list()
@@ -558,8 +559,10 @@
/datum/graph/testing/proc/CheckExpectations()
if(on_check_expectations)
issues += DoCheckExpectations(on_check_expectations)
+ QDEL_NULL(on_check_expectations) // stop holding up GC!
if(length(split_expectations) && !on_split_was_called)
issues += "Had split expectations but OnSplit was not called"
+ QDEL_LIST(split_expectations) // stop holding up GC!
if(!length(split_expectations) && on_split_was_called)
issues += "Had no split expectations but OnSplit was called"
if(expecting_merge != on_merge_was_called)
@@ -576,6 +579,11 @@
src.expected_nodes = expected_nodes || list()
src.expected_edges = expected_edges || list()
+/datum/graph_expectation/Destroy(force)
+ expected_nodes.Cut()
+ expected_edges.Cut()
+ return ..()
+
// Stub for subtype-specific functionality for DoCheckExpectations.
// Should not access graph.nodes or graph.edges.
/datum/graph_expectation/proc/OnCheckExpectations(var/datum/graph/graph)
diff --git a/code/unit_tests/icon_tests.dm b/code/unit_tests/icon_tests.dm
index 58783a20f51c..279daba8a344 100644
--- a/code/unit_tests/icon_tests.dm
+++ b/code/unit_tests/icon_tests.dm
@@ -1,6 +1,6 @@
/datum/unit_test/icon_test
name = "ICON STATE template"
- template = /datum/unit_test/icon_test
+ abstract_type = /datum/unit_test/icon_test
/datum/unit_test/icon_test/food_shall_have_icon_states
name = "ICON STATE: Food And Drink Subtypes Shall Have Icon States"
diff --git a/code/unit_tests/integrated_circuits.dm b/code/unit_tests/integrated_circuits.dm
index 79c26d52a3a8..84de2ac2ff34 100644
--- a/code/unit_tests/integrated_circuits.dm
+++ b/code/unit_tests/integrated_circuits.dm
@@ -1,5 +1,5 @@
/datum/unit_test/integrated_circuits
- template = /datum/unit_test/integrated_circuits
+ abstract_type = /datum/unit_test/integrated_circuits
/datum/unit_test/integrated_circuits/unique_names
name = "INTEGRATED CIRCUITS: Circuits must have unique names"
@@ -64,7 +64,7 @@
/datum/unit_test/integrated_circuits/input_output
name = "INTEGRATED CIRCUITS: INPUT/OUTPUT - TEMPLATE"
- template = /datum/unit_test/integrated_circuits/input_output
+ abstract_type = /datum/unit_test/integrated_circuits/input_output
var/list/all_inputs = list()
var/list/all_expected_outputs = list()
var/activation_pin = 1
diff --git a/code/unit_tests/map_tests.dm b/code/unit_tests/map_tests.dm
index 2803ba8db097..89238fa88d21 100644
--- a/code/unit_tests/map_tests.dm
+++ b/code/unit_tests/map_tests.dm
@@ -503,6 +503,28 @@
//=======================================================================================
+// These vars are used to avoid in-world loops in the following unit test.
+var/global/_unit_test_disposal_segments = list()
+var/global/_unit_test_sort_junctions = list()
+
+#ifdef UNIT_TEST
+/obj/structure/disposalpipe/segment/Initialize(mapload)
+ . = ..()
+ _unit_test_disposal_segments += src
+
+/obj/structure/disposalpipe/segment/Destroy()
+ _unit_test_disposal_segments -= src
+ return ..()
+
+/obj/structure/disposalpipe/sortjunction/Initialize(mapload)
+ . = ..()
+ _unit_test_sort_junctions += src
+
+/obj/structure/disposalpipe/sortjunction/Destroy()
+ _unit_test_sort_junctions -= src
+ return ..()
+#endif
+
/datum/unit_test/disposal_segments_shall_connect_with_other_disposal_pipes
name = "MAP: Disposal segments shall connect with other disposal pipes"
@@ -522,7 +544,7 @@
num2text(SOUTH) = list(list(SOUTH, list(NORTH, WEST)), list(EAST, list(NORTH, EAST))),
num2text(WEST) = list(list(EAST, list(NORTH, EAST)), list(SOUTH, list(SOUTH, EAST))))
- for(var/obj/structure/disposalpipe/segment/D in world)
+ for(var/obj/structure/disposalpipe/segment/D in _unit_test_disposal_segments)
if(!D.loc)
continue
if(D.icon_state == "pipe-s")
@@ -760,7 +782,7 @@
/datum/unit_test/networked_disposals_shall_deliver_tagged_packages/start_test()
. = 1
var/fail = FALSE
- for(var/obj/structure/disposalpipe/sortjunction/sort in world)
+ for(var/obj/structure/disposalpipe/sortjunction/sort in _unit_test_sort_junctions)
if(!sort.loc)
continue
if(is_type_in_list(sort, exempt_junctions))
diff --git a/code/unit_tests/mob_tests.dm b/code/unit_tests/mob_tests.dm
index 0228ea803411..2f03eb9da320 100644
--- a/code/unit_tests/mob_tests.dm
+++ b/code/unit_tests/mob_tests.dm
@@ -58,21 +58,9 @@
// ============================================================================
-var/global/default_mobloc = null
-
-/proc/create_test_mob_with_mind(var/turf/mobloc = null, var/mobtype = /mob/living/human)
+/datum/unit_test/mob_damage/proc/create_test_mob_with_mind(var/turf/mobloc, var/mobtype = /mob/living/human)
var/list/test_result = list("result" = FAILURE, "msg" = "", "mobref" = null)
- if(isnull(mobloc))
- if(!default_mobloc)
- for(var/turf/floor/tiled/T in world)
- if(!T.zone?.air)
- continue
- var/pressure = T.zone.air.return_pressure()
- if(90 < pressure && pressure < 120) // Find a turf between 90 and 120
- default_mobloc = T
- break
- mobloc = default_mobloc
if(!mobloc)
test_result["msg"] = "Unable to find a location to create test mob"
return test_result
@@ -129,7 +117,7 @@ var/global/default_mobloc = null
/datum/unit_test/mob_damage
name = "MOB: Template for mob damage"
- template = /datum/unit_test/mob_damage
+ abstract_type = /datum/unit_test/mob_damage
var/damagetype = BRUTE
var/mob_type = /mob/living/human
var/expected_vulnerability = STANDARD
diff --git a/code/unit_tests/movement_tests.dm b/code/unit_tests/movement_tests.dm
index 8d45dbe20cfb..dbcb2bc44991 100644
--- a/code/unit_tests/movement_tests.dm
+++ b/code/unit_tests/movement_tests.dm
@@ -1,6 +1,6 @@
/datum/unit_test/movement
name = "MOVEMENT template"
- template = /datum/unit_test/movement
+ abstract_type = /datum/unit_test/movement
async = 0
/datum/unit_test/movement/force_move_shall_trigger_crossed_when_entering_turf
diff --git a/code/unit_tests/observation_tests.dm b/code/unit_tests/observation_tests.dm
index b9174d26fe87..829bc7435764 100644
--- a/code/unit_tests/observation_tests.dm
+++ b/code/unit_tests/observation_tests.dm
@@ -4,7 +4,7 @@
/datum/unit_test/observation
name = "OBSERVATION template"
- template = /datum/unit_test/observation
+ abstract_type = /datum/unit_test/observation
async = 0
var/list/received_moves
var/list/received_name_set_events
diff --git a/code/unit_tests/override_tests.dm b/code/unit_tests/override_tests.dm
index 2c8d6bc47cca..4687b0c72aaa 100644
--- a/code/unit_tests/override_tests.dm
+++ b/code/unit_tests/override_tests.dm
@@ -2,7 +2,7 @@
/datum/unit_test/override
name = "OVERRIDE template"
- template = /datum/unit_test/override
+ abstract_type = /datum/unit_test/override
/datum/unit_test/override/obj_random_shall_spawn_heaviest_item
name = "OVERRIDE: obj/random shall spawn heaviest item"
diff --git a/code/unit_tests/proximity_tests.dm b/code/unit_tests/proximity_tests.dm
index b77946ec7397..b405a2c3db25 100644
--- a/code/unit_tests/proximity_tests.dm
+++ b/code/unit_tests/proximity_tests.dm
@@ -2,7 +2,7 @@
* Template Setup *
*****************/
/datum/unit_test/proximity
- template = /datum/unit_test/proximity
+ abstract_type = /datum/unit_test/proximity
var/turf/wall/wall
var/obj/proximity_listener/proximity_listener
@@ -24,7 +24,7 @@
wall.set_opacity(opacity)
/datum/unit_test/proximity/visibility
- template = /datum/unit_test/proximity/visibility
+ abstract_type = /datum/unit_test/proximity/visibility
var/list/expected_number_of_turfs_by_trigger_type
/datum/unit_test/proximity/visibility/start_test()
diff --git a/code/unit_tests/time_tests.dm b/code/unit_tests/time_tests.dm
index 2dbf636d1e91..55a17518a603 100644
--- a/code/unit_tests/time_tests.dm
+++ b/code/unit_tests/time_tests.dm
@@ -1,6 +1,6 @@
/datum/unit_test/time
name = "TIME: Template"
- template = /datum/unit_test/time
+ abstract_type = /datum/unit_test/time
/datum/unit_test/time/shall_validate_sixth_of_june
name = "TIME: Shall validate 6th of June"
diff --git a/code/unit_tests/unit_test.dm b/code/unit_tests/unit_test.dm
index 4fe4fedfdc5c..24fd800c8544 100644
--- a/code/unit_tests/unit_test.dm
+++ b/code/unit_tests/unit_test.dm
@@ -4,7 +4,7 @@
* For the most part I think any test can be created that doesn't require a client in a mob or require a game mode other then extended
*
* The easiest way to make effective tests is to create a "template" if you intend to run the same test over and over and make your actual
- * tests be a "child object" of those templates. Be sure and name your templates with the word "template" somewhere in var/name.
+ * tests be a "child object" of those templates. Be sure to set abstract_type on your template type.
*
* The goal is to have all sorts of tests that run and to run them as quickly as possible.
*
@@ -51,8 +51,8 @@ var/global/ascii_reset = "[ascii_esc]\[0m"
// Templates aren't intended to be ran but just serve as a way to create child objects of it with inheritable tests for quick test creation.
/datum/unit_test
+ abstract_type = /datum/unit_test
var/name = "template - should not be ran."
- var/template // Treat the unit test as a template if its type is the same as the value of this var
var/disabled = 0 // If we want to keep a unit test in the codebase but not run it for some reason.
var/async = 0 // If the check can be left to do it's own thing, you must define a check_result() proc if you use this.
var/reported = 0 // If it's reported a success or failure. Any tests that have not are assumed to be failures.
@@ -157,11 +157,10 @@ var/global/ascii_reset = "[ascii_esc]\[0m"
/proc/get_test_datums()
. = list()
- for(var/test in subtypesof(/datum/unit_test))
- var/datum/unit_test/d = test
- if(test == initial(d.template))
+ for(var/datum/unit_test/test as anything in subtypesof(/datum/unit_test))
+ if(TYPE_IS_ABSTRACT(test))
continue
- . += d
+ . += test
/proc/do_unit_test(datum/unit_test/test, end_time, skip_disabled_tests = TRUE)
if(test.disabled && skip_disabled_tests)
diff --git a/code/unit_tests/virtual_mob_tests.dm b/code/unit_tests/virtual_mob_tests.dm
index dab89f395ec8..718bf0107483 100644
--- a/code/unit_tests/virtual_mob_tests.dm
+++ b/code/unit_tests/virtual_mob_tests.dm
@@ -1,10 +1,10 @@
/datum/unit_test/virtual
name = "VIRTUAL: Template"
- template = /datum/unit_test/virtual
+ abstract_type = /datum/unit_test/virtual
/datum/unit_test/virtual/helper
name = "VIRTUAL: Template Helper"
- template = /datum/unit_test/virtual/helper
+ abstract_type = /datum/unit_test/virtual/helper
var/helper_proc
var/list/expected_mobs
diff --git a/code/unit_tests/zas_tests.dm b/code/unit_tests/zas_tests.dm
index b83f880bff9e..7866c78bd62a 100644
--- a/code/unit_tests/zas_tests.dm
+++ b/code/unit_tests/zas_tests.dm
@@ -12,7 +12,7 @@
/datum/unit_test/zas_area_test
name = "ZAS: Area Test Template"
- template = /datum/unit_test/zas_area_test
+ abstract_type = /datum/unit_test/zas_area_test
var/area_path = null // Put the area you are testing here.
var/expectation = UT_NORMAL // See defines above.
diff --git a/code/world.dm b/code/world.dm
index 361fa6c4a150..057199cfb0a5 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -12,6 +12,9 @@
hub = "Exadv1.spacestation13"
icon_size = WORLD_ICON_SIZE
fps = 20
-#ifdef GC_FAILURE_HARD_LOOKUP
+#ifdef FIND_REF_NO_CHECK_TICK
+#pragma push
+#pragma ignore loop_checks
loop_checks = FALSE
+#pragma pop
#endif
diff --git a/html/changelog.html b/html/changelog.html
index 58aeb978adc1..23cae88f2087 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -52,6 +52,25 @@
-->
+ 22 January 2025
+ MistakeNot4892 updated:
+
+ - Swords on Shaded Hills can be sharpened using whetstones or grindstones.
+ - Guns can now be fired from rigs regardless of dexterity.
+
+
+ 21 January 2025
+ Penelope Haze updated:
+
+ - Mud can now receive footprints with any reagent other than mud. No more conspicuously missing bloody footprints!
+
+
+ 19 January 2025
+ MistakeNot4892 updated:
+
+ - Intents have been rewritten and moved, please report any issues with intent selection.
+
+
16 January 2025
MistakeNot4892 updated:
@@ -103,12 +122,6 @@ ophelia updated:
- You can now put any disk into the research design database or research design console, but only the correct disk type (tech disk or design disk) will function.
-
- 18 November 2024
- MistakeNot4892 updated:
-
- - Swapped barrel icons out for Doe's much nicer barrels.
-
|