[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 4cf930ac0f9..c9d3dad9751 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 8219540a8dc..52a9b747a84 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 faa52cb2323..35f3e0bbe61 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 1d6b432822c..b16d8919e29 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 2beef64083b..3dfa745cdec 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"
@@ -122,6 +129,14 @@
joint = "right ankle"
amputation_point = "right ankle"
+/obj/item/organ/external/foot/avian/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/stomp/weak)
+ return unarmed_attack
+
+/obj/item/organ/external/foot/right/avian/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/stomp/weak)
+ return unarmed_attack
+
/obj/item/organ/external/hand
organ_tag = BP_L_HAND
name = "left hand"
@@ -139,6 +154,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 +177,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 2c2746cd154..60219be1f1a 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 92bcc2d8ed7..36d6a3ac531 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -482,9 +482,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]
@@ -495,7 +497,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/organs/organ_prosthetics.dm b/code/modules/organs/organ_prosthetics.dm
index 03d8abee4ae..a107c79e810 100644
--- a/code/modules/organs/organ_prosthetics.dm
+++ b/code/modules/organs/organ_prosthetics.dm
@@ -9,7 +9,7 @@
// External organ procs:
// Does this bodypart count as a modular limb, and if so, what kind?
/obj/item/organ/external/proc/get_modular_limb_category()
- return isnull(bodytype.modular_limb_tier) ? MODULAR_BODYPART_INVALID : bodytype.modular_limb_tier
+ return isnull(bodytype?.modular_limb_tier) ? MODULAR_BODYPART_INVALID : bodytype.modular_limb_tier
// Checks if a limb could theoretically be removed.
// Note that this does not currently bother checking if a child or internal organ is vital.
diff --git a/code/modules/overmap/contacts/_contacts.dm b/code/modules/overmap/contacts/_contacts.dm
index e4cab812e76..bde9a41d171 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/disperser/disperser_charge.dm b/code/modules/overmap/disperser/disperser_charge.dm
index 895e2955dc0..4ab02455666 100644
--- a/code/modules/overmap/disperser/disperser_charge.dm
+++ b/code/modules/overmap/disperser/disperser_charge.dm
@@ -7,7 +7,7 @@
matter = list(
/decl/material/solid/metal/steel = MATTER_AMOUNT_REINFORCEMENT,
/decl/material/solid/metal/copper = MATTER_AMOUNT_SECONDARY,
- /decl/material/solid/supermatter = MATTER_AMOUNT_TRACE
+ /decl/material/solid/exotic_matter = MATTER_AMOUNT_TRACE
)
var/chargetype
var/chargedesc
diff --git a/code/modules/overmap/overmap_shuttle.dm b/code/modules/overmap/overmap_shuttle.dm
index 408db04970a..2a7e5b3fb64 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/overmap/ships/landable.dm b/code/modules/overmap/ships/landable.dm
index 20414a0cf0a..eaeabd18e3a 100644
--- a/code/modules/overmap/ships/landable.dm
+++ b/code/modules/overmap/ships/landable.dm
@@ -231,14 +231,14 @@
if(SHIP_STATUS_LANDED)
var/obj/effect/overmap/visitable/location = loc
if(istype(loc, /obj/effect/overmap/visitable/sector))
- return "Landed on \the [location.name]. Use secondary thrust to get clear before activating primary engines."
+ return "Landed on \the [location]. Use secondary thrust to get clear before activating primary engines."
if(istype(loc, /obj/effect/overmap/visitable/ship))
- return "Docked with \the [location.name]. Use secondary thrust to get clear before activating primary engines."
+ return "Docked with \the [location]. Use secondary thrust to get clear before activating primary engines."
return "Docked with an unknown object."
if(SHIP_STATUS_ENCOUNTER)
var/datum/shuttle/autodock/overmap/child_shuttle = SSshuttle.shuttles[shuttle]
var/obj/effect/overmap/visitable/location = global.overmap_sectors[num2text(child_shuttle.current_location.z)]
- return "Maneuvering nearby \the [location.name]."
+ return "Maneuvering nearby \the [location]."
if(SHIP_STATUS_TRANSIT)
return "Maneuvering under secondary thrust."
if(SHIP_STATUS_OVERMAP)
diff --git a/code/modules/overmap/ships/ship_physics.dm b/code/modules/overmap/ships/ship_physics.dm
index 66e85a3f0b9..28e71cf1f5b 100644
--- a/code/modules/overmap/ships/ship_physics.dm
+++ b/code/modules/overmap/ships/ship_physics.dm
@@ -36,31 +36,43 @@
/obj/effect/overmap/visitable/ship/proc/recalculate_vessel_mass()
var/list/zones = list()
+ // for(var/turf/tile in area) is an implied in-world loop
+ // an in-world loop per area is very bad, so instead
+ // we do one in-world loop and check area
+ var/list/areas = list()
+ // create an associative list of area -> TRUE so that lookup is faster
for(var/area/A in get_areas())
-
- // Do not include space please
- if(istype(A, world.area))
+ if(istype(A, world.area)) // exclude the base area
continue
+ areas[A] = TRUE
+ var/start_z = min(map_z)
+ var/end_z = max(map_z)
+ if(!start_z || !end_z)
+ return initial(vessel_mass) // This shouldn't happen ideally so just go with the initial vessel mass
+ for(var/z_level in start_z to end_z)
+ var/datum/level_data/z_data = SSmapping.levels_by_z[z_level]
+ for(var/turf/tile in block(z_data.level_inner_min_x, z_data.level_inner_min_y, z_level, z_data.level_inner_max_x, z_data.level_inner_max_y))
+ var/area/tile_area = tile.loc
+ if(!tile_area || !areas[tile_area])
+ continue
- for(var/turf/T in A)
-
- if(!T.simulated || T.is_open())
+ if(!tile.simulated || tile.is_open())
continue
. += DEFAULT_TURF_MASS
- if(istype(T, /turf/wall))
- var/turf/wall/W = T
- if(W.material)
- . += W.material.weight * 5
- if(W.reinf_material)
- . += W.reinf_material.weight * 5
- if(W.girder_material)
- . += W.girder_material.weight * 5
+ if(istype(tile, /turf/wall))
+ var/turf/wall/wall_tile = tile
+ if(wall_tile.material)
+ . += wall_tile.material.weight * 5
+ if(wall_tile.reinf_material)
+ . += wall_tile.reinf_material.weight * 5
+ if(wall_tile.girder_material)
+ . += wall_tile.girder_material.weight * 5
- if(T.zone)
- zones |= T.zone
+ if(tile.zone)
+ zones[tile.zone] = TRUE // assoc list for fast deduplication
- for(var/atom/movable/C in T)
+ for(var/atom/movable/C as anything in tile) // as anything is safe here since only movables can be in turf contents
if(!C.simulated)
continue
. += C.get_mass()
@@ -69,8 +81,9 @@
continue
. += C2.get_mass()
- for(var/zone/Z in zones)
- . += Z.air.get_mass()
+ // loop over keys of all zones in the list
+ for(var/zone/zone as anything in zones)
+ . += zone.air.get_mass()
// Convert kilograms to metric tonnes.
. = . / 1000
\ No newline at end of file
diff --git a/code/modules/paperwork/carbonpaper.dm b/code/modules/paperwork/carbonpaper.dm
index 72eb84cc491..5991f75c6c4 100644
--- a/code/modules/paperwork/carbonpaper.dm
+++ b/code/modules/paperwork/carbonpaper.dm
@@ -54,8 +54,9 @@
// Carbon Paper Alt Interactions
/////////////////////////////////////////////////
/decl/interaction_handler/carbon_paper_remove
- name = "remove carbon-copy"
+ name = "Remove Carbon-Copy"
expected_target_type = /obj/item/paper/carbon
+ examine_desc = "remove the carbon-copy"
/decl/interaction_handler/carbon_paper_remove/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/paper/carbon/paper = target
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index d25c1d6cbe5..cd40acd76d9 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -198,6 +198,7 @@
/decl/interaction_handler/clipboard_remove_pen
name = "Remove Pen"
expected_target_type = /obj/item/clipboard
+ examine_desc = "remove the pen"
/decl/interaction_handler/clipboard_remove_pen/is_possible(atom/target, mob/user, obj/item/prop)
. = ..()
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 92a37e75a1b..02428e20f70 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -636,6 +636,8 @@ var/global/datum/topic_state/default/paper_state/paper_topic_state = new
/decl/interaction_handler/scroll/furl
name = "Furl Scroll"
+ examine_desc = "furl $TARGET_THEM$"
/decl/interaction_handler/scroll/unfurl
name = "Unfurl Scroll"
+ examine_desc = "unfurl $TARGET_THEM$"
diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm
index bf75bc60846..16a2f1f7ab9 100644
--- a/code/modules/paperwork/paper_bundle.dm
+++ b/code/modules/paperwork/paper_bundle.dm
@@ -40,7 +40,7 @@
// merging bundles
else if(istype(W, /obj/item/paper_bundle) && merge(W, user, cur_page))
- to_chat(user, SPAN_NOTICE("You add \the [W.name] to \the [name]."))
+ to_chat(user, SPAN_NOTICE("You add \the [W] to \the [name]."))
return TRUE
// burning
@@ -517,6 +517,7 @@
/decl/interaction_handler/rename/paper_bundle
name = "Rename Bundle"
expected_target_type = /obj/item/paper_bundle
+ examine_desc = "rename $TARGET_THEM$"
/decl/interaction_handler/rename/paper_bundle/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/paper_bundle/bundle = target
diff --git a/code/modules/paperwork/paper_plane.dm b/code/modules/paperwork/paper_plane.dm
index ac8ebc5d961..2e183472066 100644
--- a/code/modules/paperwork/paper_plane.dm
+++ b/code/modules/paperwork/paper_plane.dm
@@ -77,6 +77,7 @@
/decl/interaction_handler/make_paper_plane
name = "Fold Into Paper Plane"
expected_target_type = /obj/item/paper
+ examine_desc = "make a paper plane"
/decl/interaction_handler/make_paper_plane/is_possible(obj/item/paper/target, mob/user, obj/item/prop)
return ..() && !target.is_crumpled
@@ -91,4 +92,4 @@
/obj/item/paper/get_alt_interactions(mob/user)
. = ..()
- LAZYDISTINCTADD(., /decl/interaction_handler/make_paper_plane)
\ No newline at end of file
+ LAZYADD(., /decl/interaction_handler/make_paper_plane)
\ No newline at end of file
diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm
index 70b9b4c453d..3622d047f5c 100644
--- a/code/modules/paperwork/paperbin.dm
+++ b/code/modules/paperwork/paperbin.dm
@@ -155,6 +155,7 @@
/decl/interaction_handler/paper_bin_dump_contents
name = "Dump Contents"
expected_target_type = /obj/item/paper_bin
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/paper_bin_dump_contents/is_possible(var/obj/item/paper_bin/target, mob/user, obj/item/prop)
return ..() && target.amount > 0
diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm
index 7905a718674..a5b56cf128f 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 ..()
@@ -193,6 +193,7 @@
/decl/interaction_handler/empty/paper_shredder
name = "Empty Bin"
expected_target_type = /obj/machinery/papershredder
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/empty/paper_shredder/is_possible(obj/machinery/papershredder/target, mob/user, obj/item/prop)
return ..() && !target.is_bin_empty()
diff --git a/code/modules/paperwork/pen/crayon.dm b/code/modules/paperwork/pen/crayon.dm
index 0c3222998ac..f06419b8711 100644
--- a/code/modules/paperwork/pen/crayon.dm
+++ b/code/modules/paperwork/pen/crayon.dm
@@ -33,24 +33,31 @@
return
if(istype(target) && target.is_floor())
- var/drawtype = input("Choose what you'd like to draw.", "Crayon scribbles") in list("graffiti","rune","letter","arrow")
+ var/static/list/drawtypes = list(CRAYON_DRAW_GRAFFITI, CRAYON_DRAW_RUNE, CRAYON_DRAW_LETTER, CRAYON_DRAW_ARROW)
+ var/drawtype = input(user, "Choose what you'd like to draw.", "Crayon scribbles") as null|anything in drawtypes
var/draw_message = "drawing"
switch(drawtype)
- if("letter")
- drawtype = input("Choose the letter.", "Crayon scribbles") in list(global.alphabet)
+ if(CRAYON_DRAW_LETTER)
+ drawtype = input(user, "Choose a letter.", "Crayon scribbles") as null|anything in global.alphabet
draw_message = "drawing a letter"
- if("graffiti")
+ if(CRAYON_DRAW_GRAFFITI)
draw_message = "drawing graffiti"
- if("rune")
+ if(CRAYON_DRAW_RUNE)
draw_message = "drawing a rune"
- if("arrow")
- drawtype = input("Choose the arrow.", "Crayon scribbles") in list("left", "right", "up", "down")
+ if(CRAYON_DRAW_ARROW)
+ var/static/list/arrow_dirs = list("left", "right", "up", "down")
+ drawtype = input(user, "Choose an arrow.", "Crayon scribbles") as null|anything in arrow_dirs
draw_message = "drawing an arrow"
+ if(!drawtype || QDELETED(src) || QDELETED(target) || QDELETED(user) || user.get_active_held_item() != src || !CanPhysicallyInteractWith(user, target))
+ return TRUE
+
if(do_tool_interaction(TOOL_PEN, user, target, 5 SECONDS, draw_message, "drawing on", fuel_expenditure = 1))
- new /obj/effect/decal/cleanable/crayon(target, stroke_color, shade_color, drawtype)
+ var/obj/effect/decal/cleanable/crayon/graffiti = new(target, stroke_color, shade_color, drawtype)
target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on.
- return
+ graffiti.add_fingerprint(user)
+
+ return TRUE
/obj/item/pen/crayon/red
stroke_color = "#da0000"
diff --git a/code/modules/paperwork/pen/fancy.dm b/code/modules/paperwork/pen/fancy.dm
index 9c7e149a7be..098033965e6 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 4944165f4e5..f643b9d1247 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 67dfcad441c..7334323851a 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/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 712c2d6c2b6..5d816b92448 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -268,6 +268,7 @@
/decl/interaction_handler/empty/photocopier_paper_bin
name = "Empty Paper Bin"
expected_target_type = /obj/machinery/photocopier
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/empty/photocopier_paper_bin/is_possible(obj/machinery/photocopier/target, mob/user, obj/item/prop)
return (target.printer?.get_amount_paper() > 0) && ..()
@@ -288,6 +289,7 @@
/decl/interaction_handler/remove/photocopier_scanner_item
name = "Remove Item From Scanner"
expected_target_type = /obj/machinery/photocopier
+ examine_desc = "remove a loaded item"
/decl/interaction_handler/remove/photocopier_scanner_item/is_possible(obj/machinery/photocopier/target, mob/user, obj/item/prop)
return target.scanner_item && ..()
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index 6e18e36decb..eb9bbb76a03 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -398,6 +398,7 @@
icon = 'icons/screen/radial.dmi'
icon_state = "radial_eject"
expected_target_type = /obj/item/camera
+ examine_desc = "eject the film"
/decl/interaction_handler/camera_eject_film/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/camera/camera = target
diff --git a/code/modules/paperwork/printer.dm b/code/modules/paperwork/printer.dm
index 7cfeaa96c43..0f91439ab58 100644
--- a/code/modules/paperwork/printer.dm
+++ b/code/modules/paperwork/printer.dm
@@ -423,6 +423,7 @@
/decl/interaction_handler/empty/stock_parts_printer
name = "Empty Paper Bin"
expected_target_type = /obj/item/stock_parts/printer
+ examine_desc = "empty $TARGET_THEM$"
/decl/interaction_handler/empty/stock_parts_printer/is_possible(obj/item/stock_parts/printer/target, mob/user, obj/item/prop)
return (target.get_amount_paper() > 0) && ..()
diff --git a/code/modules/persistence/graffiti.dm b/code/modules/persistence/graffiti.dm
index e9afbbad8d8..0bd85389b6f 100644
--- a/code/modules/persistence/graffiti.dm
+++ b/code/modules/persistence/graffiti.dm
@@ -14,10 +14,10 @@
var/author = "unknown"
/obj/effect/decal/writing/Initialize(mapload, var/_age, var/_message, var/_author)
- var/list/random_icon_states = icon_states(icon)
+ var/list/random_icon_states = get_states_in_icon(icon)
for(var/obj/effect/decal/writing/W in loc)
- random_icon_states.Remove(W.icon_state)
- if(random_icon_states.len)
+ random_icon_states -= W.icon_state
+ if(length(random_icon_states))
icon_state = pick(random_icon_states)
SSpersistence.track_value(src, /decl/persistence_handler/graffiti)
. = ..(mapload)
@@ -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/persistence/persistence_datum.dm b/code/modules/persistence/persistence_datum.dm
index 557ae252b88..027081f7949 100644
--- a/code/modules/persistence/persistence_datum.dm
+++ b/code/modules/persistence/persistence_datum.dm
@@ -26,14 +26,16 @@
return TRUE
/decl/persistence_handler/proc/CheckTokenSanity(var/list/tokens)
- return ( \
- islist(tokens) && \
- !isnull(tokens["x"]) && \
- !isnull(tokens["y"]) && \
- !isnull(tokens["z"]) && \
- !isnull(tokens["age"]) && \
- tokens["age"] <= entries_expire_at \
- )
+ if(!islist(tokens))
+ return FALSE
+ if(isnull(tokens["x"]) || isnull(tokens["y"]) || isnull(tokens["z"]))
+ return FALSE
+ if(!isnull(entries_expire_at))
+ if(isnull(tokens["age"]))
+ return FALSE
+ if(tokens["age"] > entries_expire_at)
+ return FALSE
+ return TRUE
/decl/persistence_handler/proc/CreateEntryInstance(var/turf/creating, var/list/tokens)
return
@@ -59,8 +61,9 @@
else
return
- if(GetValidTurf(locate(tokens["x"], tokens["y"], tokens["z"]), tokens))
- return CreateEntryInstance(., tokens)
+ . = GetValidTurf(locate(tokens["x"], tokens["y"], tokens["z"]), tokens)
+ if(.)
+ . = CreateEntryInstance(., tokens)
/decl/persistence_handler/proc/IsValidEntry(var/atom/entry)
if(!istype(entry))
diff --git a/code/modules/persistence/persistence_datum_book.dm b/code/modules/persistence/persistence_datum_book.dm
index 479a9c8cb45..cf33c5df07d 100644
--- a/code/modules/persistence/persistence_datum_book.dm
+++ b/code/modules/persistence/persistence_datum_book.dm
@@ -5,7 +5,14 @@
ignore_invalid_loc = TRUE
/decl/persistence_handler/book/CreateEntryInstance(var/turf/creating, var/list/tokens)
- var/obj/item/book/book = new(creating)
+
+ var/book_type = tokens["book_type"]
+ if(book_type)
+ book_type = text2path(book_type)
+ if(!ispath(book_type))
+ book_type = /obj/item/book
+
+ var/obj/item/book/book = new book_type(creating)
book.dat = tokens["message"]
book.title = tokens["title"]
book.author = tokens["writer"]
@@ -29,11 +36,12 @@
. = ..()
var/obj/item/book/book = entry
- .["author"] = book.last_modified_ckey || ""
- .["message"] = book.dat || "dat"
- .["title"] = book.title || "Untitled"
- .["writer"] = book.author || "unknown"
+ .["author"] = book.last_modified_ckey || ""
+ .["message"] = book.dat || "dat"
+ .["title"] = book.title || "Untitled"
+ .["writer"] = book.author || "unknown"
.["icon_state"] = book.icon_state || "book"
+ .["book_type"] = "[book.type]"
var/turf/T = get_turf(entry)
if(!T || !isStationLevel(T.z))
@@ -62,7 +70,7 @@
else
T = get_random_spawn_turf(SPAWN_FLAG_PERSISTENCE_CAN_SPAWN)
- . = ..(T, tokens)
+ . = ..()
/decl/persistence_handler/book/GetEntryAge(var/atom/entry)
. = -1
diff --git a/code/modules/supermatter/setup_supermatter.dm b/code/modules/power/admin_setup_engine.dm
similarity index 51%
rename from code/modules/supermatter/setup_supermatter.dm
rename to code/modules/power/admin_setup_engine.dm
index 1fb598744b2..d7d59c8f9e5 100644
--- a/code/modules/supermatter/setup_supermatter.dm
+++ b/code/modules/power/admin_setup_engine.dm
@@ -1,108 +1,7 @@
-#define SETUP_OK 1 // All good
-#define SETUP_WARNING 2 // Something that shouldn't happen happened, but it's not critical so we will continue
-#define SETUP_ERROR 3 // Something bad happened, and it's important so we won't continue setup.
-#define SETUP_DELAYED 4 // Wait for other things first.
-
-#define ENERGY_NITROGEN 115 // Roughly 8 emitter shots.
-#define ENERGY_CARBONDIOXIDE 150 // Roughly 10 emitter shots.
-#define ENERGY_HYDROGEN 300 // Roughly 20 emitter shots.
-#define ENERGY_PHORON 500 // Roughly 40 emitter shots.
-
-/datum/admins/proc/setup_supermatter()
- set category = "Debug"
- set name = "Setup Supermatter"
- set desc = "Allows you to start the Supermatter engine."
-
- if (!istype(src,/datum/admins))
- src = usr.client.holder
- if (!istype(src,/datum/admins))
- to_chat(usr, "Error: you are not an admin!")
- return
-
- var/response = input(usr, "Are you sure? This will start up the engine with selected gas as coolant.", "Engine setup") as null|anything in list("N2", "CO2", "PH", "H2", "Abort")
- if(!response || response == "Abort")
- return
-
- var/errors = 0
- var/warnings = 0
- var/success = 0
-
- log_and_message_admins("## SUPERMATTER SETUP - Setup initiated by [usr] using coolant type [response].")
-
- // CONFIGURATION PHASE
- // Coolant canisters, set types according to response.
- for(var/obj/effect/engine_setup/coolant_canister/C in global.engine_setup_markers)
- switch(response)
- if("N2")
- C.canister_type = /obj/machinery/portable_atmospherics/canister/nitrogen/engine_setup/
- continue
- if("CO2")
- C.canister_type = /obj/machinery/portable_atmospherics/canister/carbon_dioxide/engine_setup/
- continue
- if("PH")
- C.canister_type = /obj/machinery/portable_atmospherics/canister/phoron/engine_setup/
- continue
- if("H2")
- C.canister_type = /obj/machinery/portable_atmospherics/canister/hydrogen/engine_setup/
- continue
-
- for(var/obj/effect/engine_setup/core/C in global.engine_setup_markers)
- switch(response)
- if("N2")
- C.energy_setting = ENERGY_NITROGEN
- continue
- if("CO2")
- C.energy_setting = ENERGY_CARBONDIOXIDE
- continue
- if("PH")
- C.energy_setting = ENERGY_PHORON
- continue
- if("H2")
- C.energy_setting = ENERGY_HYDROGEN
- continue
-
- for(var/obj/effect/engine_setup/filter/F in global.engine_setup_markers)
- F.coolant = response
-
- var/list/delayed_objects = list()
- // SETUP PHASE
- for(var/obj/effect/engine_setup/S in global.engine_setup_markers)
- var/result = S.activate(0)
- switch(result)
- if(SETUP_OK)
- success++
- continue
- if(SETUP_WARNING)
- warnings++
- continue
- if(SETUP_ERROR)
- errors++
- log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.")
- break
- if(SETUP_DELAYED)
- delayed_objects.Add(S)
- continue
-
- if(!errors)
- for(var/obj/effect/engine_setup/S in delayed_objects)
- var/result = S.activate(1)
- switch(result)
- if(SETUP_OK)
- success++
- continue
- if(SETUP_WARNING)
- warnings++
- continue
- if(SETUP_ERROR)
- errors++
- log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.")
- break
-
- log_and_message_admins("## SUPERMATTER SETUP - Setup completed with [errors] errors, [warnings] warnings and [success] successful steps.")
-
- return
-
-
+#define ENGINE_SETUP_OK 1 // All good
+#define ENGINE_SETUP_WARNING 2 // Something that shouldn't happen happened, but it's not critical so we will continue
+#define ENGINE_SETUP_ERROR 3 // Something bad happened, and it's important so we won't continue setup.
+#define ENGINE_SETUP_DELAYED 4 // Wait for other things first.
var/global/list/engine_setup_markers = list()
@@ -129,7 +28,7 @@ var/global/list/engine_setup_markers = list()
// Tries to locate a pump, enables it, and sets it to MAX. Triggers warning if unable to locate a pump.
-/obj/effect/engine_setup/pump_max/
+/obj/effect/engine_setup/pump_max
name = "Pump Setup Marker"
/obj/effect/engine_setup/pump_max/activate()
@@ -137,15 +36,15 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/atmospherics/binary/pump/P = locate() in get_turf(src)
if(!P)
log_and_message_admins("## WARNING: Unable to locate pump at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
P.target_pressure = P.max_pressure_setting
P.update_use_power(POWER_USE_IDLE)
- return SETUP_OK
+ return ENGINE_SETUP_OK
// Spawns an empty canister on this turf, if it has a connector port. Triggers warning if unable to find a connector port
-/obj/effect/engine_setup/empty_canister/
+/obj/effect/engine_setup/empty_canister
name = "Empty Canister Marker"
/obj/effect/engine_setup/empty_canister/activate()
@@ -153,16 +52,16 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/atmospherics/portables_connector/P = locate() in get_turf(src)
if(!P)
log_and_message_admins("## WARNING: Unable to locate connector port at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
new/obj/machinery/portable_atmospherics/canister(get_turf(src)) // Canisters automatically connect to connectors in New()
- return SETUP_OK
+ return ENGINE_SETUP_OK
// Spawns a coolant canister on this turf, if it has a connector port.
// Triggers error when unable to locate connector port or when coolant canister type is unset.
-/obj/effect/engine_setup/coolant_canister/
+/obj/effect/engine_setup/coolant_canister
name = "Coolant Canister Marker"
var/canister_type = null
@@ -171,33 +70,12 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/atmospherics/portables_connector/P = locate() in get_turf(src)
if(!P)
log_and_message_admins("## ERROR: Unable to locate coolant connector port at [x] [y] [z]!")
- return SETUP_ERROR
+ return ENGINE_SETUP_ERROR
if(!canister_type)
log_and_message_admins("## ERROR: Canister type unset at [x] [y] [z]!")
- return SETUP_ERROR
+ return ENGINE_SETUP_ERROR
new canister_type(get_turf(src))
- return SETUP_OK
-
-
-
-// Energises the supermatter. Errors when unable to locate supermatter.
-/obj/effect/engine_setup/core/
- name = "Supermatter Core Marker"
- var/energy_setting = 0
-
-/obj/effect/engine_setup/core/activate(var/last = 0)
- if(!last)
- return SETUP_DELAYED
- ..()
- var/obj/machinery/power/supermatter/SM = locate() in get_turf(src)
- if(!SM)
- log_and_message_admins("## ERROR: Unable to locate supermatter core at [x] [y] [z]!")
- return SETUP_ERROR
- if(!energy_setting)
- log_and_message_admins("## ERROR: Energy setting unset at [x] [y] [z]!")
- return SETUP_ERROR
- SM.power = energy_setting
- return SETUP_OK
+ return ENGINE_SETUP_OK
@@ -218,13 +96,13 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/power/smes/S = locate() in get_turf(src)
if(!S)
log_and_message_admins("## WARNING: Unable to locate SMES unit at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
S.input_attempt = 1
S.input_level = min(target_input_level, S.input_level_max)
S.output_attempt = 1
S.output_level = min(target_output_level, S.output_level_max)
S.update_icon()
- return SETUP_OK
+ return ENGINE_SETUP_OK
// Sets up filters. This assumes filters are set to filter out CO2 back to the core loop by default!
/obj/effect/engine_setup/filter
@@ -236,10 +114,10 @@ var/global/list/engine_setup_markers = list()
var/obj/machinery/atmospherics/omni/filter/F = locate() in get_turf(src)
if(!F)
log_and_message_admins("## WARNING: Unable to locate omni filter at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
if(!coolant)
log_and_message_admins("## WARNING: No coolant type set at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
// Non-co2 coolant, adjust the filter's config first.
if(coolant != "CO2")
@@ -257,11 +135,11 @@ var/global/list/engine_setup_markers = list()
break
else
log_and_message_admins("## WARNING: Inapropriate filter coolant type set at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
F.rebuild_filtering_list()
F.update_use_power(POWER_USE_IDLE)
- return SETUP_OK
+ return ENGINE_SETUP_OK
// Closes the monitoring room shutters so the first Engi to show up doesn't get microwaved
/obj/effect/engine_setup/shutters
@@ -272,7 +150,7 @@ var/global/list/engine_setup_markers = list()
/obj/effect/engine_setup/shutters/activate()
if(!target_button)
log_and_message_admins("## WARNING: No button type set at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
var/obj/machinery/button/blast_door/found = null
var/turf/T = get_turf(src)
for(var/obj/machinery/button/blast_door/B in T.contents)
@@ -281,16 +159,7 @@ var/global/list/engine_setup_markers = list()
break
if(!found)
log_and_message_admins("## WARNING: Unable to locate button at [x] [y] [z]!")
- return SETUP_WARNING
+ return ENGINE_SETUP_WARNING
found.activate()
found.update_icon()
- return SETUP_OK
-
-#undef SETUP_OK
-#undef SETUP_WARNING
-#undef SETUP_ERROR
-#undef SETUP_DELAYED
-#undef ENERGY_NITROGEN
-#undef ENERGY_CARBONDIOXIDE
-#undef ENERGY_HYDROGEN
-#undef ENERGY_PHORON
\ No newline at end of file
+ return ENGINE_SETUP_OK
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 1f6254eea46..6e2b63b82fa 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 dd74a49e3d3..655e2766497 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -166,50 +166,48 @@ By design, d1 is the smallest direction and d2 is the highest
//
// TODO: take a closer look at cable attackby, make it call parent?
-/obj/structure/cable/attackby(obj/item/W, mob/user)
- if(IS_WIRECUTTER(W))
- cut_wire(W, user)
+/obj/structure/cable/attackby(obj/item/used_item, mob/user)
- else if(IS_COIL(W))
- var/obj/item/stack/cable_coil/coil = W
+ if(IS_WIRECUTTER(used_item))
+ cut_wire(used_item, user)
+ return TRUE
+
+ if(IS_COIL(used_item))
+ var/obj/item/stack/cable_coil/coil = used_item
if (coil.get_amount() < 1)
to_chat(user, "You don't have enough cable to lay down.")
return TRUE
coil.cable_join(src, user)
+ return TRUE
- else if(IS_MULTITOOL(W))
-
+ if(IS_MULTITOOL(used_item))
if(powernet && (powernet.avail > 0)) // is it powered?
to_chat(user, SPAN_WARNING("[get_wattage()] in power network."))
-
+ shock(user, 5, 0.2)
else
to_chat(user, SPAN_WARNING("\The [src] is not powered."))
+ return TRUE
- shock(user, 5, 0.2)
-
-
- else if(W.edge)
+ else if(used_item.has_edge())
var/delay_holder
-
- if(W.get_attack_force(user) < 5)
- visible_message(SPAN_WARNING("[user] starts sawing away roughly at \the [src] with \the [W]."))
+ if(used_item.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
- visible_message(SPAN_WARNING("[user] begins to cut through \the [src] with \the [W]."))
+ visible_message(SPAN_WARNING("[user] begins to cut through \the [src] with \the [used_item]."))
delay_holder = 3 SECONDS
-
if(user.do_skilled(delay_holder, SKILL_ELECTRICAL, src))
- cut_wire(W, user)
- if(W.obj_flags & OBJ_FLAG_CONDUCTIBLE)
+ cut_wire(used_item, user)
+ if(used_item.obj_flags & OBJ_FLAG_CONDUCTIBLE)
shock(user, 66, 0.7)
else
visible_message(SPAN_WARNING("[user] stops cutting before any damage is done."))
+ return TRUE
- src.add_fingerprint(user)
- return TRUE
+ return ..()
-/obj/structure/cable/proc/cut_wire(obj/item/W, mob/user)
+/obj/structure/cable/proc/cut_wire(obj/item/used_item, mob/user)
var/turf/T = get_turf(src)
if(!T || !T.is_plating())
return
@@ -241,13 +239,13 @@ By design, d1 is the smallest direction and d2 is the highest
// shock the user with probability prb
/obj/structure/cable/proc/shock(mob/user, prb, var/siemens_coeff = 1.0)
- if(!prob(prb))
- return 0
+ if(!prob(prb) || powernet?.avail <= 0)
+ return FALSE
if (electrocute_mob(user, powernet, src, siemens_coeff))
spark_at(src, amount=5, cardinal_only = TRUE)
if(HAS_STATUS(user, STAT_STUN))
- return 1
- return 0
+ return TRUE
+ return FALSE
// TODO: generalize to matter list and parts_type.
/obj/structure/cable/create_dismantled_products(turf/T)
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 48abeb8383a..a60fab7f939 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/fuel_assembly/fuel_assembly.dm b/code/modules/power/fuel_assembly/fuel_assembly.dm
index dbd9544418e..3721dff6b01 100644
--- a/code/modules/power/fuel_assembly/fuel_assembly.dm
+++ b/code/modules/power/fuel_assembly/fuel_assembly.dm
@@ -90,8 +90,8 @@
/obj/item/fuel_assembly/phoron
material = /decl/material/solid/phoron
-/obj/item/fuel_assembly/supermatter
- material = /decl/material/solid/supermatter
+/obj/item/fuel_assembly/exotic_matter
+ material = /decl/material/solid/exotic_matter
/obj/item/fuel_assembly/hydrogen
material = /decl/material/gas/hydrogen
diff --git a/code/modules/power/fuel_assembly/fuel_compressor.dm b/code/modules/power/fuel_assembly/fuel_compressor.dm
index 58b26a67dd9..0488d360f93 100644
--- a/code/modules/power/fuel_assembly/fuel_compressor.dm
+++ b/code/modules/power/fuel_assembly/fuel_compressor.dm
@@ -129,12 +129,6 @@
to_chat(user, SPAN_NOTICE("You add the contents of \the [thing] to \the [src]'s material buffer."))
return TRUE
- if(istype(thing, /obj/machinery/power/supermatter/shard))
- stored_material[/decl/material/solid/supermatter] = 5 * SHEET_MATERIAL_AMOUNT
- to_chat(user, SPAN_NOTICE("You awkwardly cram \the [thing] into \the [src]'s material buffer."))
- qdel(thing)
- return TRUE
-
if(istype(thing, /obj/item/stack/material))
var/obj/item/stack/material/M = thing
var/decl/material/mat = M.get_material()
diff --git a/code/modules/power/fusion/fusion_reactions.dm b/code/modules/power/fusion/fusion_reactions.dm
index 472ab5c37b5..14ac3c4e1cc 100644
--- a/code/modules/power/fusion/fusion_reactions.dm
+++ b/code/modules/power/fusion/fusion_reactions.dm
@@ -102,7 +102,7 @@
// VERY UNIDEAL REACTIONS.
/decl/fusion_reaction/phoron_supermatter
- p_react = /decl/material/solid/supermatter
+ p_react = /decl/material/solid/exotic_matter
s_react = /decl/material/solid/phoron
energy_consumption = 0
energy_production = 5 * FUSION_PROCESSING_TIME_MULT
@@ -121,8 +121,7 @@
qdel(holder)
var/radiation_level = rand(100, 200)
- // Copied from the SM for proof of concept. //Not any more --Cirra //Use the whole z proc --Leshana
- SSradiation.z_radiate(locate(1, 1, holder.z), radiation_level, 1)
+ SSradiation.z_radiate(origin, radiation_level, respect_maint = TRUE)
for(var/mob/living/human/H in global.living_mob_list_)
var/turf/T = get_turf(H)
@@ -130,10 +129,10 @@
H.set_hallucination(rand(100,150), 51)
for(var/obj/machinery/fusion_fuel_injector/I in range(world.view, origin))
- if(I.cur_assembly && I.cur_assembly.material && I.cur_assembly.material.type == /decl/material/solid/supermatter)
+ if(I.cur_assembly && I.cur_assembly.material && I.cur_assembly.material.type == /decl/material/solid/exotic_matter)
explosion(get_turf(I), 1, 2, 3)
if(!QDELETED(I))
- QDEL_IN(I, 5)
+ addtimer(CALLBACK(I, TYPE_PROC_REF(/atom, physically_destroyed)), 0.5 SECONDS)
sleep(5)
explosion(origin, 1, 2, 5)
diff --git a/code/modules/power/geothermal/_geothermal.dm b/code/modules/power/geothermal/_geothermal.dm
index 5f76fa6dd0f..3425a37cd2c 100644
--- a/code/modules/power/geothermal/_geothermal.dm
+++ b/code/modules/power/geothermal/_geothermal.dm
@@ -148,6 +148,7 @@ var/global/const/MAX_GEOTHERMAL_PRESSURE = 12000
/obj/machinery/geothermal/Destroy()
var/atom/last_loc = loc
unset_vent()
+ connector = null
. = ..()
if(istype(last_loc))
propagate_refresh_neighbors(last_loc)
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index e3b47f5c5d1..624425a5121 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 ca4b205e6b0..8afd72314ce 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 233b66d985f..c2b62b6059f 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/singularity/generator.dm b/code/modules/power/singularity/generator.dm
index fc1b54c7edc..00976a216f0 100644
--- a/code/modules/power/singularity/generator.dm
+++ b/code/modules/power/singularity/generator.dm
@@ -8,7 +8,7 @@
density = TRUE
use_power = POWER_USE_OFF
matter = list(
- /decl/material/solid/supermatter = MATTER_AMOUNT_PRIMARY,
+ /decl/material/solid/exotic_matter = MATTER_AMOUNT_PRIMARY,
/decl/material/solid/metal/steel = MATTER_AMOUNT_SECONDARY
)
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 8dae5c06871..d53d37aa144 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -13,7 +13,7 @@ var/global/list/singularities = list()
/// Category used for investigation entries relating to this atom.
var/const/investigation_label = "singulo"
- /// A list of events. Toxins is in here twice to double the chance of proccing.
+ /// A weighted list of events.
var/static/list/singularity_events = list(
/decl/singularity_event/empulse = 1,
/decl/singularity_event/toxins = 2,
@@ -63,7 +63,7 @@ var/global/list/singularities = list()
/obj/effect/singularity/explosion_act(severity)
SHOULD_CALL_PARENT(FALSE)
- if(current_stage.stage_size == STAGE_SUPER)//IT'S UNSTOPPABLE
+ if(!current_stage.explosion_vulnerable)//IT'S UNSTOPPABLE
return
if(severity == 1)
if(prob(25))
@@ -153,16 +153,13 @@ var/global/list/singularities = list()
// Handle random events.
if(prob(current_stage.event_chance))
- if(current_stage.stage_size >= STAGE_SUPER)
- var/decl/singularity_event/wave_event = GET_DECL(/decl/singularity_event/supermatter_wave)
- wave_event.handle_event(src)
- var/decl/singularity_event/singularity_event = pickweight(singularity_events)
+ var/decl/singularity_event/singularity_event = current_stage.forced_event || pickweight(singularity_events)
singularity_event = GET_DECL(singularity_event)
singularity_event.handle_event(src)
/obj/effect/singularity/proc/try_move(var/movement_dir, var/vertical_move)
set waitfor = FALSE
- if(current_stage.stage_size >= STAGE_FIVE)//The superlarge one does not care about things in its way
+ if(current_stage.ignore_obstacles)//The superlarge one does not care about things in its way
step(src, movement_dir)
if(!vertical_move)
sleep(1)
diff --git a/code/modules/power/singularity/singularity_events.dm b/code/modules/power/singularity/singularity_events.dm
index e48a040231b..f3bc342ac90 100644
--- a/code/modules/power/singularity/singularity_events.dm
+++ b/code/modules/power/singularity/singularity_events.dm
@@ -7,10 +7,7 @@
/decl/singularity_event/nothing // Nothing happens.
/decl/singularity_event/empulse/handle_event(obj/effect/singularity/source)
- if(source.current_stage.stage_size != STAGE_SUPER)
- empulse(source, 8, 10)
- else
- empulse(source, 12, 16)
+ empulse(source, source.current_stage.em_heavy_range, source.current_stage.em_light_range)
/decl/singularity_event/toxins
var/toxrange = 10
@@ -35,20 +32,10 @@
if(ishuman(M))
var/mob/living/human/H = M
if(istype(H.get_equipped_item(slot_glasses_str), /obj/item/clothing/glasses/meson))
- if(source.current_stage.stage_size != STAGE_SUPER)
+ if(!source.current_stage.the_goggles_do_nothing)
to_chat(H, SPAN_WARNING("You look directly into \the [source]. Good thing you had your protective eyewear on!"))
continue
to_chat(H, SPAN_WARNING("Your eyewear does absolutely nothing to protect you from \the [source]"))
- to_chat(M, SPAN_DANGER("You look directly into \the [source] and feel [source.current_stage.stage_size == STAGE_SUPER ? "helpless" : "weak"]."))
+ to_chat(M, SPAN_DANGER("You look directly into \the [source] and feel [source.current_stage.mesmerize_text]."))
M.apply_effect(3, STUN)
M.visible_message(SPAN_DANGER("\The [M] stares blankly at \the [source]!"))
-
-/decl/singularity_event/supermatter_wave/handle_event(obj/effect/singularity/source)
- for(var/mob/living/M in view(10, source.loc))
- to_chat(M, SPAN_WARNING("You hear an unearthly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat."))
- if(prob(67))
- to_chat(M, SPAN_NOTICE("Miraculously, it fails to kill you."))
- else
- to_chat(M, SPAN_DANGER("You don't even have a moment to react as you are reduced to ashes by the intense radiation."))
- M.dust()
- SSradiation.radiate(source, rand(source.energy))
diff --git a/code/modules/power/singularity/singularity_stages.dm b/code/modules/power/singularity/singularity_stages.dm
index 831cacd48c5..2624c10e818 100644
--- a/code/modules/power/singularity/singularity_stages.dm
+++ b/code/modules/power/singularity/singularity_stages.dm
@@ -32,8 +32,22 @@
var/dissipation_energy_loss = 1
/// What is the percent chance of an event each tick?
var/event_chance
+ /// Do we force a specific event when we proc events?
+ var/decl/singularity_event/forced_event = null
/// Will we wander around?
var/wander
+ /// Can explosions destroy the singularity?
+ var/explosion_vulnerable
+ /// What is the heavy range for the EM pulse event in this stage?
+ var/em_heavy_range = 8
+ /// What is the light range for the EM pulse event in this stage?
+ var/em_light_range = 10
+ /// What do characters feel when they're mesmerized during this stage?
+ var/mesmerize_text = "weak"
+ /// Do we ignore PPE for mesmerizing in this stage?
+ var/the_goggles_do_nothing = FALSE
+ /// Do we ignore obstacles in our way?
+ var/ignore_obstacles = FALSE
/decl/singularity_stage/validate()
. = ..()
@@ -171,29 +185,7 @@
dissipates_over_time = FALSE //It cant go smaller due to e loss.
wander = TRUE
event_chance = 20
+ ignore_obstacles = TRUE
/decl/singularity_stage/stage_five/grow_to(obj/effect/singularity/source)
source.visible_message(SPAN_DANGER("\The [source] has grown out of control!"))
-
-/decl/singularity_stage/stage_five/shrink_to(obj/effect/singularity/source)
- source.visible_message(SPAN_WARNING("\The [source] miraculously reduces in size and loses its supermatter properties."))
-
-/decl/singularity_stage/stage_super
- name = "super gravitational singularity"
- desc = "A gravitational singularity with the properties of supermatter. It has the power to destroy worlds."
- min_energy = 50000
- max_energy = INFINITY
- stage_size = STAGE_SUPER
- footprint = 6
- icon = 'icons/effects/352x352.dmi'
- icon_state = "singularity_s11"//uh, whoever drew that, you know that black holes are supposed to look dark right? What's this, the clown's singulo?
- pixel_x = -160
- pixel_y = -160
- grav_pull = 16
- consume_range = 5
- dissipates_over_time = 0 //It cant go smaller due to e loss
- event_chance = 25 //Events will fire off more often.
- wander = TRUE
-
-/decl/singularity_stage/stage_super/grow_to(obj/effect/singularity/source)
- source.visible_message(SPAN_SINISTER("You witness the creation of a destructive force that cannot possibly be stopped by human hands."))
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index bd129184831..a941debb006 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 f163d0f64c7..613ae77ae76 100644
--- a/code/modules/projectiles/ammunition.dm
+++ b/code/modules/projectiles/ammunition.dm
@@ -39,17 +39,20 @@
pixel_y = rand(-randpixel, randpixel)
. = ..()
+/obj/item/ammo_casing/Destroy()
+ QDEL_NULL(BB)
+ return ..()
+
//removes the projectile from the ammo casing
/obj/item/ammo_casing/proc/expend()
. = 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)
..()
@@ -119,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)
@@ -270,10 +278,9 @@ var/global/list/magazine_icondata_states = list()
/proc/magazine_icondata_cache_add(var/obj/item/ammo_magazine/M)
var/list/icon_keys = list()
var/list/ammo_states = list()
- var/list/states = icon_states(M.icon)
for(var/i = 0, i <= M.max_ammo, i++)
var/ammo_state = "[M.icon_state]-[i]"
- if(ammo_state in states)
+ if(check_state_in_icon(ammo_state, M.icon))
icon_keys += i
ammo_states += ammo_state
diff --git a/code/modules/projectiles/ammunition/chemdart.dm b/code/modules/projectiles/ammunition/chemdart.dm
index bd8710bef92..fa7647a4dcf 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 4de22aa0616..d99abdef1e6 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)
@@ -744,6 +751,9 @@
return FALSE
return TRUE
+/obj/item/gun/get_quick_interaction_handler(mob/user)
+ return GET_DECL(/decl/interaction_handler/gun/toggle_safety)
+
/obj/item/gun/get_alt_interactions(mob/user)
. = ..()
LAZYADD(., /decl/interaction_handler/gun/toggle_safety)
@@ -756,6 +766,7 @@
/decl/interaction_handler/gun/toggle_safety
name = "Toggle Safety"
+ examine_desc = "toggle the safety"
/decl/interaction_handler/gun/toggle_safety/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/gun = target
@@ -763,6 +774,7 @@
/decl/interaction_handler/gun/toggle_firemode
name = "Change Firemode"
+ examine_desc = "change the firemode"
/decl/interaction_handler/gun/toggle_firemode/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/gun = target
diff --git a/code/modules/projectiles/guns/launcher/bows/arrow.dm b/code/modules/projectiles/guns/launcher/bows/arrow.dm
index 1fb6cc35867..073c4d5928b 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 d44be24924d..69fa0078472 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 1466e138166..e34fd58e061 100644
--- a/code/modules/projectiles/guns/projectile.dm
+++ b/code/modules/projectiles/guns/projectile.dm
@@ -49,6 +49,12 @@
ammo_magazine = new magazine_type(src)
update_icon()
+/obj/item/gun/projectile/Destroy()
+ chambered = null
+ loaded.Cut()
+ ammo_magazine = null
+ return ..()
+
/obj/item/gun/projectile/consume_next_projectile()
if(!is_jammed && prob(jam_chance))
src.visible_message("\The [src] jams!")
@@ -74,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
@@ -334,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")
@@ -354,6 +360,7 @@
/decl/interaction_handler/projectile/remove_silencer
name = "Remove Silencer"
+ examine_desc = "remove the silencer"
/decl/interaction_handler/projectile/remove_silencer/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/projectile/gun = target
@@ -361,6 +368,7 @@
/decl/interaction_handler/projectile/unload_ammo
name = "Remove Ammunition"
+ examine_desc = "unload the ammunition"
/decl/interaction_handler/projectile/unload_ammo/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/projectile/gun = target
diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm
index 7505d0152aa..802b1f93863 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 6c00e6c2594..ee2edcdcfae 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 638376989ee..e64e7c3f731 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/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm
index 0f54520856d..464ce437f7c 100644
--- a/code/modules/projectiles/guns/projectile/revolver.dm
+++ b/code/modules/projectiles/guns/projectile/revolver.dm
@@ -74,6 +74,7 @@
/decl/interaction_handler/revolver_spin_cylinder
name = "Spin Cylinder"
expected_target_type = /obj/item/gun/projectile/revolver
+ examine_desc = "spin the cylinder"
/decl/interaction_handler/revolver_spin_cylinder/invoked(atom/target, mob/user, obj/item/prop)
var/obj/item/gun/projectile/revolver/R = target
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 07ad3c6c686..152cb7a6ab5 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -14,6 +14,18 @@
is_spawnable_type = FALSE
atom_damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, ELECTROCUTE are the only things that should be in here, Try not to use PAIN as it doesn't go through stun_effect_act
+ // Code for handling tails, if any.
+ /// If the projectile leaves a trail.
+ var/proj_trail = FALSE
+ /// How long the trail lasts.
+ var/proj_trail_lifespan = 0
+ /// What icon to use for the projectile trail.
+ var/proj_trail_icon = 'icons/effects/projectiles/trail.dmi'
+ /// What icon_state to use for the projectile trail.
+ var/proj_trail_icon_state = "trail"
+ /// Any extant trail effects.
+ var/list/proj_trails
+
var/bumped = 0 //Prevents it from hitting more than one guy at once
var/def_zone = "" //Aiming at
var/atom/movable/firer = null//Who shot it
@@ -316,7 +328,15 @@
return
/obj/item/projectile/proc/before_move()
- return
+ if(!proj_trail || !isturf(loc) || !proj_trail_icon || !proj_trail_icon_state || !proj_trail_lifespan)
+ return
+ var/obj/effect/overlay/projectile_trail/trail = new(loc)
+ trail.master = src
+ trail.icon = proj_trail_icon
+ trail.icon_state = proj_trail_icon_state
+ trail.set_density(FALSE)
+ LAZYADD(proj_trails, trail)
+ QDEL_IN(trail, proj_trail_lifespan)
/obj/item/projectile/proc/after_move()
if(hitscan && tracer_type && !(locate(/obj/effect/projectile) in loc))
@@ -609,6 +629,7 @@
trajectory.initialize_location(target.x, target.y, target.z, 0, 0)
/obj/item/projectile/Destroy()
+ QDEL_NULL_LIST(proj_trails)
if(hitscan)
if(loc && trajectory)
var/datum/point/pcache = trajectory.copy_to()
@@ -650,4 +671,4 @@
QDEL_NULL(beam_index)
/obj/item/projectile/proc/update_effect(var/obj/effect/projectile/effect)
- return
\ No newline at end of file
+ return
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index dc643dcdc3b..8df181e9195 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/projectile/change.dm b/code/modules/projectiles/projectile/change.dm
index 8e241456d22..ff77df0fa33 100644
--- a/code/modules/projectiles/projectile/change.dm
+++ b/code/modules/projectiles/projectile/change.dm
@@ -55,12 +55,9 @@
var/mob/living/new_mob = apply_transformation(M, choice)
if(new_mob)
new_mob.set_intent(I_FLAG_HARM)
- if(M.mind)
- for (var/spell/S in M.mind.learned_spells)
- new_mob.add_spell(new S.type)
- new_mob.set_intent(I_FLAG_HARM)
- transfer_key_from_mob_to_mob(M, new_mob)
- to_chat(new_mob, "Your form morphs into that of \a [choice].")
+ new_mob.copy_abilities_from(M)
+ transfer_key_from_mob_to_mob(M, new_mob)
+ to_chat(new_mob, "Your form morphs into that of \a [choice].")
else
new_mob = M
if(new_mob)
@@ -68,4 +65,3 @@
if(new_mob != M && !QDELETED(M))
qdel(M)
-
diff --git a/code/modules/projectiles/secure.dm b/code/modules/projectiles/secure.dm
index 241a0e0a8af..6902b3bddb1 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/projectiles/targeting/targeting_overlay.dm b/code/modules/projectiles/targeting/targeting_overlay.dm
index 5d5b1f9ba65..7210efedb4c 100644
--- a/code/modules/projectiles/targeting/targeting_overlay.dm
+++ b/code/modules/projectiles/targeting/targeting_overlay.dm
@@ -34,27 +34,24 @@
// Update HUD icons.
if(owner.gun_move_icon)
if(!(target_permissions & TARGET_CAN_MOVE))
- owner.gun_move_icon.icon_state = "no_walk0"
owner.gun_move_icon.SetName("Allow Movement")
else
- owner.gun_move_icon.icon_state = "no_walk1"
owner.gun_move_icon.SetName("Disallow Movement")
+ owner.gun_move_icon.update_icon()
if(owner.item_use_icon)
if(!(target_permissions & TARGET_CAN_CLICK))
- owner.item_use_icon.icon_state = "no_item0"
owner.item_use_icon.SetName("Allow Item Use")
else
- owner.item_use_icon.icon_state = "no_item1"
owner.item_use_icon.SetName("Disallow Item Use")
+ owner.item_use_icon.update_icon()
if(owner.radio_use_icon)
if(!(target_permissions & TARGET_CAN_RADIO))
- owner.radio_use_icon.icon_state = "no_radio0"
owner.radio_use_icon.SetName("Allow Radio Use")
else
- owner.radio_use_icon.icon_state = "no_radio1"
owner.radio_use_icon.SetName("Disallow Radio Use")
+ owner.radio_use_icon.update_icon()
var/message = "no longer permitted to "
var/use_span = "warning"
@@ -206,7 +203,7 @@
if(!no_message)
to_chat(owner, "You will no longer aim rather than fire.")
owner.client.remove_gun_icons()
- owner.gun_setting_icon.icon_state = "gun[active]"
+ owner.gun_setting_icon.update_icon()
/obj/aiming_overlay/proc/cancel_aiming(var/no_message = 0)
if(!aiming_with || !aiming_at)
diff --git a/code/modules/prometheus_metrics/metric_family.dm b/code/modules/prometheus_metrics/metric_family.dm
index 373130e297a..0054e97a257 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 95e2f819002..ad98b6c178f 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 232bce38faf..3aa58ba942d 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 5c6d315b04d..f686f1d1bed 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 d12f5a79204..91044cd99d5 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/drop_types.dm b/code/modules/random_map/drop/drop_types.dm
index a9f290a0aa6..1560263f996 100644
--- a/code/modules/random_map/drop/drop_types.dm
+++ b/code/modules/random_map/drop/drop_types.dm
@@ -22,12 +22,6 @@ var/global/list/datum/supply_drop_loot/supply_drop
/datum/supply_drop_loot/dd_SortValue()
return name
-/datum/supply_drop_loot/supermatter
- name = "Supermatter"
-/datum/supply_drop_loot/supermatter/New()
- ..()
- contents = list(/obj/machinery/power/supermatter)
-
/datum/supply_drop_loot/lasers
name = "Lasers"
container = /obj/structure/largecrate
diff --git a/code/modules/random_map/drop/droppod.dm b/code/modules/random_map/drop/droppod.dm
index ac23a7b14e8..926ed6b2d0b 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 length(map))
return 0
var/turf/T = locate((origin_x-1)+x,(origin_y-1)+y,origin_z)
if(!T || (target_turf_type && !istype(T,target_turf_type)))
diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm
index 28b4f593c18..9b76b5dec22 100644
--- a/code/modules/reagents/Chemistry-Holder.dm
+++ b/code/modules/reagents/Chemistry-Holder.dm
@@ -1,8 +1,8 @@
var/global/obj/temp_reagents_holder = new
var/global/datum/reagents/sink/infinite_reagent_sink = new
-/atom/proc/add_to_reagents(reagent_type, amount, data, safety = FALSE, defer_update = FALSE)
- return reagents?.add_reagent(reagent_type, amount, data, safety, defer_update)
+/atom/proc/add_to_reagents(reagent_type, amount, data, safety = FALSE, defer_update = FALSE, phase = null)
+ return reagents?.add_reagent(reagent_type, amount, data, safety, defer_update, phase)
/atom/proc/remove_from_reagents(reagent_type, amount, safety = FALSE, defer_update = FALSE)
return reagents?.remove_reagent(reagent_type, amount, safety, defer_update)
@@ -549,11 +549,11 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new
/datum/reagents/proc/trans_to_holder(var/datum/reagents/target, var/amount = 1, var/multiplier = 1, var/copy = 0, var/safety = 0, var/defer_update = FALSE, var/list/skip_reagents, var/transferred_phases = (MAT_PHASE_LIQUID | MAT_PHASE_SOLID))
if(!target || !istype(target))
- return
+ return 0
amount = max(0, min(amount, total_volume, REAGENTS_FREE_SPACE(target) / multiplier))
if(!amount)
- return
+ return 0
var/part = amount
if(skip_reagents)
@@ -561,7 +561,7 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new
for(var/rtype in skip_reagents)
using_volume -= LAZYACCESS(reagent_volumes, rtype)
if(using_volume <= 0)
- return
+ return 0
part /= using_volume
else
var/using_volume = total_volume
@@ -797,37 +797,55 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new
// Options are touch_turf(), touch_mob() and touch_obj(). This does not handle transferring reagents to things.
// For example, splashing someone with water will get them wet and extinguish them if they are on fire,
// even if they are wearing an impermeable suit that prevents the reagents from contacting the skin.
-/datum/reagents/proc/touch_mob(var/mob/target)
+
+/datum/reagents/proc/touch_atom(atom/target, touch_atoms = TRUE)
+ if(ismob(target))
+ return touch_mob(target)
+ if(isobj(target))
+ return touch_obj(target)
+ if(isturf(target))
+ return touch_turf(target, touch_atoms)
+ return FALSE
+
+/datum/reagents/proc/touch_mob(mob/target)
if(!target || !istype(target) || !target.simulated)
return
for(var/rtype in reagent_volumes)
var/decl/material/current = GET_DECL(rtype)
current.touch_mob(target, REAGENT_VOLUME(src, rtype), src)
-/datum/reagents/proc/touch_turf(var/turf/target)
- if(!istype(target) || !target.simulated)
+/datum/reagents/proc/touch_turf(turf/touching_turf, touch_atoms = TRUE)
+
+ if(!istype(touching_turf) || !touching_turf.simulated)
return
+
for(var/rtype in reagent_volumes)
var/decl/material/current = GET_DECL(rtype)
- current.touch_turf(target, REAGENT_VOLUME(src, rtype), src)
+ current.touch_turf(touching_turf, REAGENT_VOLUME(src, rtype), src)
+
var/dirtiness = get_dirtiness()
if(dirtiness <= DIRTINESS_CLEAN)
- target.clean()
- target.remove_cleanables()
- if(dirtiness != DIRTINESS_NEUTRAL)
- if(dirtiness > DIRTINESS_NEUTRAL)
- target.add_dirt(ceil(total_volume * dirtiness))
- else
- if(dirtiness <= DIRTINESS_STERILE)
- target.germ_level -= min(total_volume*20, target.germ_level)
- for(var/obj/item/I in target.contents)
- I.was_bloodied = null
- for(var/obj/effect/decal/cleanable/blood/B in target)
- qdel(B)
- if(dirtiness <= DIRTINESS_CLEAN)
- target.clean()
-
-/datum/reagents/proc/touch_obj(var/obj/target)
+ touching_turf.clean()
+ touching_turf.remove_cleanables()
+
+ if(dirtiness > DIRTINESS_NEUTRAL)
+ touching_turf.add_dirt(ceil(total_volume * dirtiness))
+ else if(dirtiness < DIRTINESS_NEUTRAL)
+ if(dirtiness <= DIRTINESS_STERILE)
+ touching_turf.germ_level -= min(total_volume*20, touching_turf.germ_level)
+ for(var/obj/item/I in touching_turf.contents)
+ I.was_bloodied = null
+ for(var/obj/effect/decal/cleanable/blood/B in touching_turf)
+ qdel(B)
+ if(dirtiness <= DIRTINESS_CLEAN)
+ touching_turf.clean()
+
+ if(touch_atoms)
+ for(var/atom/movable/thing in touching_turf.get_contained_external_atoms())
+ if(thing.simulated && !istype(thing, /obj/effect/effect/smoke/chem))
+ touch_atom(thing)
+
+/datum/reagents/proc/touch_obj(obj/target)
if(!target || !istype(target) || !target.simulated)
return
for(var/rtype in reagent_volumes)
@@ -872,13 +890,13 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new
/datum/reagents/proc/trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0, var/defer_update = FALSE, var/transferred_phases = (MAT_PHASE_LIQUID | MAT_PHASE_SOLID))
if(!target?.simulated)
- return
+ return 0
// If we're only dumping solids, and there's not enough liquid present on the turf to make a slurry, we dump the solids directly.
// This avoids creating an unnecessary reagent holder that won't be immediately deleted.
if((!(transferred_phases & MAT_PHASE_LIQUID) || !total_liquid_volume) && (target.reagents?.total_liquid_volume < FLUID_SLURRY))
var/datum/reagents/R = new /datum/reagents(amount, global.temp_reagents_holder)
- trans_to_holder(R, amount, multiplier, copy, TRUE, defer_update = defer_update, transferred_phases = MAT_PHASE_SOLID)
+ . = trans_to_holder(R, amount, multiplier, copy, TRUE, defer_update = defer_update, transferred_phases = MAT_PHASE_SOLID)
R.touch_turf(target)
target.dump_solid_reagents(R)
qdel(R)
@@ -887,16 +905,16 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new
if(!target.reagents)
target.create_reagents(FLUID_MAX_DEPTH)
- trans_to_holder(target.reagents, amount, multiplier, copy, defer_update = defer_update, transferred_phases = transferred_phases)
+ . = trans_to_holder(target.reagents, amount, multiplier, copy, defer_update = defer_update, transferred_phases = transferred_phases)
// Deferred updates are presumably being done by SSfluids.
// Do an immediate fluid_act call rather than waiting for SSfluids to proc.
- if(!defer_update)
+ if(!defer_update && target.reagents.total_volume >= FLUID_PUDDLE)
target.fluid_act(target.reagents)
// Objects may or may not have reagents; if they do, it's probably a beaker or something and we need to transfer properly; otherwise, just touch.
/datum/reagents/proc/trans_to_obj(var/obj/target, var/amount = 1, var/multiplier = 1, var/copy = 0, var/defer_update = FALSE, var/transferred_phases = (MAT_PHASE_LIQUID | MAT_PHASE_SOLID))
if(!target || !target.simulated)
- return
+ return 0
if(!target.reagents)
var/datum/reagents/R = new /datum/reagents(amount * multiplier, global.temp_reagents_holder)
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index 0216e31ad13..e304fbec91e 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -223,7 +223,7 @@
. += "
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/Chemistry-Metabolism.dm b/code/modules/reagents/Chemistry-Metabolism.dm
index e1002809b1f..9c78f190ca2 100644
--- a/code/modules/reagents/Chemistry-Metabolism.dm
+++ b/code/modules/reagents/Chemistry-Metabolism.dm
@@ -20,7 +20,7 @@
parent = null
return ..()
-/datum/reagents/metabolism/proc/metabolize(var/list/dosage_tracker)
+/datum/reagents/metabolism/proc/metabolize(list/dosage_tracker)
if(!parent || total_volume < MINIMUM_CHEMICAL_VOLUME || !length(reagent_volumes))
return
for(var/rtype in reagent_volumes)
diff --git a/code/modules/reagents/chems/chems_alcohol.dm b/code/modules/reagents/chems/chems_alcohol.dm
index aa7ca92f847..44384d64365 100644
--- a/code/modules/reagents/chems/chems_alcohol.dm
+++ b/code/modules/reagents/chems/chems_alcohol.dm
@@ -226,8 +226,8 @@
if(M.bodytemperature > 310)
M.bodytemperature = max(310, M.bodytemperature - (5 * TEMPERATURE_DAMAGE_COEFFICIENT))
-/decl/material/liquid/alcohol/coffee/affect_overdose(mob/living/M, total_dose)
- ADJ_STATUS(M, STAT_JITTER, 5)
+/decl/material/liquid/alcohol/coffee/affect_overdose(mob/living/victim, total_dose)
+ ADJ_STATUS(victim, STAT_JITTER, 5)
/decl/material/liquid/alcohol/melonliquor
name = "melon liqueur"
diff --git a/code/modules/reagents/chems/chems_blood.dm b/code/modules/reagents/chems/chems_blood.dm
index e3a08e5b873..ab5f8e6dd8e 100644
--- a/code/modules/reagents/chems/chems_blood.dm
+++ b/code/modules/reagents/chems/chems_blood.dm
@@ -46,12 +46,12 @@
for(var/chem in other_chems)
my_chems[chem] = my_chems[chem] + other_chems[chem]
-/decl/material/liquid/blood/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
+/decl/material/liquid/blood/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
var/data = REAGENT_DATA(holder, type)
- if(!istype(T) || REAGENT_VOLUME(holder, type) < 3)
+ if(!istype(touching_turf) || REAGENT_VOLUME(holder, type) < 3)
return
- var/weakref/W = LAZYACCESS(data, DATA_BLOOD_DONOR)
- blood_splatter(T, W?.resolve() || holder.my_atom, 1)
+ var/weakref/donor = LAZYACCESS(data, DATA_BLOOD_DONOR)
+ blood_splatter(touching_turf, donor?.resolve() || holder.my_atom, 1)
/decl/material/liquid/blood/affect_ingest(var/mob/living/M, var/removed, var/datum/reagents/holder)
. = ..()
@@ -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/chems/chems_compounds.dm b/code/modules/reagents/chems/chems_compounds.dm
index 829ba1df5b2..1558ef76762 100644
--- a/code/modules/reagents/chems/chems_compounds.dm
+++ b/code/modules/reagents/chems/chems_compounds.dm
@@ -35,11 +35,11 @@
addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living/human, update_eyes)), 5 SECONDS)
. = ..()
-/decl/material/liquid/glowsap/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/glowsap/affect_overdose(mob/living/victim, total_dose)
. = ..()
- M.add_chemical_effect(CE_TOXIN, 1)
- M.set_hallucination(60, 20)
- SET_STATUS_MAX(M, STAT_DRUGGY, 10)
+ victim.add_chemical_effect(CE_TOXIN, 1)
+ victim.set_hallucination(60, 20)
+ SET_STATUS_MAX(victim, STAT_DRUGGY, 10)
/decl/material/solid/blackpepper
name = "black pepper"
diff --git a/code/modules/reagents/chems/chems_drinks.dm b/code/modules/reagents/chems/chems_drinks.dm
index af54d84cd62..eca5276b785 100644
--- a/code/modules/reagents/chems/chems_drinks.dm
+++ b/code/modules/reagents/chems/chems_drinks.dm
@@ -379,9 +379,9 @@
..()
M.add_chemical_effect(CE_PULSE, 2)
-/decl/material/liquid/drink/coffee/affect_overdose(mob/living/M, total_dose)
- ADJ_STATUS(M, STAT_JITTER, 5)
- M.add_chemical_effect(CE_PULSE, 1)
+/decl/material/liquid/drink/coffee/affect_overdose(mob/living/victim, total_dose)
+ ADJ_STATUS(victim, STAT_JITTER, 5)
+ victim.add_chemical_effect(CE_PULSE, 1)
/decl/material/liquid/drink/coffee/build_presentation_name_from_reagents(var/obj/item/prop, var/supplied)
diff --git a/code/modules/reagents/chems/chems_drugs.dm b/code/modules/reagents/chems/chems_drugs.dm
index 9d36a9a5ae3..e9345200297 100644
--- a/code/modules/reagents/chems/chems_drugs.dm
+++ b/code/modules/reagents/chems/chems_drugs.dm
@@ -61,9 +61,9 @@
LAZYSET(holder.reagent_data, type, world.time)
to_chat(M, "You feel invigorated and calm.")
-/decl/material/liquid/nicotine/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/nicotine/affect_overdose(mob/living/victim, total_dose)
..()
- M.add_chemical_effect(CE_PULSE, 2)
+ victim.add_chemical_effect(CE_PULSE, 2)
/decl/material/liquid/sedatives
name = "sedatives"
@@ -253,10 +253,9 @@
if(istype(M))
M.remove_client_color(/datum/client_color/noir/thirdeye)
-/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/M, total_dose)
- M.take_damage(rand(1, 5), BRAIN)
- if(ishuman(M) && prob(10))
- var/mob/living/human/H = M
- H.seizure()
+/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/victim, total_dose)
+ victim.take_damage(rand(1, 5), BRAIN)
+ if(prob(10))
+ victim.seizure()
if(prob(10))
- to_chat(M, SPAN_DANGER("[pick(overdose_messages)]"))
+ to_chat(victim, SPAN_DANGER("[pick(overdose_messages)]"))
diff --git a/code/modules/reagents/chems/chems_medicines.dm b/code/modules/reagents/chems/chems_medicines.dm
index 701d2f1d476..7b8357a1767 100644
--- a/code/modules/reagents/chems/chems_medicines.dm
+++ b/code/modules/reagents/chems/chems_medicines.dm
@@ -52,14 +52,12 @@
uid = "chem_styptic"
var/effectiveness = 1
-/decl/material/liquid/brute_meds/affect_overdose(mob/living/M, var/datum/reagents/holder)
+/decl/material/liquid/brute_meds/affect_overdose(mob/living/victim, total_dose)
..()
- if(ishuman(M))
- M.add_chemical_effect(CE_BLOCKAGE, (15 + REAGENT_VOLUME(holder, type))/100)
- var/mob/living/human/H = M
- for(var/obj/item/organ/external/E in H.get_external_organs())
- if(E.status & ORGAN_ARTERY_CUT && prob(2 + REAGENT_VOLUME(holder, type) / overdose))
- E.status &= ~ORGAN_ARTERY_CUT
+ victim.add_chemical_effect(CE_BLOCKAGE, (15 + total_dose) / 100)
+ for(var/obj/item/organ/external/limb in victim.get_external_organs())
+ if((limb.status & ORGAN_ARTERY_CUT) && prob(2 + total_dose / overdose))
+ limb.status &= ~ORGAN_ARTERY_CUT
//This is a logistic function that effectively doubles the healing rate as brute amounts get to around 200. Any injury below 60 is essentially unaffected and there's a scaling inbetween.
#define ADJUSTED_REGEN_VAL(X) (6+(6/(1+200*2.71828**(-0.05*(X)))))
@@ -169,12 +167,10 @@
if(immunity_to_add > 0)
M.adjust_immunity(immunity_to_add) // Rapidly brings someone up to half immunity.
-/decl/material/liquid/immunobooster/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/immunobooster/affect_overdose(mob/living/victim, total_dose)
..()
- M.add_chemical_effect(CE_TOXIN, 1)
- var/mob/living/human/H = M
- if(istype(H))
- M.adjust_immunity(-0.5)
+ victim.add_chemical_effect(CE_TOXIN, 1)
+ victim.adjust_immunity(-0.5)
/decl/material/liquid/stimulants
name = "stimulants"
@@ -240,12 +236,12 @@
exoplanet_rarity_gas = MAT_RARITY_EXOTIC
uid = "chem_antibiotics"
-/decl/material/liquid/antibiotics/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/antibiotics/affect_overdose(mob/living/victim, total_dose)
..()
- M.adjust_immunity(-0.5)
- M.immunity = max(M.immunity - 0.25, 0)
+ victim.adjust_immunity(-0.5)
+ victim.immunity = max(victim.immunity - 0.25, 0)
if(prob(2))
- M.immunity_norm = max(M.immunity_norm - 1, 0)
+ victim.immunity_norm = max(victim.immunity_norm - 1, 0)
/decl/material/liquid/retrovirals
name = "retrovirals"
@@ -258,14 +254,12 @@
exoplanet_rarity_gas = MAT_RARITY_EXOTIC
uid = "chem_retrovirals"
-/decl/material/liquid/retrovirals/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/retrovirals/affect_overdose(mob/living/victim, total_dose)
. = ..()
- if(ishuman(M))
- var/mob/living/human/H = M
- for(var/obj/item/organ/external/E in H.get_external_organs())
- if(!BP_IS_PROSTHETIC(E) && prob(25) && !(E.status & ORGAN_MUTATED))
- E.mutate()
- E.limb_flags |= ORGAN_FLAG_DEFORMED
+ for(var/obj/item/organ/external/limb in victim.get_external_organs())
+ if(!BP_IS_PROSTHETIC(limb) && prob(25) && !(limb.status & ORGAN_MUTATED))
+ limb.mutate()
+ limb.limb_flags |= ORGAN_FLAG_DEFORMED
/decl/material/liquid/retrovirals/affect_blood(var/mob/living/M, var/removed, var/datum/reagents/holder)
. = ..()
@@ -404,8 +398,8 @@
break
..()
-/decl/material/liquid/clotting_agent/affect_overdose(mob/living/M, total_dose)
- var/obj/item/organ/internal/heart = GET_INTERNAL_ORGAN(M, BP_HEART)
+/decl/material/liquid/clotting_agent/affect_overdose(mob/living/victim, total_dose)
+ var/obj/item/organ/internal/heart = GET_INTERNAL_ORGAN(victim, BP_HEART)
if(heart && prob(25))
heart.take_general_damage(rand(1,3))
return ..()
diff --git a/code/modules/reagents/chems/chems_nutriment.dm b/code/modules/reagents/chems/chems_nutriment.dm
index d96d2b840d7..cc0774431ca 100644
--- a/code/modules/reagents/chems/chems_nutriment.dm
+++ b/code/modules/reagents/chems/chems_nutriment.dm
@@ -83,9 +83,9 @@
uid = "chem_nutriment_flour"
allergen_flags = ALLERGEN_GLUTEN
-/decl/material/liquid/nutriment/flour/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
+/decl/material/liquid/nutriment/flour/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
..()
- new /obj/effect/decal/cleanable/flour(T)
+ new /obj/effect/decal/cleanable/flour(touching_turf)
/decl/material/liquid/nutriment/batter
name = "batter"
@@ -102,9 +102,9 @@
boiling_point = 373
allergen_flags = ALLERGEN_EGG | ALLERGEN_GLUTEN
-/decl/material/liquid/nutriment/batter/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
+/decl/material/liquid/nutriment/batter/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
..()
- new /obj/effect/decal/cleanable/pie_smudge(T)
+ new /obj/effect/decal/cleanable/pie_smudge(touching_turf)
/decl/material/liquid/nutriment/batter/cakebatter
name = "cake batter"
diff --git a/code/modules/reagents/chems/chems_painkillers.dm b/code/modules/reagents/chems/chems_painkillers.dm
index 6647c2afed2..8ab62f4048f 100644
--- a/code/modules/reagents/chems/chems_painkillers.dm
+++ b/code/modules/reagents/chems/chems_painkillers.dm
@@ -112,17 +112,17 @@
M.add_chemical_effect(CE_ALCOHOL_TOXIC, 1)
M.add_chemical_effect(CE_BREATHLOSS, 1 * boozed) //drinking and opiating suppresses breathing.
-/decl/material/liquid/painkillers/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/painkillers/affect_overdose(mob/living/victim, total_dose)
..()
- M.add_chemical_effect(CE_PAINKILLER, pain_power*0.5) //extra painkilling for extra trouble
+ victim.add_chemical_effect(CE_PAINKILLER, pain_power*0.5) //extra painkilling for extra trouble
if(narcotic)
- SET_STATUS_MAX(M, STAT_DRUGGY, 10)
- M.set_hallucination(120, 30)
- M.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*2) //ODing on opiates can be deadly.
- if(isboozed(M))
- M.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*4) //Don't drink and OD on opiates folks
+ SET_STATUS_MAX(victim, STAT_DRUGGY, 10)
+ victim.set_hallucination(120, 30)
+ victim.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*2) //ODing on opiates can be deadly.
+ if(isboozed(victim))
+ victim.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*4) //Don't drink and OD on opiates folks
else
- M.add_chemical_effect(CE_TOXIN, 1)
+ victim.add_chemical_effect(CE_TOXIN, 1)
/decl/material/liquid/painkillers/proc/isboozed(var/mob/living/M)
. = 0
diff --git a/code/modules/reagents/chems/chems_pigments.dm b/code/modules/reagents/chems/chems_pigments.dm
index d110680a76e..55c6be4c47c 100644
--- a/code/modules/reagents/chems/chems_pigments.dm
+++ b/code/modules/reagents/chems/chems_pigments.dm
@@ -85,9 +85,9 @@
painting.reset_color()
painting.set_alpha(keep_alpha)
-/decl/material/liquid/paint_stripper/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
- if(istype(T) && !isspaceturf(T))
- remove_paint(T, holder)
+/decl/material/liquid/paint_stripper/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
+ if(istype(touching_turf) && !isspaceturf(touching_turf))
+ remove_paint(touching_turf, holder)
/decl/material/liquid/paint_stripper/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder)
if(istype(O))
@@ -107,20 +107,20 @@
uid = "chem_pigment_paint"
exoplanet_rarity_gas = MAT_RARITY_NOWHERE
-/decl/material/liquid/paint/proc/apply_paint(var/atom/painting, var/datum/reagents/holder)
- if(istype(painting) && istype(holder))
+/decl/material/liquid/paint/proc/apply_paint(var/atom/painting, var/datum/reagents/holder, var/threshold = 1)
+ if(istype(painting) && istype(holder) && REAGENT_VOLUME(holder, type) >= threshold)
var/keep_alpha = painting.alpha
painting.set_color(holder.get_color())
painting.set_alpha(keep_alpha)
-/decl/material/liquid/paint/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder)
- if(istype(T) && !isspaceturf(T))
- apply_paint(T, holder)
+/decl/material/liquid/paint/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder)
+ if(istype(touching_turf) && !isspaceturf(touching_turf))
+ apply_paint(touching_turf, holder, FLUID_MINIMUM_TRANSFER)
/decl/material/liquid/paint/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder)
if(istype(O))
- apply_paint(O, holder)
+ apply_paint(O, holder, O.get_object_size())
/decl/material/liquid/paint/touch_mob(var/mob/living/M, var/amount, var/datum/reagents/holder)
if(istype(M))
- apply_paint(M, holder)
\ No newline at end of file
+ apply_paint(M, holder, M.get_object_size())
diff --git a/code/modules/reagents/heat_sources/_heat_source.dm b/code/modules/reagents/heat_sources/_heat_source.dm
index b9295313707..eb5b3cebf44 100644
--- a/code/modules/reagents/heat_sources/_heat_source.dm
+++ b/code/modules/reagents/heat_sources/_heat_source.dm
@@ -5,8 +5,8 @@
#define HEATER_MODE_COOL "cool"
/obj/machinery/reagent_temperature
- name = "chemical heater"
- desc = "A small electric Bunsen, used to heat beakers and vials of chemicals."
+ name = "hotplate"
+ desc = "A small electric hotplate, used to heat cookware, beakers, or vials of chemicals."
icon = 'icons/obj/machines/heat_sources.dmi'
icon_state = "hotplate"
atom_flags = ATOM_FLAG_CLIMBABLE
@@ -70,6 +70,7 @@
/obj/machinery/reagent_temperature/ProcessAtomTemperature()
if(use_power >= POWER_USE_ACTIVE)
+
var/last_temperature = temperature
if(heater_mode == HEATER_MODE_HEAT && temperature < target_temperature)
temperature = min(target_temperature, temperature + heating_power)
@@ -79,10 +80,25 @@
if(container)
queue_temperature_atoms(container)
queue_icon_update()
+
+ // Hackery to heat pots placed onto a hotplate without also grilling/baking stuff.
+ if(isturf(loc))
+ var/datum/gas_mixture/environment = loc.return_air()
+ for(var/obj/item/chems/cooking_vessel/pot in loc.get_contained_external_atoms())
+ pot.fire_act(environment, temperature, 500)
+
return TRUE // Don't kill this processing loop unless we're not powered.
. = ..()
/obj/machinery/reagent_temperature/attackby(var/obj/item/thing, var/mob/user)
+
+ if(istype(thing, /obj/item/chems/cooking_vessel))
+ if(!user.try_unequip(thing, get_turf(src)))
+ return TRUE
+ thing.reset_offsets(anim_time = 0)
+ user.visible_message(SPAN_NOTICE("\The [user] places \the [thing] onto \the [src]."))
+ return TRUE
+
if(IS_WRENCH(thing))
if(use_power == POWER_USE_ACTIVE)
to_chat(user, SPAN_WARNING("Turn \the [src] off first!"))
diff --git a/code/modules/reagents/reactions/_reaction.dm b/code/modules/reagents/reactions/_reaction.dm
index e743ecf0ab2..fbc2eaa85d6 100644
--- a/code/modules/reagents/reactions/_reaction.dm
+++ b/code/modules/reagents/reactions/_reaction.dm
@@ -38,7 +38,7 @@
return 1
-/decl/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(thermal_product && location && ATOM_SHOULD_TEMPERATURE_ENQUEUE(location))
ADJUST_ATOM_TEMPERATURE(location, location.temperature + (location.get_thermal_mass_coefficient() * thermal_product))
@@ -61,8 +61,6 @@
if(reaction_volume > A)
reaction_volume = A
- var/alt_reaction_indicator = get_alternate_reaction_indicator(holder)
-
for(var/reactant in required_reagents)
holder.remove_reagent(reactant, reaction_volume * required_reagents[reactant], safety = 1)
@@ -71,7 +69,7 @@
if(result)
holder.add_reagent(result, amt_produced, data, safety = 1)
- on_reaction(holder, amt_produced, alt_reaction_indicator, data)
+ on_reaction(holder, amt_produced, data)
//called after processing reactions, if they occurred
/decl/chemical_reaction/proc/post_reaction(var/datum/reagents/holder)
diff --git a/code/modules/reagents/reactions/reaction_compounds.dm b/code/modules/reagents/reactions/reaction_compounds.dm
index 8e530dacaa5..8df2ada04be 100644
--- a/code/modules/reagents/reactions/reaction_compounds.dm
+++ b/code/modules/reagents/reactions/reaction_compounds.dm
@@ -155,10 +155,20 @@
required_reagents = list(/decl/material/liquid/capsaicin = 2)
result = list(/decl/material/liquid/capsaicin/condensed = 1)
-/decl/chemical_reaction/compound/condensed_capsaicin/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/compound/condensed_capsaicin/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
. = ..()
holder?.add_reagent(/decl/material/liquid/water, created_volume)
+/decl/chemical_reaction/compound/nanitefluid
+ name = "Nanite Fluid"
+ result = /decl/material/liquid/nanitefluid
+ required_reagents = list(/decl/material/liquid/plasticide = 1, /decl/material/solid/metal/aluminium = 1, /decl/material/liquid/lube = 1)
+ catalysts = list(/decl/material/solid/phoron = 5)
+ result_amount = 3
+ minimum_temperature = (-25 CELSIUS) - 100
+ maximum_temperature = -25 CELSIUS
+ mix_message = "The solution becomes a metallic slime."
+
// This is a bit silly, but we need a way to unify oil types until someone rewrites lanterns.
/decl/chemical_reaction/compound/fuel_oil
name = "Plant Fuel Oil"
diff --git a/code/modules/reagents/reactions/reaction_drugs.dm b/code/modules/reagents/reactions/reaction_drugs.dm
index 657850ae05c..a4f85cb3fa7 100644
--- a/code/modules/reagents/reactions/reaction_drugs.dm
+++ b/code/modules/reagents/reactions/reaction_drugs.dm
@@ -111,16 +111,6 @@
required_reagents = list(/decl/material/liquid/antirads = 1, /decl/material/solid/carbon = 1)
result_amount = 2
-/decl/chemical_reaction/compound/nanitefluid
- name = "Nanite Fluid"
- result = /decl/material/liquid/nanitefluid
- required_reagents = list(/decl/material/liquid/plasticide = 1, /decl/material/solid/metal/aluminium = 1, /decl/material/liquid/lube = 1)
- catalysts = list(/decl/material/solid/phoron = 5)
- result_amount = 3
- minimum_temperature = (-25 CELSIUS) - 100
- maximum_temperature = -25 CELSIUS
- mix_message = "The solution becomes a metallic slime."
-
/decl/chemical_reaction/drug/antibiotics
name = "Antibiotics"
result = /decl/material/liquid/antibiotics
diff --git a/code/modules/reagents/reactions/reaction_grenade_reaction.dm b/code/modules/reagents/reactions/reaction_grenade_reaction.dm
index ec529bef717..7827c6ac054 100644
--- a/code/modules/reagents/reactions/reaction_grenade_reaction.dm
+++ b/code/modules/reagents/reactions/reaction_grenade_reaction.dm
@@ -11,7 +11,7 @@
required_reagents = list(/decl/material/liquid/water = 1, /decl/material/solid/potassium = 1)
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/explosion_potassium/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/explosion_potassium/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
@@ -32,7 +32,7 @@
result_amount = null
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/flash_powder/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/flash_powder/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -58,7 +58,7 @@
mix_message = "The solution bubbles vigorously!"
maximum_temperature = T100C
-/decl/chemical_reaction/grenade_reaction/emp_pulse/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/emp_pulse/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
@@ -79,7 +79,7 @@
reaction_sound = 'sound/items/Welder.ogg'
mix_message = "The solution suddenly ignites!"
-/decl/chemical_reaction/grenade_reaction/flash_fire/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/flash_fire/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(istype(location))
@@ -93,7 +93,7 @@
result_amount = 0.4
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/chemsmoke/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/chemsmoke/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -112,7 +112,7 @@
result_amount = 2
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/foam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/foam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -129,7 +129,7 @@
result_amount = 5
mix_message = "The solution foams up violently!"
-/decl/chemical_reaction/grenade_reaction/metalfoam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/metalfoam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/atom/location = holder.get_reaction_loc(chemical_reaction_flags)
if(location)
@@ -151,7 +151,7 @@
result_amount = 5
mix_message = "The solution bubbles vigorously!"
-/decl/chemical_reaction/grenade_reaction/ironfoam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/grenade_reaction/ironfoam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
diff --git a/code/modules/reagents/reactions/reaction_herbal.dm b/code/modules/reagents/reactions/reaction_herbal.dm
index b8a02ca07fe..62950dd1d64 100644
--- a/code/modules/reagents/reactions/reaction_herbal.dm
+++ b/code/modules/reagents/reactions/reaction_herbal.dm
@@ -3,7 +3,7 @@
result_amount = 2
minimum_temperature = 100 CELSIUS
-/decl/chemical_reaction/drug/herbal/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/drug/herbal/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
. = ..()
// Add plant matter to represent the herbs that the medicine has been leached out of.
holder?.add_reagent(/decl/material/solid/organic/plantmatter, created_volume)
diff --git a/code/modules/reagents/reactions/reaction_other.dm b/code/modules/reagents/reactions/reaction_other.dm
index 19c5613ea7e..dca52f041f6 100644
--- a/code/modules/reagents/reactions/reaction_other.dm
+++ b/code/modules/reagents/reactions/reaction_other.dm
@@ -10,7 +10,7 @@
return ..()
return 0
-/decl/chemical_reaction/soap_key/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/soap_key/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
var/obj/item/soap/S = holder.get_reaction_loc(chemical_reaction_flags)
if(istype(S) && S.key_data)
new /obj/item/key/temporary(get_turf(S), /decl/material/liquid/cleaner, S.key_data, strength)
diff --git a/code/modules/reagents/reactions/reaction_recipe_food.dm b/code/modules/reagents/reactions/reaction_recipe_food.dm
index bc052960e91..0ece0daefd2 100644
--- a/code/modules/reagents/reactions/reaction_recipe_food.dm
+++ b/code/modules/reagents/reactions/reaction_recipe_food.dm
@@ -4,7 +4,7 @@
abstract_type = /decl/chemical_reaction/recipe/food
var/obj_result
-/decl/chemical_reaction/recipe/food/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/recipe/food/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(obj_result && isturf(location))
diff --git a/code/modules/reagents/reactions/reaction_synthesis.dm b/code/modules/reagents/reactions/reaction_synthesis.dm
index 57192c726ae..79695861328 100644
--- a/code/modules/reagents/reactions/reaction_synthesis.dm
+++ b/code/modules/reagents/reactions/reaction_synthesis.dm
@@ -19,7 +19,7 @@
)
. = ..()
-/decl/chemical_reaction/synthesis/fiberglass/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/fiberglass/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -44,7 +44,7 @@
if(rtype != /decl/material/liquid/crystal_agent && REAGENT_VOLUME(holder, rtype) >= REAGENT_UNITS_PER_MATERIAL_SHEET)
return TRUE
-/decl/chemical_reaction/synthesis/crystalization/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/crystalization/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
var/list/removing_reagents = list()
@@ -78,7 +78,7 @@
continue
return TRUE
-/decl/chemical_reaction/synthesis/aerogel/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/aerogel/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
var/list/removing_reagents = list()
@@ -97,7 +97,7 @@
required_reagents = list(/decl/material/liquid/acid = 1, /decl/material/liquid/plasticide = 2)
mix_message = "The solution solidifies into a grey-white mass."
-/decl/chemical_reaction/synthesis/plastication/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/plastication/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(location)
@@ -112,7 +112,7 @@
result_amount = 3
mix_message = "The solution hardens and begins to crystallize."
-/decl/chemical_reaction/synthesis/resin_pack/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/resin_pack/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(!istype(T))
@@ -133,7 +133,7 @@
mix_message = "The solution thickens and solidifies."
minimum_temperature = 100 CELSIUS
-/decl/chemical_reaction/synthesis/soap/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/soap/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(!istype(T))
@@ -164,7 +164,7 @@
minimum_temperature = 100 CELSIUS
var/chipboard_type = /decl/material/solid/organic/wood/chipboard
-/decl/chemical_reaction/synthesis/chipboard/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
+/decl/chemical_reaction/synthesis/chipboard/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
..()
var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
if(!istype(T))
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 99ec47811aa..de18007e761 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -27,6 +27,8 @@
/obj/item/chems/on_update_icon()
. = ..()
+ if(detail_state)
+ add_overlay(overlay_image(icon, "[initial(icon_state)][detail_state]", detail_color || COLOR_WHITE, RESET_COLOR))
var/image/contents_overlay = get_reagents_overlay(use_single_icon ? icon_state : null)
if(contents_overlay)
add_overlay(contents_overlay)
@@ -198,12 +200,21 @@
//
// 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
+ examine_desc = "set the transfer volume"
/decl/interaction_handler/set_transfer/chems/is_possible(var/atom/target, var/mob/user)
. = ..()
@@ -220,6 +231,7 @@
name = "Empty On Floor"
expected_target_type = /obj/item/chems
interaction_flags = INTERACTION_NEEDS_INVENTORY | INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC
+ examine_desc = "empty $TARGET_THEM$ onto the floor"
/decl/interaction_handler/empty/chems/invoked(atom/target, mob/user, obj/item/prop)
var/turf/T = get_turf(user)
diff --git a/code/modules/reagents/reagent_containers/_glass.dm b/code/modules/reagents/reagent_containers/_glass.dm
index 90981c54511..f381c8a44bb 100644
--- a/code/modules/reagents/reagent_containers/_glass.dm
+++ b/code/modules/reagents/reagent_containers/_glass.dm
@@ -58,9 +58,15 @@
/obj/item/chems/glass/proc/can_lid()
return TRUE
+/obj/item/chems/glass/proc/should_drink_from(mob/drinker)
+ . = reagents?.total_volume > 0
+ if(.)
+ var/decl/material/drinking = reagents.get_primary_reagent_decl()
+ return drinking ? !drinking.is_unsafe_to_drink(drinker) : FALSE
+
/obj/item/chems/glass/attack_self(mob/user)
- . = ..()
- if(!. && can_lid())
+
+ if(can_lid() && user.check_intent(I_FLAG_HELP))
if(ATOM_IS_OPEN_CONTAINER(src))
to_chat(user, SPAN_NOTICE("You put the lid on \the [src]."))
atom_flags ^= ATOM_FLAG_OPEN_CONTAINER
@@ -68,9 +74,15 @@
to_chat(user, SPAN_NOTICE("You take the lid off \the [src]."))
atom_flags |= ATOM_FLAG_OPEN_CONTAINER
update_icon()
+ return TRUE
+
+ if(should_drink_from(user) && is_edible(user) && handle_eaten_by_mob(user, user) != EATEN_INVALID)
+ return TRUE
+
+ 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
@@ -102,17 +114,6 @@
. = ..()
// Drinking out of bowls.
-/obj/item/chems/glass/attack_self(mob/user)
- if(is_edible(user) && handle_eaten_by_mob(user, user) != EATEN_INVALID)
- return TRUE
- return ..()
-
-/obj/item/chems/glass/get_food_default_transfer_amount(mob/eater)
- return eater?.get_eaten_transfer_amount(amount_per_transfer_from_this)
-
-/obj/item/chems/glass/get_food_consumption_method(mob/eater)
- return EATING_METHOD_DRINK
-
/obj/item/chems/glass/get_edible_material_amount(mob/eater)
return reagents?.total_volume
@@ -123,36 +124,53 @@
// Should we consider moving this down to /chems for any open container? Medicine from a bottle using a spoon, etc.
/obj/item/chems/glass/attackby(obj/item/used_item, mob/living/user)
- if(ATOM_IS_OPEN_CONTAINER(src))
- if(istype(used_item, /obj/item/food))
- if(!reagents?.total_volume)
- to_chat(user, SPAN_WARNING("\The [src] is empty."))
- return TRUE
- var/transferring = min(get_food_default_transfer_amount(user), REAGENTS_FREE_SPACE(used_item.reagents))
- if(!transferring)
- to_chat(user, SPAN_WARNING("You cannot dip \the [used_item] in \the [src]."))
- return TRUE
- reagents.trans_to_holder(used_item.reagents, transferring)
- user.visible_message(SPAN_NOTICE("\The [user] dunks \the [used_item] in \the [src]."))
+ if(!ATOM_IS_OPEN_CONTAINER(src))
+ return ..()
+
+ var/obj/item/utensil/utensil = used_item
+ if(istype(utensil) && (utensil.utensil_flags & UTENSIL_FLAG_SCOOP))
+ if(utensil.loaded_food)
+ to_chat(user, SPAN_WARNING("You already have something on \the [utensil]."))
return TRUE
- var/obj/item/utensil/utensil = used_item
- if(istype(utensil) && (utensil.utensil_flags & UTENSIL_FLAG_SCOOP))
- if(utensil.loaded_food)
- to_chat(user, SPAN_WARNING("You already have something on \the [utensil]."))
- return TRUE
- if(!reagents?.total_volume)
- to_chat(user, SPAN_WARNING("\The [src] is empty."))
- return TRUE
- seperate_food_chunk(utensil, user)
- if(utensil.loaded_food?.reagents?.total_volume)
- to_chat(user, SPAN_NOTICE("You scoop up some of \the [utensil.loaded_food.reagents.get_primary_reagent_name()] with \the [utensil]."))
+ if(!reagents?.total_volume)
+ to_chat(user, SPAN_WARNING("\The [src] is empty."))
return TRUE
+ seperate_food_chunk(utensil, user)
+ if(utensil.loaded_food?.reagents?.total_volume)
+ to_chat(user, SPAN_NOTICE("You scoop up some of \the [utensil.loaded_food.reagents.get_primary_reagent_name()] with \the [utensil]."))
+ return TRUE
+
return ..()
-/obj/structure/glass/get_alt_interactions(mob/user)
+/obj/item/chems/glass/get_alt_interactions(mob/user)
. = ..()
if(reagents?.total_volume >= FLUID_PUDDLE)
LAZYADD(., /decl/interaction_handler/dip_item)
LAZYADD(., /decl/interaction_handler/fill_from)
if(user?.get_active_held_item())
LAZYADD(., /decl/interaction_handler/empty_into)
+ if(can_lid())
+ LAZYADD(., /decl/interaction_handler/toggle_lid)
+
+/decl/interaction_handler/toggle_lid
+ name = "Toggle Lid"
+ expected_target_type = /obj/item/chems/glass
+
+/decl/interaction_handler/toggle_lid/is_possible(atom/target, mob/user, obj/item/prop)
+ . = ..()
+ if(. && !istype(prop))
+ var/obj/item/chems/glass/glass = target
+ return glass.can_lid()
+
+/decl/interaction_handler/toggle_lid/invoked(atom/target, mob/user, obj/item/prop)
+ var/obj/item/chems/glass/glass = target
+ if(istype(glass) && glass.can_lid())
+ if(ATOM_IS_OPEN_CONTAINER(glass))
+ to_chat(user, SPAN_NOTICE("You put the lid on \the [glass]."))
+ glass.atom_flags ^= ATOM_FLAG_OPEN_CONTAINER
+ else
+ to_chat(user, SPAN_NOTICE("You take the lid off \the [glass]."))
+ glass.atom_flags |= ATOM_FLAG_OPEN_CONTAINER
+ glass.update_icon()
+ return TRUE
+
diff --git a/code/modules/reagents/reagent_containers/beaker.dm b/code/modules/reagents/reagent_containers/beaker.dm
index 9e055646570..724a0ca448b 100644
--- a/code/modules/reagents/reagent_containers/beaker.dm
+++ b/code/modules/reagents/reagent_containers/beaker.dm
@@ -178,5 +178,5 @@
matter = list(/decl/material/solid/organic/plastic = MATTER_AMOUNT_REINFORCEMENT)
volume = 120
-/obj/item/chems/glass/beaker/sulphuric/populate_reagents()
+/obj/item/chems/glass/beaker/sulfuric/populate_reagents()
add_to_reagents(/decl/material/liquid/acid, reagents.maximum_volume)
diff --git a/code/modules/reagents/reagent_containers/drinks.dm b/code/modules/reagents/reagent_containers/drinks.dm
index 46c56514eee..d80b593cf60 100644
--- a/code/modules/reagents/reagent_containers/drinks.dm
+++ b/code/modules/reagents/reagent_containers/drinks.dm
@@ -57,7 +57,7 @@
return
return ..()
-/obj/item/chems/drinks/standard_dispenser_refill(var/mob/user, var/obj/structure/reagent_dispensers/target, skip_container_check = FALSE)
+/obj/item/chems/drinks/standard_dispenser_refill(mob/user, obj/structure/reagent_dispensers/target, skip_container_check = FALSE)
return do_open_check(user) && ..()
/obj/item/chems/drinks/standard_pour_into(var/mob/user, var/atom/target)
@@ -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 5d0776020c4..56e5f6b4720 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 c28d70364f6..55309ff3d2c 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 d4a3a57106b..fd8ec91188e 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/food/sliceable/pizza/pizza_box.dm b/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm
index a048bb7eac3..6c6cf548fe6 100644
--- a/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm
+++ b/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm
@@ -304,6 +304,7 @@
/decl/interaction_handler/open_pizza_box
expected_target_type = /obj/item/pizzabox
+ examine_desc = "open or close $TARGET_THEM$"
/decl/interaction_handler/open_pizza_box/is_possible(atom/target, mob/user, obj/item/prop)
. = ..()
diff --git a/code/modules/reagents/reagent_containers/inhaler.dm b/code/modules/reagents/reagent_containers/inhaler.dm
index 275a3bac13d..19eaaa9cd1d 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 fe85a5c09fe..b19a7340e23 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 c46af37998f..391c3440471 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/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 9cd81a4c437..c3b4cbd9ff8 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -36,9 +36,6 @@
if(A?.storage || istype(A, /obj/structure/table) || istype(A, /obj/structure/closet) || istype(A, /obj/item/chems) || istype(A, /obj/structure/hygiene/sink) || istype(A, /obj/structure/janitorialcart))
return
- if(istype(A, /spell))
- return
-
if(proximity)
if(standard_dispenser_refill(user, A))
return
@@ -50,7 +47,7 @@
Spray_at(A, user, proximity)
if(reagents.has_reagent(/decl/material/liquid/acid))
- log_and_message_admins("fired sulphuric acid from \a [src].", user)
+ log_and_message_admins("fired sulfuric acid from \a [src].", user)
if(reagents.has_reagent(/decl/material/liquid/acid/polyacid))
log_and_message_admins("fired polyacid from \a [src].", user)
if(reagents.has_reagent(/decl/material/liquid/lube))
@@ -119,6 +116,7 @@
name = "Next Nozzle Setting"
expected_target_type = /obj/item/chems/spray
interaction_flags = INTERACTION_NEEDS_INVENTORY | INTERACTION_NEEDS_PHYSICAL_INTERACTION
+ examine_desc = "select the next nozzle spray amount"
/decl/interaction_handler/next_spray_amount/is_possible(obj/item/chems/spray/target, mob/user, obj/item/prop)
. = ..()
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index ba547ec695c..0018d127862 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/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index d8d5d4e5e06..778ed37be45 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -10,6 +10,7 @@
matter = list(/decl/material/solid/metal/steel = MATTER_AMOUNT_SECONDARY)
max_health = 100
tool_interaction_flags = TOOL_INTERACTION_DECONSTRUCT
+
var/wrenchable = TRUE
var/unwrenched = FALSE
var/tmp/volume = 1000
@@ -102,6 +103,7 @@
log_and_message_admins("opened a tank at [get_area_name(loc)].")
leak()
return TRUE
+
. = ..()
/obj/structure/reagent_dispensers/verb/set_amount_dispensed()
@@ -317,11 +319,12 @@
add_to_reagents(/decl/material/liquid/alcohol/beer, reagents.maximum_volume)
/obj/structure/reagent_dispensers/acid
- name = "sulphuric acid dispenser"
+ name = "sulfuric acid dispenser"
desc = "A dispenser of acid for industrial processes."
icon_state = "acidtank"
amount_dispensed = 10
anchored = TRUE
+ density = FALSE
/obj/structure/reagent_dispensers/acid/populate_reagents()
add_to_reagents(/decl/material/liquid/acid, reagents.maximum_volume)
@@ -351,6 +354,7 @@
/decl/interaction_handler/toggle_open/reagent_dispenser
name = "Toggle refilling cap"
expected_target_type = /obj/structure/reagent_dispensers
+ examine_desc = "open or close the refilling cap"
/decl/interaction_handler/toggle_open/reagent_dispenser/invoked(atom/target, mob/user, obj/item/prop)
if(target.atom_flags & ATOM_FLAG_OPEN_CONTAINER)
diff --git a/code/modules/recycling/disposalholder.dm b/code/modules/recycling/disposalholder.dm
index 4f3546d06a6..7a95d7d2ce2 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 e035da8b825..88e11fbbdc6 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 57261df802b..da2a33bfd70 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/sealant_gun/sealant_injector.dm b/code/modules/sealant_gun/sealant_injector.dm
index a3e89a44343..99f8553586d 100644
--- a/code/modules/sealant_gun/sealant_injector.dm
+++ b/code/modules/sealant_gun/sealant_injector.dm
@@ -103,6 +103,7 @@
/decl/interaction_handler/sealant_try_inject
name = "Inject Sealant"
expected_target_type = /obj/structure/sealant_injector
+ examine_desc = "inject sealant from a held item"
/decl/interaction_handler/sealant_try_inject/invoked(atom/target, mob/user, obj/item/prop)
var/obj/structure/sealant_injector/SI = target
diff --git a/code/modules/shield_generators/shield.dm b/code/modules/shield_generators/shield.dm
index 0b97dd24cbf..b39816fdce5 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 f76892be8a4..0cb3ee417b9 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 12682043752..0ca75384784 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 c12dc6e38d9..bd13d30c417 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/landmarks.dm b/code/modules/shuttles/landmarks.dm
index 82cde0c759b..661bab8cf89 100644
--- a/code/modules/shuttles/landmarks.dm
+++ b/code/modules/shuttles/landmarks.dm
@@ -135,7 +135,7 @@ var/global/list/shuttle_landmarks = list()
/obj/effect/shuttle_landmark/automatic/sector_set(var/obj/effect/overmap/visitable/O)
..()
- SetName("[initial(name)] ([x],[y])")
+ SetName("[initial(name)] ([x],[y],[z])")
//Subtype that calls explosion on init to clear space for shuttles
/obj/effect/shuttle_landmark/automatic/clearing
diff --git a/code/modules/shuttles/shuttle.dm b/code/modules/shuttles/shuttle.dm
index 794f0736f12..85ee565817b 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 74c157df8fe..f2003eb0129 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 2bdc11d2284..f6efaa4a864 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 4f23361de2b..ebe0a7cf54f 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 41778075e99..90a54b1eab0 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 175924860dc..f38e5fef5b3 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 35e00c68be6..71e144e02e2 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 06db017b9df..d7477882df5 100644
--- a/code/modules/species/species.dm
+++ b/code/modules/species/species.dm
@@ -57,9 +57,6 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200
var/flesh_color = "#ffc896" // Pink.
var/blood_oxy = 1
- // Preview in prefs positioning. If null, uses defaults set on a static list in preferences.dm.
- var/list/character_preview_screen_locs
-
var/organs_icon //species specific internal organs icons
var/strength = STR_MEDIUM
@@ -82,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.
@@ -499,23 +492,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 d2daf2daa06..0fffa984643 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 5bd257fa5bc..efd996aaf26 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 f63a7bc37bf..7add078db3a 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 9f571d66c60..93dc4786eae 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 6264a7b2048..2ee92427f41 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 9159f5eadc3..1871219744e 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/spells/aoe_turf/aoe_turf.dm b/code/modules/spells/aoe_turf/aoe_turf.dm
deleted file mode 100644
index 0f7a721de80..00000000000
--- a/code/modules/spells/aoe_turf/aoe_turf.dm
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-Aoe turf spells target a ring of tiles around the user
-This ring has an outer radius (range) and an inner radius (inner_radius)
-Aoe turf spells have a useful flag: IGNOREDENSE. It is explained in setup.dm
-*/
-
-/spell/aoe_turf //affects all turfs in view or range (depends)
- spell_flags = IGNOREDENSE
- var/inner_radius = -1 //for all your ring spell needs
-
-/spell/aoe_turf/choose_targets(mob/user = usr)
- var/list/targets = list()
-
- for(var/turf/target in view_or_range(range, holder, selection_type))
- if(!(target in view_or_range(inner_radius, holder, selection_type)))
- if(target.density && (spell_flags & IGNOREDENSE))
- continue
- targets += target
-
- if(!targets.len) //doesn't waste the spell
- return
-
- return targets
\ No newline at end of file
diff --git a/code/modules/spells/aoe_turf/conjure/conjure.dm b/code/modules/spells/aoe_turf/conjure/conjure.dm
deleted file mode 100644
index 8dd91146310..00000000000
--- a/code/modules/spells/aoe_turf/conjure/conjure.dm
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Conjure spells spawn things (mobs, objs, turfs) in their summon_type
-How they spawn stuff is decided by behaviour vars, which are explained below
-*/
-
-/spell/aoe_turf/conjure
- name = "Conjure"
- desc = "This spell conjures objs of the specified types in range."
-
- school = "conjuration" //funny, that
-
- var/list/summon_type = list() //determines what exactly will be summoned
- //should NOT be text, like list(/obj/machinery/bot/ed209)
-
- range = 0 //default values: only spawn on the player tile
- selection_type = "view"
-
- duration = 0 // 0=permanent, any other time in deciseconds - how long the summoned objects last for
- var/summon_amt = 1 //amount of objects summoned
- var/summon_exclusive = 0 //spawn one of everything, instead of random things
-
- var/list/newVars = list() //vars of the summoned objects will be replaced with those where they meet
- //should have format of list("emagged" = 1,"name" = "Justicebot"), for example
-
- cast_sound = 'sound/magic/castsummon.ogg'
-
-/spell/aoe_turf/conjure/cast(list/targets, mob/user)
-
- for(var/i=1,i <= summon_amt,i++)
- if(!targets.len)
- break
- var/summoned_object_type
- if(summon_exclusive)
- if(!summon_type.len)
- break
- summoned_object_type = summon_type[1]
- summon_type -= summoned_object_type
- else
- summoned_object_type = pick(summon_type)
- var/turf/spawn_place = pick(targets)
- var/atom/summoned_object
- if(ispath(summoned_object_type,/turf))
- spawn_place.ChangeTurf(summoned_object_type)
- summoned_object = spawn_place
- else
- summoned_object = new summoned_object_type(spawn_place)
- var/atom/movable/overlay/animation = new /atom/movable/overlay(summoned_object)
- animation.SetName("conjure")
- animation.set_density(0)
- animation.anchored = TRUE
- animation.icon = 'icons/effects/effects.dmi'
- animation.layer = BASE_HUMAN_LAYER
- if(ismob(summoned_object)) //we want them to NOT attack us.
- var/mob/M = summoned_object
- M.faction = user.faction
- apply_vars(summoned_object, user)
-
- if(duration)
- spawn(duration)
- if(summoned_object && !isturf(summoned_object))
- qdel(summoned_object)
- conjure_animation(animation, spawn_place)
- return
-
-/spell/aoe_turf/conjure/proc/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
- qdel(animation)
-
-/spell/aoe_turf/conjure/proc/apply_vars(atom/summoned_object, mob/caster)
- if(!istype(summoned_object) || !length(newVars))
- return
- for(var/varName in newVars)
- if(varName in summoned_object.vars)
- summoned_object.vars[varName] = newVars[varName]
diff --git a/code/modules/spells/construct_spells.dm b/code/modules/spells/construct_spells.dm
deleted file mode 100644
index 0c705aff4fc..00000000000
--- a/code/modules/spells/construct_spells.dm
+++ /dev/null
@@ -1,10 +0,0 @@
-//////////////////////////////Construct Spells/////////////////////////
-
-/proc/findNullRod(var/atom/target)
- if(istype(target,/obj/item/nullrod))
- return 1
- else if(target.contents)
- for(var/atom/A in target.contents)
- if(findNullRod(A))
- return 1
- return 0
diff --git a/code/modules/spells/spell_code.dm b/code/modules/spells/spell_code.dm
deleted file mode 100644
index bfcf1f4d8f6..00000000000
--- a/code/modules/spells/spell_code.dm
+++ /dev/null
@@ -1,385 +0,0 @@
-var/global/list/spells = typesof(/spell) //needed for the badmin verb for now
-
-/spell
- var/name
- var/desc
- var/feedback = "" //what gets sent if this spell gets chosen by the spellbook.
- parent_type = /datum
- var/panel = "Spells"//What panel the proc holder needs to go on.
-
- var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
- /*Spell schools as follows:
- Racial - Only tagged to spells gained for being a certain race
- Conjuration - Creating an object or transporting it.
- Transmutation - Modifying an object or transforming it.
- Illusion - Altering perception or thought.
- */
- var/charge_type = Sp_RECHARGE //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that
-
- var/charge_max = 100 //recharge time in deciseconds if charge_type = Sp_RECHARGE or starting charges if charge_type = Sp_CHARGES
- var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = Sp_RECHARGE or -- each cast if charge_type = Sp_CHARGES
- var/still_recharging_msg = "The spell is still recharging."
-
- var/silenced = 0 //not a binary - the length of time we can't cast this for
- var/processing = 0 //are we processing already? Mainly used so that silencing a spell doesn't call process() again. (and inadvertedly making it run twice as fast)
-
- var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var"
- var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used
-
- var/spell_flags = 0
- var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
- var/invocation_type = SpI_NONE //can be none, whisper, shout, and emote
- var/range = 7 //the range of the spell; outer radius for aoe spells
- var/message = "" //whatever it says to the guy affected by it
- var/selection_type = "view" //can be "range" or "view"
- var/atom/movable/holder //where the spell is. Normally the user, can be an item
- var/duration = 0 //how long the spell lasts
-
- var/list/spell_levels = list(Sp_SPEED = 0, Sp_POWER = 0) //the current spell levels - total spell levels can be obtained by just adding the two values
- var/list/level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 0) //maximum possible levels in each category. Total does cover both.
- var/cooldown_reduc = 0 //If set, defines how much charge_max drops by every speed upgrade
- var/delay_reduc = 0
- var/cooldown_min = 0 //minimum possible cooldown for a charging spell
-
- var/overlay = 0
- var/overlay_icon = 'icons/obj/wizard.dmi'
- var/overlay_icon_state = "spell"
- var/overlay_lifespan = 0
-
- var/sparks_spread = 0
- var/sparks_amt = 0 //cropped at 10
- var/smoke_spread = 0 //1 - harmless, 2 - harmful
- var/smoke_amt = 0 //cropped at 10
-
- var/critfailchance = 0
- var/time_between_channels = 0 //Delay between casts
- var/number_of_channels = 1 //How many times can we channel?
-
- var/cast_delay = 1
- var/cast_sound = ""
-
- var/hud_state = "" //name of the icon used in generating the spell hud object
- var/override_base = ""
-
-
- var/obj/screen/connected_button
-
- var/hidden_from_codex = FALSE
-
-///////////////////////
-///SETUP AND PROCESS///
-///////////////////////
-
-/spell/New()
- ..()
-
- //still_recharging_msg = "[name] is still recharging."
- charge_counter = charge_max
-
-/spell/proc/process()
- if(processing)
- return
- processing = 1
- spawn(0)
- while(charge_counter < charge_max || silenced > 0)
- charge_counter = min(charge_max,charge_counter+1)
- silenced = max(0,silenced-1)
- sleep(1)
- if(connected_button)
- var/obj/screen/ability/spell/S = connected_button
- if(!istype(S))
- return
- S.update_charge(1)
- processing = 0
- return
-
-/////////////////
-/////CASTING/////
-/////////////////
-
-/spell/proc/choose_targets(mob/user = usr) //depends on subtype - see targeted.dm, aoe_turf.dm, dumbfire.dm, or code in general folder
- return
-
-/spell/proc/perform(mob/user = usr, skipcharge = 0) //if recharge is started is important for the trigger spells
- if(!holder)
- holder = user //just in case
- if(!cast_check(skipcharge, user))
- return
- to_chat(user, SPAN_NOTICE("You start casting \the [name]..."))
- if(cast_delay && !spell_do_after(user, cast_delay))
- return
- var/list/targets = choose_targets(user)
- if(!check_valid_targets(targets))
- to_chat(user, SPAN_WARNING("\The [name] fizzles. There are no valid targets nearby."))
- return
- var/time = 0
- admin_attacker_log(user, "attempted to cast the spell [name]")
- do
- time++
- if(!check_valid_targets(targets)) //make sure we HAVE something
- break
- if(cast_check(1,user, targets)) //we check again, otherwise you can choose a target and then wait for when you are no longer able to cast (I.E. Incapacitated) to use it.
- invocation(user, targets)
- take_charge(user, skipcharge)
- before_cast(targets) //applies any overlays and effects
- if(prob(critfailchance))
- critfail(targets, user)
- else
- cast(targets, user, time)
- after_cast(targets) //generates the sparks, smoke, target messages etc.
- else
- break
- while(time != number_of_channels && do_after(user, time_between_channels, incapacitation_flags = INCAPACITATION_KNOCKOUT|INCAPACITATION_FORCELYING|INCAPACITATION_STUNNED, same_direction=1))
- after_spell(targets, user, time) //When we are done with the spell completely.
-
-
-
-/spell/proc/cast(list/targets, mob/user, var/channel_duration) //the actual meat of the spell
- return
-
-/spell/proc/critfail(list/targets, mob/user) //the wizman has fucked up somehow
- return
-
-/spell/proc/after_spell(var/list/targets, var/mob/user, var/channel_duration) //After everything else is done.
- return
-
-/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types
- switch(type)
- if("bruteloss")
- target.take_damage(amount)
- if("fireloss")
- target.take_damage(amount, BURN)
- if("toxloss")
- target.take_damage(amount, TOX)
- if("oxyloss")
- target.take_damage(amount, OXY)
- if("brainloss")
- target.take_damage(amount, BRAIN)
- if("stunned")
- ADJ_STATUS(target, STAT_STUN, amount)
- if("weakened")
- ADJ_STATUS(target, STAT_WEAK, amount)
- if("paralysis")
- ADJ_STATUS(target, STAT_PARA, amount)
- else
- target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars
- return
-
-///////////////////////////
-/////CASTING WRAPPERS//////
-///////////////////////////
-
-/spell/proc/before_cast(list/targets)
- for(var/atom/target in targets)
- if(overlay)
- var/location
- if(isliving(target))
- location = target.loc
- else if(isturf(target))
- location = target
- var/obj/effect/overlay/spell = new /obj/effect/overlay(location)
- spell.icon = overlay_icon
- spell.icon_state = overlay_icon_state
- spell.anchored = TRUE
- spell.set_density(0)
- spawn(overlay_lifespan)
- qdel(spell)
-
-/spell/proc/after_cast(list/targets)
- if(cast_sound)
- playsound(get_turf(holder),cast_sound,50,1)
- for(var/atom/target in targets)
- var/location = get_turf(target)
- if(isliving(target) && message)
- to_chat(target, text("[message]"))
- if(sparks_spread)
- spark_at(location, amount = sparks_amt)
- if(smoke_spread)
- if(smoke_spread == 1)
- var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
- smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
- smoke.start()
- else if(smoke_spread == 2)
- var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad()
- smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
- smoke.start()
-
-/////////////////////
-////CASTING TOOLS////
-/////////////////////
-/*Checkers, cost takers, message makers, etc*/
-
-/spell/proc/cast_check(skipcharge = 0,mob/user = usr, var/list/targets) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
-
- if(silenced > 0)
- return 0
-
- if(!(src in user.mind.learned_spells) && holder == user && !(isanimal(user)))
- error("[user] utilized the spell '[src]' without having it.")
- to_chat(user, "You shouldn't have this spell! Something's wrong.")
- return 0
-
- var/turf/user_turf = get_turf(user)
- if(!user_turf)
- to_chat(user, "You cannot cast spells in null space!")
-
- if((spell_flags & Z2NOCAST) && isAdminLevel(user_turf.z)) //Certain spells are not allowed on the centcomm zlevel
- return 0
-
- if(spell_flags & CONSTRUCT_CHECK)
- for(var/turf/T in range(holder, 1))
- if(findNullRod(T))
- return 0
-
- if(!src.check_charge(skipcharge, user)) //sees if we can cast based on charges alone
- return 0
-
- if(holder == user)
- if(isanimal(user))
- var/mob/living/simple_animal/SA = user
- if(SA.purge)
- to_chat(SA, "The null sceptre's power interferes with your own!")
- return 0
-
- var/mob/living/L = user
- if(L.incapacitated(INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT))
- to_chat(user, "You can't cast spells while incapacitated!")
- return 0
-
- if(ishuman(user) && !(invocation_type in list(SpI_EMOTE, SpI_NONE)) && user.get_item_blocking_speech())
- to_chat(user, "Mmmf mrrfff!")
- return 0
-
- return 1
-
-/spell/proc/check_charge(var/skipcharge, mob/user)
- if(!skipcharge)
- switch(charge_type)
- if(Sp_RECHARGE)
- if(charge_counter < charge_max)
- to_chat(user, still_recharging_msg)
- return 0
- if(Sp_CHARGES)
- if(!charge_counter)
- to_chat(user, "[name] has no charges left.")
- return 0
- return 1
-
-/spell/proc/take_charge(mob/user = user, var/skipcharge)
- if(!skipcharge)
- switch(charge_type)
- if(Sp_RECHARGE)
- charge_counter = 0 //doesn't start recharging until the targets selecting ends
- src.process()
- return 1
- if(Sp_CHARGES)
- charge_counter-- //returns the charge if the targets selecting fails
- return 1
- if(Sp_HOLDVAR)
- adjust_var(user, holder_var_type, holder_var_amount)
- return 1
- return 0
- return 1
-
-/spell/proc/check_valid_targets(var/list/targets)
- if(!targets)
- return 0
- if(!islist(targets))
- targets = list(targets)
- else if(!targets.len)
- return 0
-
- var/list/valid_targets = view_or_range(range, holder, selection_type)
- for(var/target in targets)
- if(!(target in valid_targets))
- return 0
- return 1
-
-/spell/proc/invocation(mob/user = usr, var/list/targets) //spelling the spell out and setting it on recharge/reducing charges amount
-
- switch(invocation_type)
- if(SpI_SHOUT)
- if(prob(50))//Auto-mute? Fuck that noise
- user.say(invocation)
- else
- user.say(replacetext(invocation," ","`"))
- if(SpI_WHISPER)
- if(prob(50))
- user.whisper(invocation)
- else
- user.whisper(replacetext(invocation," ","`"))
- if(SpI_EMOTE)
- user.custom_emote(VISIBLE_MESSAGE, invocation)
-
-/////////////////////
-///UPGRADING PROCS///
-/////////////////////
-
-/spell/proc/can_improve(var/upgrade_type)
- if(level_max[Sp_TOTAL] <= ( spell_levels[Sp_SPEED] + spell_levels[Sp_POWER] )) //too many levels, can't do it
- return 0
-
- //if(upgrade_type && spell_levels[upgrade_type] && level_max[upgrade_type])
- if(upgrade_type && spell_levels[upgrade_type] >= level_max[upgrade_type])
- return 0
-
- return 1
-
-/spell/proc/empower_spell()
- if(!can_improve(Sp_POWER))
- return 0
-
- spell_levels[Sp_POWER]++
-
- return 1
-
-/spell/proc/quicken_spell()
- if(!can_improve(Sp_SPEED))
- return 0
-
- spell_levels[Sp_SPEED]++
-
- if(delay_reduc && cast_delay)
- cast_delay = max(0, cast_delay - delay_reduc)
- else if(cast_delay)
- cast_delay = round( max(0, initial(cast_delay) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) )
-
- if(charge_type == Sp_RECHARGE)
- if(cooldown_reduc)
- charge_max = max(cooldown_min, charge_max - cooldown_reduc)
- else
- charge_max = round( max(cooldown_min, initial(charge_max) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) //the fraction of the way you are to max speed levels is the fraction you lose
- if(charge_max < charge_counter)
- charge_counter = charge_max
-
- var/temp = ""
- name = initial(name)
- switch(level_max[Sp_SPEED] - spell_levels[Sp_SPEED])
- if(3)
- temp = "You have improved [name] into Efficient [name]."
- name = "Efficient [name]"
- if(2)
- temp = "You have improved [name] into Quickened [name]."
- name = "Quickened [name]"
- if(1)
- temp = "You have improved [name] into Free [name]."
- name = "Free [name]"
- if(0)
- temp = "You have improved [name] into Instant [name]."
- name = "Instant [name]"
-
- return temp
-
-/spell/proc/spell_do_after(var/mob/user, delay, var/numticks = 5)
- if(!user || isnull(user))
- return 0
-
- var/incap_flags = INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT
- return do_after(user,delay, incapacitation_flags = incap_flags)
-
-/proc/view_or_range(distance = world.view , center = usr , type)
- switch(type)
- if("view")
- . = view(distance,center)
- if("range")
- . = range(distance,center)
\ No newline at end of file
diff --git a/code/modules/spells/spells.dm b/code/modules/spells/spells.dm
deleted file mode 100644
index ad550747a7f..00000000000
--- a/code/modules/spells/spells.dm
+++ /dev/null
@@ -1,60 +0,0 @@
-/datum/mind
- var/list/learned_spells
-
-/mob/Stat()
- . = ..()
- if(. && ability_master && ability_master.spell_objects)
- for(var/obj/screen/ability/spell/screen in ability_master.spell_objects)
- var/spell/S = screen.spell
- if((!S.connected_button) || !statpanel(S.panel))
- continue //Not showing the noclothes spell
- switch(S.charge_type)
- if(Sp_RECHARGE)
- statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S.connected_button)
- if(Sp_CHARGES)
- statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button)
- if(Sp_HOLDVAR)
- statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button)
-
-/proc/restore_spells(var/mob/H)
- if(H.mind && H.mind.learned_spells)
- var/list/spells = list()
- for(var/spell/spell_to_remove in H.mind.learned_spells) //remove all the spells from other people.
- if(ismob(spell_to_remove.holder))
- var/mob/M = spell_to_remove.holder
- spells += spell_to_remove
- M.remove_spell(spell_to_remove)
-
- for(var/spell/spell_to_add in spells)
- H.add_spell(spell_to_add)
- H.ability_master.update_abilities(0,H)
-
-/mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready")
- if(!ability_master)
- ability_master = new(null, src)
- spell_to_add.holder = src
- if(mind)
- if(!mind.learned_spells)
- mind.learned_spells = list()
- mind.learned_spells |= spell_to_add
- ability_master.add_spell(spell_to_add, spell_base)
- return 1
-
-/mob/proc/remove_spell(var/spell/spell_to_remove)
- if(!spell_to_remove || !istype(spell_to_remove))
- return
-
- if(mind)
- mind.learned_spells -= spell_to_remove
- if (ability_master)
- ability_master.remove_ability(ability_master.get_ability_by_spell(spell_to_remove))
- return 1
-
-/mob/proc/silence_spells(var/amount = 0)
- if(amount < 0)
- return
-
- if(!ability_master)
- return
-
- ability_master.silence_spells(amount)
\ No newline at end of file
diff --git a/code/modules/spells/targeted/ethereal_jaunt.dm b/code/modules/spells/targeted/ethereal_jaunt.dm
deleted file mode 100644
index 55a0ed83359..00000000000
--- a/code/modules/spells/targeted/ethereal_jaunt.dm
+++ /dev/null
@@ -1,120 +0,0 @@
-/spell/targeted/ethereal_jaunt
- name = "Ethereal Jaunt"
- desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls."
- feedback = "EJ"
- school = "transmutation"
- charge_max = 30 SECONDS
- spell_flags = Z2NOCAST | INCLUDEUSER
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
- max_targets = 1
- level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 3)
- cooldown_min = 10 SECONDS //50 deciseconds reduction per rank
- duration = 5 SECONDS
-
- hud_state = "wiz_jaunt"
-
-/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded
- for(var/mob/living/target in targets)
- if(HAS_TRANSFORMATION_MOVEMENT_HANDLER(target))
- continue
-
- if(target.buckled)
- target.buckled.unbuckle_mob()
- spawn(0)
- var/mobloc = get_turf(target.loc)
- var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( mobloc )
- var/atom/movable/overlay/animation = new /atom/movable/overlay(holder)
- animation.SetName("water")
- animation.set_density(0)
- animation.anchored = TRUE
- animation.icon = 'icons/mob/mob.dmi'
- animation.layer = FLY_LAYER
- target.extinguish_fire()
- if(target.buckled)
- target.buckled = null
- jaunt_disappear(animation, target)
- target.forceMove(holder)
- jaunt_steam(mobloc)
- sleep(duration)
- mobloc = holder.last_valid_turf
- animation.forceMove(mobloc)
- jaunt_steam(mobloc)
- holder.reappearing = 1
- sleep(20)
- jaunt_reappear(animation, target)
- sleep(5)
- if(!target.forceMove(mobloc))
- for(var/direction in list(1,2,4,8,5,6,9,10))
- var/turf/T = get_step(mobloc, direction)
- if(T)
- if(target.forceMove(T))
- break
- target.client.eye = target
- qdel(animation)
- qdel(holder)
-
-/spell/targeted/ethereal_jaunt/empower_spell()
- if(!..())
- return 0
- duration += 2 SECONDS
-
- return "[src] now lasts longer."
-
-/spell/targeted/ethereal_jaunt/proc/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target)
- animation.icon_state = "liquify"
- flick("liquify",animation)
- playsound(get_turf(target), 'sound/magic/ethereal_enter.ogg', 30)
-
-/spell/targeted/ethereal_jaunt/proc/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target)
- flick("reappear",animation)
- playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 30)
-
-/spell/targeted/ethereal_jaunt/proc/jaunt_steam(var/mobloc)
- var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
- steam.set_up(10, 0, mobloc)
- steam.start()
-
-/obj/effect/dummy/spell_jaunt
- name = "water"
- icon = 'icons/effects/effects.dmi'
- icon_state = "nothing"
- var/canmove = 1
- var/reappearing = 0
- density = FALSE
- anchored = TRUE
- var/turf/last_valid_turf
-
-/obj/effect/dummy/spell_jaunt/Initialize()
- . = ..()
- last_valid_turf = get_turf(loc)
-
-/obj/effect/dummy/spell_jaunt/Destroy()
- // Eject contents if deleted somehow
- for(var/atom/movable/AM in src)
- AM.dropInto(loc)
- return ..()
-
-/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction)
- if (!canmove || reappearing) return
- var/turf/newLoc = get_step(src, direction)
- if(!(newLoc.turf_flags & TURF_FLAG_NOJAUNT))
- forceMove(newLoc)
- var/turf/T = get_turf(loc)
- if(!T.contains_dense_objects())
- last_valid_turf = T
- else
- to_chat(user, "Some strange aura is blocking the way!")
- canmove = 0
- addtimer(CALLBACK(src, PROC_REF(allow_move)), 2)
-
-/obj/effect/dummy/spell_jaunt/proc/allow_move()
- canmove = TRUE
-
-/obj/effect/dummy/spell_jaunt/explosion_act(blah)
- SHOULD_CALL_PARENT(FALSE)
- return
-
-/obj/effect/dummy/spell_jaunt/bullet_act(blah)
- return
diff --git a/code/modules/spells/targeted/shift.dm b/code/modules/spells/targeted/shift.dm
deleted file mode 100644
index 2bcc684939a..00000000000
--- a/code/modules/spells/targeted/shift.dm
+++ /dev/null
@@ -1,24 +0,0 @@
-/spell/targeted/ethereal_jaunt/shift
- name = "Phase Shift"
- desc = "This spell allows you to pass through walls"
-
- charge_max = 200
- spell_flags = Z2NOCAST | INCLUDEUSER | CONSTRUCT_CHECK
- invocation_type = SpI_NONE
- range = -1
- duration = 50 //in deciseconds
-
- hud_state = "const_shift"
-
-/spell/targeted/ethereal_jaunt/shift/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target)
- animation.icon_state = "phase_shift"
- animation.set_dir(target.dir)
- flick("phase_shift",animation)
-
-/spell/targeted/ethereal_jaunt/shift/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target)
- animation.icon_state = "phase_shift2"
- animation.set_dir(target.dir)
- flick("phase_shift2",animation)
-
-/spell/targeted/ethereal_jaunt/shift/jaunt_steam(var/mobloc)
- return
diff --git a/code/modules/spells/targeted/targeted.dm b/code/modules/spells/targeted/targeted.dm
deleted file mode 100644
index 733bbf1e540..00000000000
--- a/code/modules/spells/targeted/targeted.dm
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
-Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range
-Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm
-*/
-
-/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob
- var/max_targets = 1 //leave 0 for unlimited targets in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range
- var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast
-
-
- var/amt_weakened = 0
- var/amt_paralysis = 0
- var/amt_stunned = 0
-
- var/amt_dizziness = 0
- var/amt_confused = 0
- var/amt_stuttering = 0
-
- //set to negatives for healing unless commented otherwise
- var/amt_dam_fire = 0
- var/amt_dam_brute = 0
- var/amt_dam_oxy = 0
- var/amt_dam_tox = 0
- var/amt_dam_robo = 0
- var/amt_brain = 0
- var/amt_radiation = 0
- var/amt_blood = 0 //Positive numbers to add blood
- var/amt_organ = 0 //Positive numbers for healing
-
- var/amt_eye_blind = 0
- var/amt_eye_blurry = 0
-
- var/effect_state = null //What effect to show on each, if any
- var/effect_duration = 0
- var/effect_color = "#ffffff"
-
- var/list/compatible_mobs = list()
-
-
-/spell/targeted/choose_targets(mob/user = usr)
- var/list/targets = list()
-
- if(max_targets == 0) //unlimited
- if(range == -2)
- targets = global.living_mob_list_
- else
- for(var/mob/living/target in view_or_range(range, holder, selection_type))
- targets += target
-
- else if(max_targets == 1) //single target can be picked
- if((range == 0 || range == -1) && spell_flags & INCLUDEUSER)
- targets += user
- else
- var/list/possible_targets = list()
- var/list/starting_targets
- if(range == -2)
- starting_targets = global.living_mob_list_
- else
- starting_targets = view_or_range(range, holder, selection_type)
-
- for(var/mob/living/M in starting_targets)
- if(!(spell_flags & INCLUDEUSER) && M == user)
- continue
- if(compatible_mobs && compatible_mobs.len)
- if(!is_type_in_list(M, compatible_mobs)) continue
- if(compatible_mobs && compatible_mobs.len && !is_type_in_list(M, compatible_mobs))
- continue
- possible_targets += M
-
- if(possible_targets.len)
- targets += pick(possible_targets)
- //Adds a safety check post-input to make sure those targets are actually in range.
-
-
- else
- var/list/possible_targets = list()
- var/list/starting_targets
-
- if(range == -2)
- starting_targets = global.living_mob_list_
- else
- starting_targets = view_or_range(range, holder, selection_type)
-
- for(var/mob/living/target in starting_targets)
- if(!(spell_flags & INCLUDEUSER) && target == user)
- continue
- if(compatible_mobs && !is_type_in_list(target, compatible_mobs))
- continue
- possible_targets += target
-
- for(var/i=1,i<=max_targets,i++)
- if(!possible_targets.len)
- break
- if(target_ignore_prev)
- var/target = pick(possible_targets)
- possible_targets -= target
- targets += target
- else
- targets += pick(possible_targets)
-
- if(!(spell_flags & INCLUDEUSER) && (user in targets))
- targets -= user
-
- if(compatible_mobs && compatible_mobs.len)
- for(var/mob/living/target in targets) //filters out all the non-compatible mobs
- if(!is_type_in_list(target, compatible_mobs))
- targets -= target
-
- return targets
-
-/spell/targeted/cast(var/list/targets, mob/user)
- for(var/mob/living/target in targets)
- if(range >= 0)
- if(!(target in view_or_range(range, holder, selection_type))) //filter at time of casting
- targets -= target
- continue
- apply_spell_damage(target)
-
-/spell/targeted/proc/apply_spell_damage(mob/living/target)
- target.take_damage(amt_dam_brute, do_update_health = FALSE)
- target.take_damage(amt_dam_fire, BURN, do_update_health = FALSE)
- target.take_damage(amt_dam_tox, TOX, do_update_health = FALSE)
- target.take_damage(amt_dam_oxy, OXY)
- if(ishuman(target))
- var/mob/living/human/H = target
- for(var/obj/item/organ/internal/affecting in H.get_internal_organs())
- if(affecting && istype(affecting))
- affecting.heal_damage(amt_organ, amt_organ)
- for(var/obj/item/organ/external/affecting in H.get_external_organs())
- if(affecting && istype(affecting))
- var/dam = BP_IS_PROSTHETIC(affecting) ? -amt_dam_robo : amt_organ
- affecting.heal_damage(dam, dam, robo_repair = BP_IS_PROSTHETIC(affecting))
- H.adjust_blood(amt_blood)
- H.take_damage(amt_brain, BRAIN)
- H.radiation += min(H.radiation, amt_radiation)
-
- target.update_icon()
- //disabling
- SET_STATUS_MAX(target, STAT_WEAK, amt_weakened)
- SET_STATUS_MAX(target, STAT_PARA, amt_paralysis)
- SET_STATUS_MAX(target, STAT_STUN, amt_stunned)
- if(amt_weakened || amt_paralysis || amt_stunned)
- if(target.buckled)
- target.buckled = null
- ADJ_STATUS(target, STAT_BLIND, amt_eye_blind)
- ADJ_STATUS(target, STAT_BLURRY, amt_eye_blurry)
- ADJ_STATUS(target, STAT_DIZZY, amt_dizziness)
- ADJ_STATUS(target, STAT_CONFUSE, amt_confused)
- ADJ_STATUS(target, STAT_STUTTER, amt_stuttering)
- if(effect_state)
- var/obj/o = new /obj/effect/temporary(get_turf(target), effect_duration, 'icons/effects/effects.dmi', effect_state)
- o.color = effect_color
diff --git a/code/modules/sprite_accessories/metadata/accessory_metadata_gradient.dm b/code/modules/sprite_accessories/metadata/accessory_metadata_gradient.dm
index 8b5d7b48734..d134b6782f8 100644
--- a/code/modules/sprite_accessories/metadata/accessory_metadata_gradient.dm
+++ b/code/modules/sprite_accessories/metadata/accessory_metadata_gradient.dm
@@ -19,8 +19,7 @@
var/list/selectable_labels_to_states = list()
/decl/sprite_accessory_metadata/gradient/Initialize()
- var/list/selectable = icon_states(icon)
- for(var/state in selectable)
+ for(var/state in get_states_in_icon_cached(icon))
if(!selectable_states_to_labels[state])
selectable_states_to_labels[state] = capitalize(state)
for(var/state in selectable_states_to_labels)
diff --git a/code/modules/submaps/submap_job.dm b/code/modules/submaps/submap_job.dm
index 9bc3687a1ae..89d8b2f3871 100644
--- a/code/modules/submaps/submap_job.dm
+++ b/code/modules/submaps/submap_job.dm
@@ -7,7 +7,8 @@
create_record = FALSE
total_positions = 4
outfit_type = /decl/outfit/job/survivor
- hud_icon = "hudblank"
+ hud_icon_state = "hudblank"
+ hud_icon = null
available_by_default = FALSE
allowed_ranks = null
allowed_branches = null
@@ -55,7 +56,12 @@
if(islist(blacklisted_species) && !length(blacklisted_species))
blacklisted_species |= SSmodpacks.default_submap_blacklisted_species
- if(!abstract_job)
+ if(abstract_job)
+ if(!hud_icon)
+ hud_icon = global.using_map.hud_icons
+ if(!hud_icon_state)
+ hud_icon_state = "hud[ckey(title)]"
+ else
spawnpoints = list()
owner = _owner
..()
diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm
index 1b8ef1751a0..be2f0f6b69d 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/necrotic.dm b/code/modules/surgery/necrotic.dm
index 14b39b1f739..6f41080ae0d 100644
--- a/code/modules/surgery/necrotic.dm
+++ b/code/modules/surgery/necrotic.dm
@@ -133,15 +133,15 @@
var/list/dead_organs
if(E.status & ORGAN_DEAD)
var/image/radial_button = image(icon = E.icon, icon_state = E.icon_state)
- radial_button.name = "Regenerate \the [E.name]"
+ radial_button.name = "Regenerate \the [E]"
LAZYSET(dead_organs, E.organ_tag, radial_button)
for(var/obj/item/organ/I in target.get_internal_organs())
if(I && (I.status & ORGAN_DEAD) && I.parent_organ == target_zone)
if(!I.can_recover())
- to_chat(user, SPAN_WARNING("\The [I.name] is beyond saving."))
+ to_chat(user, SPAN_WARNING("\The [I] is beyond saving."))
var/image/radial_button = image(icon = I.icon, icon_state = I.icon_state)
- radial_button.name = "Regenerate \the [I.name]"
+ radial_button.name = "Regenerate \the [I]"
LAZYSET(dead_organs, I.organ_tag, radial_button)
if(!LAZYLEN(dead_organs))
diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm
index f6b9bffb28e..76b37e9eb8d 100644
--- a/code/modules/surgery/organs_internal.dm
+++ b/code/modules/surgery/organs_internal.dm
@@ -104,7 +104,7 @@
for(var/obj/item/organ/I in target.get_internal_organs())
if(I && !(I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
var/image/radial_button = image(icon = I.icon, icon_state = I.icon_state)
- radial_button.name = "Detach \the [I.name]"
+ radial_button.name = "Detach \the [I]"
LAZYSET(attached_organs, I.organ_tag, radial_button)
if(!LAZYLEN(attached_organs))
to_chat(user, SPAN_WARNING("You can't find any organs to separate."))
@@ -158,7 +158,7 @@
for(var/obj/item/organ/internal/I in affected.implants)
if(I.status & ORGAN_CUT_AWAY)
var/image/radial_button = image(icon = I.icon, icon_state = I.icon_state)
- radial_button.name = "Remove \the [I.name]"
+ radial_button.name = "Remove \the [I]"
LAZYSET(removable_organs, I, radial_button)
if(!LAZYLEN(removable_organs))
to_chat(user, SPAN_WARNING("You can't find any removable organs."))
@@ -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)
@@ -336,7 +336,7 @@
for(var/obj/item/organ/I in (affected.implants|affected.internal_organs))
if(I.status & ORGAN_CUT_AWAY)
var/image/radial_button = image(icon = I.icon, icon_state = I.icon_state)
- radial_button.name = "Attach \the [I.name]"
+ radial_button.name = "Attach \the [I]"
LAZYSET(attachable_organs, I, radial_button)
if(!LAZYLEN(attachable_organs))
diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm
index 44020605dee..8695ab98499 100644
--- a/code/modules/surgery/robotics.dm
+++ b/code/modules/surgery/robotics.dm
@@ -416,7 +416,7 @@
for(var/obj/item/organ/I in target.get_internal_organs())
if(I && !(I.status & ORGAN_CUT_AWAY) && !BP_IS_CRYSTAL(I) && I.parent_organ == target_zone)
var/image/radial_button = image(icon = I.icon, icon_state = I.icon_state)
- radial_button.name = "Detach \the [I.name]"
+ radial_button.name = "Detach \the [I]"
LAZYSET(attached_organs, I.organ_tag, radial_button)
if(!LAZYLEN(attached_organs))
to_chat(user, SPAN_WARNING("There are no appropriate internal components to decouple."))
@@ -461,7 +461,7 @@
for(var/obj/item/organ/I in affected.implants)
if ((I.status & ORGAN_CUT_AWAY) && BP_IS_PROSTHETIC(I) && !BP_IS_CRYSTAL(I) && (I.parent_organ == target_zone))
var/image/radial_button = image(icon = I.icon, icon_state = I.icon_state)
- radial_button.name = "Reattach \the [I.name]"
+ radial_button.name = "Reattach \the [I]"
LAZYSET(removable_organs, I.organ_tag, radial_button)
var/organ_to_replace = show_radial_menu(user, tool, removable_organs, radius = 42, require_near = TRUE, use_labels = RADIAL_LABELS_OFFSET, check_locs = list(tool))
if(!organ_to_replace)
diff --git a/code/modules/tools/archetypes/tool_archetype_definitions.dm b/code/modules/tools/archetypes/tool_archetype_definitions.dm
index 25df48e3afd..2b2b2f14f4d 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/components/head.dm b/code/modules/tools/components/head.dm
index 5d7aa85f512..e8e408c7c76 100644
--- a/code/modules/tools/components/head.dm
+++ b/code/modules/tools/components/head.dm
@@ -40,6 +40,11 @@ var/global/list/_tool_properties_cache = list()
desc = "The head of a hoe."
icon_state = "hoe"
+/obj/item/tool_component/head/chisel
+ name = "chisel head"
+ desc = "The head of a chisel."
+ icon_state = "hoe"
+
/obj/item/tool_component/head/handaxe
name = "hand axe head"
desc = "The head of a hand axe."
@@ -58,3 +63,8 @@ var/global/list/_tool_properties_cache = list()
icon_state = "sledgehammer"
w_class = ITEM_SIZE_NORMAL
+/obj/item/tool_component/head/forging_hammer
+ name = "forging hammer head"
+ desc = "The head of a forging hammer."
+ icon_state = "forging"
+ w_class = ITEM_SIZE_NORMAL
diff --git a/code/modules/tools/subtypes/axes.dm b/code/modules/tools/subtypes/axes.dm
index 94e14da6274..d671ffa0747 100644
--- a/code/modules/tools/subtypes/axes.dm
+++ b/code/modules/tools/subtypes/axes.dm
@@ -19,8 +19,12 @@
return tool_qualities
/obj/item/tool/axe/ebony
+ material = /decl/material/solid/metal/iron
handle_material = /decl/material/solid/organic/wood/ebony
+/obj/item/tool/axe/iron
+ material = /decl/material/solid/metal/iron
+
/obj/item/tool/axe/ebony/bronze
material = /decl/material/solid/metal/bronze
diff --git a/code/modules/tools/subtypes/hammers.dm b/code/modules/tools/subtypes/hammers.dm
index bb1c9ee58cd..ff5d1ef1989 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",
@@ -79,3 +77,18 @@
TOOL_SHOVEL = TOOL_QUALITY_DECENT
)
return tool_qualities
+
+/obj/item/tool/hammer/forge
+ name = "forging hammer"
+ desc = "A heavy hammer, used to forge hot metal at an anvil."
+ icon = 'icons/obj/items/tool/hammers/forge.dmi'
+ w_class = ITEM_SIZE_NORMAL
+
+// Forging hammers are not great at general hammer tasks (too heavy I guess),
+// and also don't work as crowbars due to missing the nail ripper/flange,
+// but will be more effective at forging when blacksmithy is merged.
+/obj/item/tool/hammer/forge/get_initial_tool_qualities()
+ var/static/list/tool_qualities = list(
+ TOOL_HAMMER = TOOL_QUALITY_MEDIOCRE
+ )
+ return tool_qualities
diff --git a/code/modules/tools/subtypes/xenoarchaeology_picks.dm b/code/modules/tools/subtypes/xenoarchaeology_picks.dm
index 9db2d59f541..2a335b9fa4c 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 889d2ab199d..953a751ebbb 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 edfc8efaba4..1098bd2bf01 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/weather/weather_fsm_states.dm b/code/modules/weather/weather_fsm_states.dm
index 029f500f16f..08c45c46c3e 100644
--- a/code/modules/weather/weather_fsm_states.dm
+++ b/code/modules/weather/weather_fsm_states.dm
@@ -248,7 +248,8 @@
/decl/state/weather/rain/hail/handle_exposure_effects(var/mob/living/M, var/obj/abstract/weather_system/weather)
to_chat(M, SPAN_DANGER("You are pelted by a shower of hail!"))
- M.take_damage(rand(1, 3))
+ if(M.getBruteLoss() < 20) // Put a cap on it to make it annoying but not lethal.
+ M.take_damage(rand(1, 3))
/decl/state/weather/ash
name = "Ash"
diff --git a/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm b/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm
index cc79f4bf2b5..abd7dc61c3b 100644
--- a/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm
+++ b/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm
@@ -1,7 +1,7 @@
/obj/machinery/giga_drill
name = "alien drill"
desc = "A giant, alien drill mounted on long treads."
- icon = 'icons/obj/mining.dmi'
+ icon = 'icons/obj/machines/gigadrill.dmi'
icon_state = "gigadrill"
var/active = 0
var/drill_time = 10
diff --git a/code/modules/xenoarcheaology/artifacts/triggers/force.dm b/code/modules/xenoarcheaology/artifacts/triggers/force.dm
index c8003f314e7..97a771745f1 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/boulder.dm b/code/modules/xenoarcheaology/boulder.dm
index ad492eb65ef..ba7a38c2f3d 100644
--- a/code/modules/xenoarcheaology/boulder.dm
+++ b/code/modules/xenoarcheaology/boulder.dm
@@ -1,8 +1,8 @@
/obj/structure/boulder
name = "boulder"
desc = "A large boulder, somewhat bigger than a small boulder."
- icon = 'icons/obj/mining.dmi'
- icon_state = "boulder1"
+ icon = 'icons/obj/structures/boulder.dmi'
+ icon_state = ICON_STATE_WORLD
density = TRUE
opacity = TRUE
anchored = TRUE
@@ -30,7 +30,7 @@
/obj/structure/boulder/Initialize(var/ml, var/_mat, var/coloration)
. = ..()
- icon_state = "boulder[rand(1,6)]"
+ icon_state = "[initial(icon_state)][rand(1,6)]"
if(coloration)
color = coloration
excavation_level = rand(5, 50)
diff --git a/code/modules/xenoarcheaology/datums/artifact_find.dm b/code/modules/xenoarcheaology/datums/artifact_find.dm
index b70f17112e8..242af56502d 100644
--- a/code/modules/xenoarcheaology/datums/artifact_find.dm
+++ b/code/modules/xenoarcheaology/datums/artifact_find.dm
@@ -2,8 +2,6 @@
var/artifact_id
var/artifact_find_type
var/static/potential_finds = list(
- /obj/machinery/power/supermatter = 5,
- /obj/machinery/power/supermatter/shard = 25,
/obj/machinery/auto_cloner = 100,
/obj/machinery/giga_drill = 100,
/obj/machinery/replicator = 100,
diff --git a/code/modules/xenoarcheaology/tools/core_sampler.dm b/code/modules/xenoarcheaology/tools/core_sampler.dm
index 01b4f1401e5..21d5bd0cb6d 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/modules/xenoarcheaology/tools/tools.dm b/code/modules/xenoarcheaology/tools/tools.dm
index 213d77ff128..813f424e7f1 100644
--- a/code/modules/xenoarcheaology/tools/tools.dm
+++ b/code/modules/xenoarcheaology/tools/tools.dm
@@ -10,8 +10,8 @@
/obj/item/bag/fossils
name = "fossil satchel"
desc = "Transports delicate fossils in suspension so they don't break during transit."
- icon = 'icons/obj/mining.dmi'
- icon_state = "satchel"
+ icon = 'icons/obj/items/mining_satchel.dmi'
+ icon_state = ICON_STATE_WORLD
slot_flags = SLOT_LOWER_BODY | SLOT_POCKET
w_class = ITEM_SIZE_NORMAL
storage = /datum/storage/bag/fossils
diff --git a/code/unit_tests/_template.dm b/code/unit_tests/_template.dm
index 556941cb1ce..36dc0ddfa18 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/alt_appearances_test.dm b/code/unit_tests/alt_appearances_test.dm
index 1bfd0ed325e..d1c4b22a8e8 100644
--- a/code/unit_tests/alt_appearances_test.dm
+++ b/code/unit_tests/alt_appearances_test.dm
@@ -20,9 +20,8 @@
for(var/ca_type in decls_repository.get_decl_paths_of_subtype(/decl/cardborg_appearance))
var/decl/cardborg_appearance/ca = ca_type
- var/list/existing_icon_states = icon_states(initial(ca.icon))
var/icon_state = initial(ca.icon_state)
- if(!(icon_state in existing_icon_states))
+ if(!check_state_in_icon(icon_state, initial(ca.icon)))
log_unit_test("Icon state [icon_state] is missing.")
failed = TRUE
if(failed)
diff --git a/code/unit_tests/atmospherics_tests.dm b/code/unit_tests/atmospherics_tests.dm
index 5a9c69c15cf..46837d818bf 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 bb6e9d90477..cdc9dae00d4 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/closets.dm b/code/unit_tests/closets.dm
index 9bc236f8ff9..10688fd7231 100644
--- a/code/unit_tests/closets.dm
+++ b/code/unit_tests/closets.dm
@@ -29,18 +29,18 @@
if(!closet.base_icon)
LAZYADD(bad_base_icon, "[closet.type]")
else
- var/list/base_states = icon_states(closet.base_icon)
+ var/list/base_states = get_states_in_icon_cached(closet.base_icon)
for(var/thing in check_base_states)
- if(!(thing in base_states))
+ if(!base_states[thing])
LAZYADD(bad_base_state, "[closet.type] - [thing] - [closet.base_icon]")
if(LAZYLEN(closet.decals) && !closet.decal_icon)
LAZYADD(bad_decal_icon, "[closet.type]")
else
- var/list/decal_states = icon_states(closet.decal_icon)
+ var/list/decal_states = get_states_in_icon_cached(closet.decal_icon)
for(var/thing in closet.decals)
if(isnull(closet.decals[thing]))
LAZYADD(bad_decal_colour, "[check_appearance] - [thing]")
- if(!(thing in decal_states))
+ if(!decal_states[thing])
LAZYADD(bad_decal_state, "[check_appearance] - [thing] - [closet.decal_icon]")
if( \
diff --git a/code/unit_tests/clothing.dm b/code/unit_tests/clothing.dm
index 2b3889695c3..8219e6d0418 100644
--- a/code/unit_tests/clothing.dm
+++ b/code/unit_tests/clothing.dm
@@ -99,7 +99,7 @@
generated_tokens += "[token][clothes.markings_state_modifier]"
// Keep track of which states we've looked for or otherwise evaluated for later state checking.
- var/list/check_states = icon_states(clothes.icon)
+ var/list/check_states = get_states_in_icon(clothes.icon)
// Validate against the list of generated tokens.
for(var/gen_token in generated_tokens)
diff --git a/code/unit_tests/del_the_world.dm b/code/unit_tests/del_the_world.dm
index 3a9c575e699..411ef21b8d3 100644
--- a/code/unit_tests/del_the_world.dm
+++ b/code/unit_tests/del_the_world.dm
@@ -7,15 +7,6 @@
var/turf/spawn_loc = get_safe_turf()
var/list/cached_contents = spawn_loc.contents.Copy()
- /// Types to except from GC checking tests.
- var/list/gc_exceptions = list(
- // I hate doing this, but until the graph tests are fixed by someone who actually understands them,
- // this is the best I can do without breaking other stuff.
- /datum/node/physical,
- // Randomly fails to GC during CI, cause unclear. Remove this if the root cause is identified.
- /obj/item/organ/external/chest
- )
-
var/list/ignore = typesof(
// will error if the area already has one
/obj/machinery/power/apc,
@@ -48,57 +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/oldest_item = filter_queue[1]
- var/qdel_time = filter_queue[oldest_item]
- 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/oldest_packet = check_queue[1]
- //Pull out the time we deld at
- var/qdeld_at = check_queue[oldest_packet]
//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
@@ -109,8 +95,6 @@
//Alright, time to see if anything messed up
var/list/cache_for_sonic_speed = SSgarbage.items
for(var/path in cache_for_sonic_speed)
- if(path in gc_exceptions)
- continue
var/datum/qdel_item/item = cache_for_sonic_speed[path]
if(item.failures)
failures += "[item.name] hard deleted [item.failures] times out of a total del count of [item.qdels]"
diff --git a/code/unit_tests/equipment_tests.dm b/code/unit_tests/equipment_tests.dm
index 558debe8c65..dac446856e8 100644
--- a/code/unit_tests/equipment_tests.dm
+++ b/code/unit_tests/equipment_tests.dm
@@ -1,41 +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"])
- return H?.equip_to_slot(new glasses_type(H), slot_glasses_str, TRUE, TRUE)
+ 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 49f9769fa43..2a7724e3cc7 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 66fb31643b3..27196ec37ff 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 66a939e3a8f..47cdb388f62 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
@@ -480,7 +480,7 @@
/atom/movable/graph_test
is_spawnable_type = FALSE
var/datum/node/physical/node
- var/list/neighoursByDirection = list()
+ var/list/neighboursByDirection = list()
/atom/movable/graph_test/Initialize()
. = ..()
@@ -489,6 +489,7 @@
/atom/movable/graph_test/Destroy()
QDEL_NULL(node)
+ neighboursByDirection.Cut()
return ..()
/atom/movable/graph_test/forceMove()
@@ -497,20 +498,21 @@
/atom/movable/graph_test/proc/Connect(atom/movable/graph_test/neighbour)
var/direction = get_dir(src, neighbour)
- neighoursByDirection[num2text(direction)] = neighbour
- neighbour.neighoursByDirection[num2text(global.flip_dir[direction])] = src
+ neighboursByDirection[num2text(direction)] = neighbour
+ neighbour.neighboursByDirection[num2text(global.flip_dir[direction])] = src
node.Connect(neighbour.node)
/atom/movable/graph_test/CheckNodeNeighbours()
// This is a lazy setup for ease of debugging
// In a practical setup you'd preferably gather a list of neighbours to be disconnected and pass them in a single Disconnect-call
// You'd possibly also verify the dir of this and neighbour nodes, to ensure that they're still facing each other properly
- for(var/direction in neighoursByDirection)
- var/atom/movable/graph_test/neighbour = neighoursByDirection[direction]
+ for(var/direction in neighboursByDirection)
+ var/atom/movable/graph_test/neighbour = neighboursByDirection[direction]
var/turf/expected_loc = get_step(src, text2num(direction))
- if(neighbour.loc != expected_loc)
+ // can't connect in nullspace
+ if(isnull(neighbour.loc) || neighbour.loc != expected_loc)
node.Disconnect(neighbour.node)
- neighoursByDirection -= direction
+ neighboursByDirection -= direction
return TRUE
/datum/graph/testing
@@ -523,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()
@@ -557,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)
@@ -575,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 8a25e15a29e..279daba8a34 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"
@@ -12,11 +12,14 @@
// We skip lumps because they are invisible, they are only ever inside utensils.
var/list/skip_types = list(/obj/item/food/lump)
-/datum/unit_test/icon_test/food_shall_have_icon_states/start_test()
-
+/datum/unit_test/icon_test/food_shall_have_icon_states/proc/assemble_skipped_types()
skip_types |= typesof(/obj/item/food/grown)
skip_types |= typesof(/obj/item/food/processed_grown)
+/datum/unit_test/icon_test/food_shall_have_icon_states/start_test()
+
+ assemble_skipped_types()
+
var/list/failures = list()
for(var/check_type in check_types)
for(var/check_subtype in typesof(check_type))
@@ -296,3 +299,64 @@
else
pass("All vendors have all icons and icon states.")
return 1
+
+
+/datum/unit_test/HUDS_shall_have_icon_states
+ name = "ICON STATE: HUD overlays shall have appropriate icon_states"
+
+/datum/unit_test/HUDS_shall_have_icon_states/start_test()
+ var/failed_jobs = 0
+ var/failed_sanity_checks = 0
+
+ // Throwing implants and health HUDs in here.
+ // Antag HUDs are tested by special role validation.
+
+ var/static/list/implant_hud_states = list(
+ "hud_imp_blank" = "Blank",
+ "hud_imp_loyal" = "Loyalty",
+ "hud_imp_unknown" = "Unknown",
+ "hud_imp_tracking" = "Tracking",
+ "hud_imp_chem" = "Chemical",
+ )
+ for(var/implant_hud_state in implant_hud_states)
+ if(!check_state_in_icon(implant_hud_state, global.using_map.implant_hud_icons))
+ log_bad("Sanity Check - Missing map [implant_hud_states[implant_hud_state]] implant HUD icon_state '[implant_hud_state]' from icon [global.using_map.implant_hud_icons]")
+ failed_sanity_checks++
+
+ var/static/list/med_hud_states = list(
+ "blank" = "Blank",
+ "flatline" = "Flatline",
+ "0" = "Dead",
+ "1" = "Healthy",
+ "2" = "Lightly injured",
+ "3" = "Moderately injured",
+ "4" = "Severely injured",
+ "5" = "Dying",
+ )
+ for(var/med_hud_state in med_hud_states)
+ if(!check_state_in_icon(med_hud_state, global.using_map.med_hud_icons))
+ log_bad("Sanity Check - Missing map [med_hud_states[med_hud_state]] medical HUD icon_state '[med_hud_state]' from icon [global.using_map.med_hud_icons]")
+ failed_sanity_checks++
+ var/static/list/global_states = list(
+ "" = "Default/unnamed",
+ "hudunknown" = "Unknown role",
+ "hudhealthy" = "Healthy mob",
+ "hudill" = "Diseased mob",
+ "huddead" = "Dead mob"
+ )
+ for(var/global_state in global_states)
+ if(!check_state_in_icon(global_state, global.using_map.hud_icons))
+ log_bad("Sanity Check - Missing map [global_states[global_state]] HUD icon_state '[global_state]' from icon [global.using_map.hud_icons]")
+ failed_sanity_checks++
+
+ for(var/job_name in SSjobs.titles_to_datums)
+ var/datum/job/job = SSjobs.titles_to_datums[job_name]
+ if(!check_state_in_icon(job.hud_icon_state, job.hud_icon))
+ log_bad("[job.title] - Missing HUD icon: [job.hud_icon_state] in icon [job.hud_icon]")
+ failed_jobs++
+
+ if(failed_sanity_checks || failed_jobs)
+ fail("[global.using_map.type] - [failed_sanity_checks] failed sanity check\s, [failed_jobs] job\s with missing HUD icon.")
+ else
+ pass("All jobs have a HUD icon.")
+ return 1
diff --git a/code/unit_tests/integrated_circuits.dm b/code/unit_tests/integrated_circuits.dm
index 79c26d52a3a..84de2ac2ff3 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/job_tests.dm b/code/unit_tests/job_tests.dm
index b1295165734..b6b652731f8 100644
--- a/code/unit_tests/job_tests.dm
+++ b/code/unit_tests/job_tests.dm
@@ -35,36 +35,6 @@
pass("All jobs had outfit types.")
return 1
-/datum/unit_test/jobs_shall_have_a_HUD_icon
- name = "JOB: Shall have a HUD icon"
-
-/datum/unit_test/jobs_shall_have_a_HUD_icon/start_test()
- var/failed_jobs = 0
- var/failed_sanity_checks = 0
-
- var/job_huds = icon_states(global.using_map.id_hud_icons)
-
- if(!("" in job_huds))
- log_bad("Sanity Check - Missing default/unnamed HUD icon")
- failed_sanity_checks++
-
- if(!("hudunknown" in job_huds))
- log_bad("Sanity Check - Missing HUD icon: hudunknown")
- failed_sanity_checks++
-
- for(var/job_name in SSjobs.titles_to_datums)
- var/datum/job/J = SSjobs.titles_to_datums[job_name]
- var/hud_icon_state = J.hud_icon
- if(!(hud_icon_state in job_huds))
- log_bad("[J.title] - Missing HUD icon: [hud_icon_state]")
- failed_jobs++
-
- if(failed_sanity_checks || failed_jobs)
- fail("[global.using_map.id_hud_icons] - [failed_sanity_checks] failed sanity check\s, [failed_jobs] job\s with missing HUD icon.")
- else
- pass("All jobs have a HUD icon.")
- return 1
-
/datum/unit_test/jobs_shall_have_a_unique_title
name = "JOBS: All Job Datums Shall Have A Unique Title"
diff --git a/code/unit_tests/map_tests.dm b/code/unit_tests/map_tests.dm
index 2803ba8db09..89238fa88d2 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 5867dd2ca90..2f03eb9da32 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
@@ -260,15 +248,15 @@ var/global/default_mobloc = null
fail("[icon_file] is not a valid icon file.")
return 1
- var/list/valid_states = icon_states(icon_file)
+ var/list/valid_states = get_states_in_icon_cached(icon_file)
- if(!valid_states.len)
+ if(!length(valid_states))
return 1
for(var/i=1, i<=SSrobots.all_module_names.len, i++)
var/modname = lowertext(SSrobots.all_module_names[i])
var/bad_msg = "[ascii_red]--------------- [modname]"
- if(!(modname in valid_states))
+ if(!valid_states[modname])
log_unit_test("[bad_msg] does not contain a valid icon state in [icon_file][ascii_reset]")
failed=1
diff --git a/code/unit_tests/movement_tests.dm b/code/unit_tests/movement_tests.dm
index 8d45dbe20cf..dbcb2bc4499 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 b9174d26fe8..829bc743576 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 2c8d6bc47cc..4687b0c72aa 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 b77946ec739..b405a2c3db2 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 2dbf636d1e9..55a17518a60 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/turf_icons.dm b/code/unit_tests/turf_icons.dm
index 5cf5cb9dce7..3319864ee2a 100644
--- a/code/unit_tests/turf_icons.dm
+++ b/code/unit_tests/turf_icons.dm
@@ -8,8 +8,7 @@
/turf/unsimulated
)
var/list/excepted_types = list(
- /turf/unsimulated/map,
- /turf/unsimulated/wall/cascade
+ /turf/unsimulated/map
)
/datum/unit_test/turf_floor_icons_shall_be_valid/setup_test()
diff --git a/code/unit_tests/unit_test.dm b/code/unit_tests/unit_test.dm
index 4fe4fedfdc5..24fd800c854 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 dab89f395ec..718bf010748 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 b83f880bff9..7866c78bd62 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/unit_tests/~unit_test_subsystems.dm b/code/unit_tests/~unit_test_subsystems.dm
index 23d8aab1d0b..eea8a75f692 100644
--- a/code/unit_tests/~unit_test_subsystems.dm
+++ b/code/unit_tests/~unit_test_subsystems.dm
@@ -31,6 +31,12 @@ SUBSYSTEM_DEF(unit_tests)
#endif
log_unit_test("Initializing Unit Testing")
+ // Misc validation.
+ if(istype(global.using_map))
+ global.using_map.validate()
+ else
+ log_error("global.using_map is null or invalid!")
+
//
//Start the Round.
//
diff --git a/code/world.dm b/code/world.dm
index 361fa6c4a15..057199cfb0a 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 1b80c1d0545..8e46ecdab25 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -52,6 +52,45 @@
-->
+ 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:
+
+ - The White and Minimalist HUD styles can now be customised to use a specific overlay color.
+ - The Shaded Hills river now flows north.
+ - Snow, mud and sand will now show footprints.
+
+
+ 15 January 2025
+ MistakeNot4892 updated:
+
+ - The way you interact with barrels and well has been significantly reworked; clicking with a bucket or tool should give a list of options to pick from. Please report bugs with this on the tracker.
+
+
+ 08 January 2025
+ MistakeNot4892 updated:
+
+ - Mud and blood can now leave footprints.
+
+
03 January 2025
MistakeNot4892 updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 894f308ccdb..20e1bd55f28 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -14945,3 +14945,29 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
MistakeNot4892:
- tweak: Raw plant oil no longer works as lantern fuel; it must be mixed with powdered
graphite first.
+2025-01-08:
+ MistakeNot4892:
+ - tweak: Mud and blood can now leave footprints.
+2025-01-15:
+ MistakeNot4892:
+ - tweak: The way you interact with barrels and well has been significantly reworked;
+ clicking with a bucket or tool should give a list of options to pick from. Please
+ report bugs with this on the tracker.
+2025-01-16:
+ MistakeNot4892:
+ - tweak: The White and Minimalist HUD styles can now be customised to use a specific
+ overlay color.
+ - tweak: The Shaded Hills river now flows north.
+ - tweak: Snow, mud and sand will now show footprints.
+2025-01-19:
+ MistakeNot4892:
+ - tweak: Intents have been rewritten and moved, please report any issues with intent
+ selection.
+2025-01-21:
+ Penelope Haze:
+ - tweak: Mud can now receive footprints with any reagent other than mud. No more
+ conspicuously missing bloody footprints!
+2025-01-22:
+ MistakeNot4892:
+ - tweak: Swords on Shaded Hills can be sharpened using whetstones or grindstones.
+ - tweak: Guns can now be fired from rigs regardless of dexterity.
diff --git a/html/changelogs/AutoChangeLog-pr-4695.yml b/html/changelogs/AutoChangeLog-pr-4695.yml
deleted file mode 100644
index 84dde3ff37c..00000000000
--- a/html/changelogs/AutoChangeLog-pr-4695.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: MistakeNot4892
-changes:
- - {tweak: Mud and blood can now leave footprints.}
-delete-after: true
diff --git a/icons/clothing/spacesuit/void/medical_alt/suit.dmi b/icons/clothing/spacesuit/void/medical_alt/suit.dmi
index 77b79193e46..634b6742079 100644
Binary files a/icons/clothing/spacesuit/void/medical_alt/suit.dmi and b/icons/clothing/spacesuit/void/medical_alt/suit.dmi differ
diff --git a/icons/effects/crayondecal.dmi b/icons/effects/crayondecal.dmi
index e1966e9bb5a..3642e8ed8f4 100644
Binary files a/icons/effects/crayondecal.dmi and b/icons/effects/crayondecal.dmi differ
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 78c4315424a..5502343f0d5 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/effects/landmarks.dmi b/icons/effects/landmarks.dmi
index 7c5729455bf..28317726409 100644
Binary files a/icons/effects/landmarks.dmi and b/icons/effects/landmarks.dmi differ
diff --git a/icons/effects/liquids.dmi b/icons/effects/liquids.dmi
index 965e319bc4a..7cdf5d1b006 100644
Binary files a/icons/effects/liquids.dmi and b/icons/effects/liquids.dmi differ
diff --git a/icons/effects/projectiles/trail.dmi b/icons/effects/projectiles/trail.dmi
new file mode 100644
index 00000000000..4e058a3f1bf
Binary files /dev/null and b/icons/effects/projectiles/trail.dmi differ
diff --git a/icons/mob/footprints/footprints.dmi b/icons/mob/footprints/footprints.dmi
new file mode 100644
index 00000000000..2d9699e82c8
Binary files /dev/null and b/icons/mob/footprints/footprints.dmi differ
diff --git a/icons/mob/footprints/footprints_paw.dmi b/icons/mob/footprints/footprints_paw.dmi
new file mode 100644
index 00000000000..08fac62a016
Binary files /dev/null and b/icons/mob/footprints/footprints_paw.dmi differ
diff --git a/icons/mob/footprints/footprints_snake.dmi b/icons/mob/footprints/footprints_snake.dmi
new file mode 100644
index 00000000000..6e913803eb1
Binary files /dev/null and b/icons/mob/footprints/footprints_snake.dmi differ
diff --git a/icons/mob/footprints/footprints_trail.dmi b/icons/mob/footprints/footprints_trail.dmi
new file mode 100644
index 00000000000..944ed4e175b
Binary files /dev/null and b/icons/mob/footprints/footprints_trail.dmi differ
diff --git a/icons/mob/footprints/footprints_wheelchair.dmi b/icons/mob/footprints/footprints_wheelchair.dmi
new file mode 100644
index 00000000000..4a2e800cf76
Binary files /dev/null and b/icons/mob/footprints/footprints_wheelchair.dmi differ
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
deleted file mode 100644
index ed608471041..00000000000
Binary files a/icons/mob/hud.dmi and /dev/null differ
diff --git a/icons/mob/hud_med.dmi b/icons/mob/hud_med.dmi
deleted file mode 100644
index 705886a5490..00000000000
Binary files a/icons/mob/hud_med.dmi and /dev/null differ
diff --git a/icons/mob/screen/abilities.dmi b/icons/mob/screen/abilities.dmi
new file mode 100644
index 00000000000..ca7d904bd71
Binary files /dev/null and b/icons/mob/screen/abilities.dmi differ
diff --git a/icons/mob/screen/ability_inhand.dmi b/icons/mob/screen/ability_inhand.dmi
new file mode 100644
index 00000000000..63e1b630dc0
Binary files /dev/null and b/icons/mob/screen/ability_inhand.dmi differ
diff --git a/icons/mob/screen/phenomena.dmi b/icons/mob/screen/phenomena.dmi
deleted file mode 100644
index f1d05fa9730..00000000000
Binary files a/icons/mob/screen/phenomena.dmi and /dev/null differ
diff --git a/icons/mob/screen/spells.dmi b/icons/mob/screen/spells.dmi
deleted file mode 100644
index d574921544d..00000000000
Binary files a/icons/mob/screen/spells.dmi and /dev/null differ
diff --git a/icons/mob/screen/styles/intents.dmi b/icons/mob/screen/styles/intents.dmi
deleted file mode 100644
index 3b0b33f8490..00000000000
Binary files a/icons/mob/screen/styles/intents.dmi and /dev/null differ
diff --git a/icons/mob/screen/styles/intents_wide.dmi b/icons/mob/screen/styles/intents_wide.dmi
deleted file mode 100644
index fc26d305f6b..00000000000
Binary files a/icons/mob/screen/styles/intents_wide.dmi and /dev/null differ
diff --git a/icons/mob/screen/styles/minimalist/attack_selector.dmi b/icons/mob/screen/styles/minimalist/attack_selector.dmi
index c5a7e57c522..2e3d66fd059 100644
Binary files a/icons/mob/screen/styles/minimalist/attack_selector.dmi and b/icons/mob/screen/styles/minimalist/attack_selector.dmi differ
diff --git a/icons/mob/screen/styles/minimalist/fire_intent.dmi b/icons/mob/screen/styles/minimalist/fire_intent.dmi
index 62efd8ca867..02a311ec4e8 100644
Binary files a/icons/mob/screen/styles/minimalist/fire_intent.dmi and b/icons/mob/screen/styles/minimalist/fire_intent.dmi differ
diff --git a/icons/mob/screen/styles/minimalist/hands.dmi b/icons/mob/screen/styles/minimalist/hands.dmi
index 28264b0635f..05840e72af8 100644
Binary files a/icons/mob/screen/styles/minimalist/hands.dmi and b/icons/mob/screen/styles/minimalist/hands.dmi differ
diff --git a/icons/mob/screen/styles/minimalist/interaction.dmi b/icons/mob/screen/styles/minimalist/interaction.dmi
index 8a4875e964f..b8c4a0b80fe 100644
Binary files a/icons/mob/screen/styles/minimalist/interaction.dmi and b/icons/mob/screen/styles/minimalist/interaction.dmi differ
diff --git a/icons/mob/screen/styles/minimalist/inventory.dmi b/icons/mob/screen/styles/minimalist/inventory.dmi
index d2d055fe753..169c66eefdd 100644
Binary files a/icons/mob/screen/styles/minimalist/inventory.dmi and b/icons/mob/screen/styles/minimalist/inventory.dmi differ
diff --git a/icons/mob/screen/styles/minimalist/movement.dmi b/icons/mob/screen/styles/minimalist/movement.dmi
index 3a3115d5b88..fa354873156 100644
Binary files a/icons/mob/screen/styles/minimalist/movement.dmi and b/icons/mob/screen/styles/minimalist/movement.dmi differ
diff --git a/icons/mob/screen/styles/minimalist/uphint.dmi b/icons/mob/screen/styles/minimalist/uphint.dmi
index fc54e68b933..412cab2b32d 100644
Binary files a/icons/mob/screen/styles/minimalist/uphint.dmi and b/icons/mob/screen/styles/minimalist/uphint.dmi differ
diff --git a/icons/mob/screen/styles/minimalist/zone_selector.dmi b/icons/mob/screen/styles/minimalist/zone_selector.dmi
index 9a35a9acd27..2cdd0893f6a 100644
Binary files a/icons/mob/screen/styles/minimalist/zone_selector.dmi and b/icons/mob/screen/styles/minimalist/zone_selector.dmi differ
diff --git a/icons/mob/screen/styles/underworld/attack_selector.dmi b/icons/mob/screen/styles/underworld/attack_selector.dmi
new file mode 100644
index 00000000000..2df7a24c30d
Binary files /dev/null and b/icons/mob/screen/styles/underworld/attack_selector.dmi differ
diff --git a/icons/mob/screen/styles/underworld/fire_intent.dmi b/icons/mob/screen/styles/underworld/fire_intent.dmi
new file mode 100644
index 00000000000..1f7c93487fd
Binary files /dev/null and b/icons/mob/screen/styles/underworld/fire_intent.dmi differ
diff --git a/icons/mob/screen/styles/underworld/hands.dmi b/icons/mob/screen/styles/underworld/hands.dmi
new file mode 100644
index 00000000000..fd37369cc08
Binary files /dev/null and b/icons/mob/screen/styles/underworld/hands.dmi differ
diff --git a/icons/mob/screen/styles/underworld/interaction.dmi b/icons/mob/screen/styles/underworld/interaction.dmi
new file mode 100644
index 00000000000..ce806127f53
Binary files /dev/null and b/icons/mob/screen/styles/underworld/interaction.dmi differ
diff --git a/icons/mob/screen/styles/underworld/inventory.dmi b/icons/mob/screen/styles/underworld/inventory.dmi
new file mode 100644
index 00000000000..b576bd3b4df
Binary files /dev/null and b/icons/mob/screen/styles/underworld/inventory.dmi differ
diff --git a/icons/mob/screen/styles/underworld/movement.dmi b/icons/mob/screen/styles/underworld/movement.dmi
new file mode 100644
index 00000000000..6890efd9fa4
Binary files /dev/null and b/icons/mob/screen/styles/underworld/movement.dmi differ
diff --git a/icons/mob/screen/styles/underworld/uphint.dmi b/icons/mob/screen/styles/underworld/uphint.dmi
new file mode 100644
index 00000000000..4d78c55da72
Binary files /dev/null and b/icons/mob/screen/styles/underworld/uphint.dmi differ
diff --git a/icons/mob/screen/styles/underworld/zone_selector.dmi b/icons/mob/screen/styles/underworld/zone_selector.dmi
new file mode 100644
index 00000000000..e482039b230
Binary files /dev/null and b/icons/mob/screen/styles/underworld/zone_selector.dmi differ
diff --git a/icons/mob/screen/styles/white/attack_selector.dmi b/icons/mob/screen/styles/white/attack_selector.dmi
index 6aa6118a743..02f97413e1a 100644
Binary files a/icons/mob/screen/styles/white/attack_selector.dmi and b/icons/mob/screen/styles/white/attack_selector.dmi differ
diff --git a/icons/mob/screen/styles/white/fire_intent.dmi b/icons/mob/screen/styles/white/fire_intent.dmi
index 5ab217edcd5..64af8d1e078 100644
Binary files a/icons/mob/screen/styles/white/fire_intent.dmi and b/icons/mob/screen/styles/white/fire_intent.dmi differ
diff --git a/icons/mob/screen/styles/white/hands.dmi b/icons/mob/screen/styles/white/hands.dmi
index 59702d43b99..0f65b990467 100644
Binary files a/icons/mob/screen/styles/white/hands.dmi and b/icons/mob/screen/styles/white/hands.dmi differ
diff --git a/icons/mob/screen/styles/white/interaction.dmi b/icons/mob/screen/styles/white/interaction.dmi
index e11d10d2c13..8511d73937a 100644
Binary files a/icons/mob/screen/styles/white/interaction.dmi and b/icons/mob/screen/styles/white/interaction.dmi differ
diff --git a/icons/mob/screen/styles/white/inventory.dmi b/icons/mob/screen/styles/white/inventory.dmi
index 0ce80198e6b..f8cfa9cbbc5 100644
Binary files a/icons/mob/screen/styles/white/inventory.dmi and b/icons/mob/screen/styles/white/inventory.dmi differ
diff --git a/icons/mob/screen/styles/white/movement.dmi b/icons/mob/screen/styles/white/movement.dmi
index 17faaf9413d..b3a61c63a9b 100644
Binary files a/icons/mob/screen/styles/white/movement.dmi and b/icons/mob/screen/styles/white/movement.dmi differ
diff --git a/icons/mob/screen/styles/white/uphint.dmi b/icons/mob/screen/styles/white/uphint.dmi
index d3e9075d704..ee795947c30 100644
Binary files a/icons/mob/screen/styles/white/uphint.dmi and b/icons/mob/screen/styles/white/uphint.dmi differ
diff --git a/icons/mob/screen/styles/white/zone_selector.dmi b/icons/mob/screen/styles/white/zone_selector.dmi
index fe86e824f98..1e768fdd53d 100644
Binary files a/icons/mob/screen/styles/white/zone_selector.dmi and b/icons/mob/screen/styles/white/zone_selector.dmi differ
diff --git a/icons/obj/items/chain.dmi b/icons/obj/items/chain.dmi
new file mode 100644
index 00000000000..95d5c71b70f
Binary files /dev/null and b/icons/obj/items/chain.dmi differ
diff --git a/icons/obj/items/hook.dmi b/icons/obj/items/hook.dmi
new file mode 100644
index 00000000000..602683208c7
Binary files /dev/null and b/icons/obj/items/hook.dmi differ
diff --git a/icons/obj/items/horseshoe.dmi b/icons/obj/items/horseshoe.dmi
new file mode 100644
index 00000000000..15f6f5f2482
Binary files /dev/null and b/icons/obj/items/horseshoe.dmi differ
diff --git a/icons/obj/items/mining_satchel.dmi b/icons/obj/items/mining_satchel.dmi
new file mode 100644
index 00000000000..64d0ded9257
Binary files /dev/null and b/icons/obj/items/mining_satchel.dmi differ
diff --git a/icons/obj/items/sheet_snatcher.dmi b/icons/obj/items/sheet_snatcher.dmi
new file mode 100644
index 00000000000..7a898ac6f09
Binary files /dev/null and b/icons/obj/items/sheet_snatcher.dmi differ
diff --git a/icons/obj/items/shield/buckler.dmi b/icons/obj/items/shield/buckler.dmi
deleted file mode 100644
index ff53a0e14e0..00000000000
Binary files a/icons/obj/items/shield/buckler.dmi and /dev/null differ
diff --git a/icons/obj/items/shield/buckler_base_metal.dmi b/icons/obj/items/shield/buckler_base_metal.dmi
new file mode 100644
index 00000000000..41372efa755
Binary files /dev/null and b/icons/obj/items/shield/buckler_base_metal.dmi differ
diff --git a/icons/obj/items/shield/buckler_base_wood.dmi b/icons/obj/items/shield/buckler_base_wood.dmi
new file mode 100644
index 00000000000..03e9bc34a6d
Binary files /dev/null and b/icons/obj/items/shield/buckler_base_wood.dmi differ
diff --git a/icons/obj/items/shield/buckler_metal.dmi b/icons/obj/items/shield/buckler_metal.dmi
new file mode 100644
index 00000000000..0d27f07c23e
Binary files /dev/null and b/icons/obj/items/shield/buckler_metal.dmi differ
diff --git a/icons/obj/items/shield/buckler_wood.dmi b/icons/obj/items/shield/buckler_wood.dmi
new file mode 100644
index 00000000000..94e4563a342
Binary files /dev/null and b/icons/obj/items/shield/buckler_wood.dmi differ
diff --git a/icons/obj/items/shield_fasteners.dmi b/icons/obj/items/shield_fasteners.dmi
new file mode 100644
index 00000000000..e4c289ffc0c
Binary files /dev/null and b/icons/obj/items/shield_fasteners.dmi differ
diff --git a/icons/obj/items/tool/chisel.dmi b/icons/obj/items/tool/chisel.dmi
new file mode 100644
index 00000000000..e277e1ba44b
Binary files /dev/null and b/icons/obj/items/tool/chisel.dmi differ
diff --git a/icons/obj/items/tool/components/tool_head.dmi b/icons/obj/items/tool/components/tool_head.dmi
index dbb7e7db2bc..cc9a43d9971 100644
Binary files a/icons/obj/items/tool/components/tool_head.dmi and b/icons/obj/items/tool/components/tool_head.dmi differ
diff --git a/icons/obj/items/tool/hammers/forge.dmi b/icons/obj/items/tool/hammers/forge.dmi
new file mode 100644
index 00000000000..a7b0a4e0611
Binary files /dev/null and b/icons/obj/items/tool/hammers/forge.dmi differ
diff --git a/icons/obj/machines/gigadrill.dmi b/icons/obj/machines/gigadrill.dmi
new file mode 100644
index 00000000000..bcbda6a5144
Binary files /dev/null and b/icons/obj/machines/gigadrill.dmi differ
diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi
deleted file mode 100644
index 0bf325c1efb..00000000000
Binary files a/icons/obj/mining.dmi and /dev/null differ
diff --git a/icons/obj/structures/boulder.dmi b/icons/obj/structures/boulder.dmi
new file mode 100644
index 00000000000..dc83a302239
Binary files /dev/null and b/icons/obj/structures/boulder.dmi differ
diff --git a/icons/obj/structures/forging/bellows.dmi b/icons/obj/structures/forging/bellows.dmi
new file mode 100644
index 00000000000..9e6031422ef
Binary files /dev/null and b/icons/obj/structures/forging/bellows.dmi differ
diff --git a/icons/obj/structures/ore_box.dmi b/icons/obj/structures/ore_box.dmi
new file mode 100644
index 00000000000..c9eea92cfd2
Binary files /dev/null and b/icons/obj/structures/ore_box.dmi differ
diff --git a/icons/obj/structures/snowmen/snowbot.dmi b/icons/obj/structures/snowmen/snowbot.dmi
new file mode 100644
index 00000000000..c209cf5e868
Binary files /dev/null and b/icons/obj/structures/snowmen/snowbot.dmi differ
diff --git a/icons/obj/structures/snowmen/snowman.dmi b/icons/obj/structures/snowmen/snowman.dmi
new file mode 100644
index 00000000000..c174da4bb4d
Binary files /dev/null and b/icons/obj/structures/snowmen/snowman.dmi differ
diff --git a/icons/obj/structures/snowmen/snowspider.dmi b/icons/obj/structures/snowmen/snowspider.dmi
new file mode 100644
index 00000000000..bc7af6f5b8c
Binary files /dev/null and b/icons/obj/structures/snowmen/snowspider.dmi differ
diff --git a/icons/obj/wizard.dmi b/icons/obj/wizard.dmi
index 49d879d47d8..b8ebfc01108 100644
Binary files a/icons/obj/wizard.dmi and b/icons/obj/wizard.dmi differ
diff --git a/icons/screen/hud.dmi b/icons/screen/hud.dmi
new file mode 100644
index 00000000000..b8d98129369
Binary files /dev/null and b/icons/screen/hud.dmi differ
diff --git a/icons/screen/hud_antag.dmi b/icons/screen/hud_antag.dmi
new file mode 100644
index 00000000000..07840ff2614
Binary files /dev/null and b/icons/screen/hud_antag.dmi differ
diff --git a/icons/screen/hud_implants.dmi b/icons/screen/hud_implants.dmi
new file mode 100644
index 00000000000..5899f696f70
Binary files /dev/null and b/icons/screen/hud_implants.dmi differ
diff --git a/icons/screen/hud_med.dmi b/icons/screen/hud_med.dmi
new file mode 100644
index 00000000000..280097c8166
Binary files /dev/null and b/icons/screen/hud_med.dmi differ
diff --git a/icons/screen/intents.dmi b/icons/screen/intents.dmi
index 23e147992e0..3e7992ed2c9 100644
Binary files a/icons/screen/intents.dmi and b/icons/screen/intents.dmi differ
diff --git a/icons/screen/intents_wide.dmi b/icons/screen/intents_wide.dmi
index 9f210bc1c2d..a89c5ee023d 100644
Binary files a/icons/screen/intents_wide.dmi and b/icons/screen/intents_wide.dmi differ
diff --git a/maps/antag_spawn/ert/ert_base.dmm b/maps/antag_spawn/ert/ert_base.dmm
index e105bb2c1a8..703d909d0c3 100644
--- a/maps/antag_spawn/ert/ert_base.dmm
+++ b/maps/antag_spawn/ert/ert_base.dmm
@@ -1195,10 +1195,6 @@
/obj/machinery/vending/medical,
/turf/unsimulated/wall,
/area/map_template/rescue_base/base)
-"dj" = (
-/obj/effect/wingrille_spawn/reinforced/crescent,
-/turf/space,
-/area/map_template/rescue_base/base)
"dk" = (
/obj/machinery/door/airlock/centcom{
name = "EVA"
@@ -4269,7 +4265,7 @@ ar
cH
ar
cS
-dj
+bg
ao
ao
bg
@@ -4334,7 +4330,7 @@ ar
cI
ar
cT
-dj
+bg
ao
ao
bg
@@ -4399,7 +4395,7 @@ ar
ar
ar
cU
-dj
+bg
ao
ao
bg
@@ -4464,7 +4460,7 @@ cy
cJ
cO
cV
-dj
+bg
ao
ao
ad
diff --git a/maps/away/errant_pisces/errant_pisces.dm b/maps/away/errant_pisces/errant_pisces.dm
index b5079186ecc..ba006dddf06 100644
--- a/maps/away/errant_pisces/errant_pisces.dm
+++ b/maps/away/errant_pisces/errant_pisces.dm
@@ -112,9 +112,9 @@
return SPAN_NOTICE("A few strands of \the [src] have been severed.")
/obj/structure/net/attackby(obj/item/W, mob/user)
- if(W.sharp || W.edge)
- var/force = W.get_attack_force(user)
- if (!(W.sharp) || (W.sharp && force < 10))//is not sharp enough or at all
+ if(W.is_sharp() || W.has_edge())
+ var/force = W.expend_attack_force(user)
+ if (!(W.is_sharp()) || (W.is_sharp() && force < 10))//is not sharp enough or at all
to_chat(user,"You can't cut through \the [src] with \the [W], it's too dull.")
return TRUE
visible_message("[user] starts to cut through \the [src] with \the [W]!")
diff --git a/maps/away/liberia/hud.dmi b/maps/away/liberia/hud.dmi
new file mode 100644
index 00000000000..01fe4cbfcd4
Binary files /dev/null and b/maps/away/liberia/hud.dmi differ
diff --git a/maps/away/liberia/liberia_jobs.dm b/maps/away/liberia/liberia_jobs.dm
index 4d3b627143f..34269ce2cd3 100644
--- a/maps/away/liberia/liberia_jobs.dm
+++ b/maps/away/liberia/liberia_jobs.dm
@@ -11,7 +11,8 @@
info = "You are free traders who have drifted into unknown distances in search of profit. Travel, trade, make profit!"
supervisors = "the invisible hand of the market"
selection_color = "#515151"
-
+ hud_icon = 'maps/away/liberia/hud.dmi'
+ hud_icon_state = "hudmerchant"
ideal_character_age = 20
minimal_player_age = 7
diff --git a/maps/away/lost_supply_base/lost_supply_base.dmm b/maps/away/lost_supply_base/lost_supply_base.dmm
index aac57b9b881..55d86201533 100644
--- a/maps/away/lost_supply_base/lost_supply_base.dmm
+++ b/maps/away/lost_supply_base/lost_supply_base.dmm
@@ -1982,7 +1982,7 @@
/turf/unsimulated/mask,
/area/mine/unexplored)
"gu" = (
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"ib" = (
/obj/structure/hygiene/sink{
diff --git a/maps/away/mining/mining-asteroid.dmm b/maps/away/mining/mining-asteroid.dmm
index 63713ba4434..89a0612365c 100644
--- a/maps/away/mining/mining-asteroid.dmm
+++ b/maps/away/mining/mining-asteroid.dmm
@@ -6,14 +6,14 @@
/turf/unsimulated/mask,
/area/mine/unexplored)
"af" = (
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"aj" = (
/turf/wall/r_wall,
/area/djstation)
"ak" = (
/obj/random/junk,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"al" = (
/obj/random/trash,
@@ -204,15 +204,15 @@
/area/djstation)
"be" = (
/obj/random/maintenance,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"bf" = (
/obj/effect/overmap/visitable/sector/cluster,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"cb" = (
/obj/effect/shuttle_landmark/cluster/nav5,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"db" = (
/obj/effect/shuttle_landmark/cluster/nav6,
@@ -236,7 +236,7 @@
/area/space)
"ib" = (
/obj/effect/shuttle_landmark/cluster/nav7,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"jb" = (
/obj/machinery/button/access/exterior{
@@ -245,7 +245,7 @@
pixel_y = -24;
dir = 1
},
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"kb" = (
/obj/machinery/door/airlock/external{
@@ -345,7 +345,7 @@
req_access = null;
dir = 4
},
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"wb" = (
/obj/machinery/door/airlock/external{
diff --git a/maps/away/mining/mining-orb.dmm b/maps/away/mining/mining-orb.dmm
index 0f03154da5c..46fc8c21fb4 100644
--- a/maps/away/mining/mining-orb.dmm
+++ b/maps/away/mining/mining-orb.dmm
@@ -14,10 +14,10 @@
/turf/unsimulated/mask,
/area/mine/unexplored)
"ae" = (
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"af" = (
-/turf/floor,
+/turf/floor/barren,
/area/mine/unexplored)
"ag" = (
/turf/wall/natural/random/high_chance,
@@ -250,7 +250,7 @@
/area/mine/explored)
"st" = (
/obj/effect/shuttle_landmark/orb/nav7,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"vc" = (
/obj/effect/floor_decal/spline/fancy/wood{
@@ -277,7 +277,7 @@
/obj/effect/floor_decal/spline/fancy/wood/corner{
dir = 4
},
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"Aj" = (
/obj/effect/floor_decal/spline/fancy/wood/corner,
diff --git a/maps/away/mining/mining_areas.dm b/maps/away/mining/mining_areas.dm
index 94d5e15d978..3dd6da72529 100644
--- a/maps/away/mining/mining_areas.dm
+++ b/maps/away/mining/mining_areas.dm
@@ -3,7 +3,7 @@
icon_state = "mining"
ambience = list('sound/ambience/ambimine.ogg', 'sound/ambience/song_game.ogg')
sound_env = ASTEROID
- base_turf = /turf/floor
+ base_turf = /turf/floor/barren
area_flags = AREA_FLAG_IS_BACKGROUND | AREA_FLAG_HIDE_FROM_HOLOMAP
/area/mine/explored
diff --git a/maps/away/smugglers/smugglers.dmm b/maps/away/smugglers/smugglers.dmm
index 1881db19743..a0dbd796036 100644
--- a/maps/away/smugglers/smugglers.dmm
+++ b/maps/away/smugglers/smugglers.dmm
@@ -3,7 +3,7 @@
/turf/space,
/area/space)
"ab" = (
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"ac" = (
/turf/unsimulated/mask,
@@ -24,7 +24,7 @@
/turf/floor,
/area/smugglers/base)
"ah" = (
-/turf/floor,
+/turf/floor/barren,
/area/space)
"aj" = (
/obj/item/ammo_casing/pistol/magnum{
@@ -37,11 +37,11 @@
pixel_y = -5
},
/obj/effect/decal/cleanable/blood,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"ak" = (
/obj/effect/decal/cleanable/blood,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"al" = (
/obj/effect/wallframe_spawn/reinforced,
@@ -98,7 +98,7 @@
pixel_y = 7
},
/obj/item/flashlight/flare/glowstick/yellow,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"av" = (
/obj/effect/decal/cleanable/blood/drip,
@@ -281,11 +281,11 @@
pixel_x = -25;
pixel_y = 25
},
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"aM" = (
/obj/random/trash,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"aN" = (
/obj/machinery/light/small{
@@ -432,7 +432,7 @@
/obj/item/tool/xeno/hand{
pixel_x = -15
},
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"bh" = (
/obj/effect/floor_decal/industrial/warning{
@@ -476,7 +476,7 @@
/area/smugglers/base)
"bn" = (
/obj/structure/boulder,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"bo" = (
/obj/item/stack/material/ore/silver,
@@ -484,7 +484,7 @@
pixel_x = 10;
pixel_y = -5
},
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"bp" = (
/obj/structure/cable{
@@ -946,7 +946,7 @@
"db" = (
/obj/effect/decal/cleanable/blood,
/obj/abstract/landmark/corpse/doctor,
-/turf/floor,
+/turf/floor/barren,
/area/mine/explored)
"eb" = (
/obj/machinery/light/small{
diff --git a/maps/away/unishi/unishi.dm b/maps/away/unishi/unishi.dm
index 54e80fe8a88..0b7112c782b 100644
--- a/maps/away/unishi/unishi.dm
+++ b/maps/away/unishi/unishi.dm
@@ -1,6 +1,7 @@
#include "unishi_areas.dm"
#include "unishi_jobs.dm"
#include "../../../mods/content/xenobiology/_xenobiology.dme"
+#include "../../../mods/content/supermatter/_supermatter.dme"
/obj/abstract/submap_landmark/joinable_submap/unishi
name = "SRV Verne"
diff --git a/maps/away_sites_testing/away_sites_testing_define.dm b/maps/away_sites_testing/away_sites_testing_define.dm
index 6f3a96274ee..fd1868d5c2a 100644
--- a/maps/away_sites_testing/away_sites_testing_define.dm
+++ b/maps/away_sites_testing/away_sites_testing_define.dm
@@ -4,10 +4,14 @@
full_name = "Away Sites Testing Land"
path = "away_sites_testing"
overmap_ids = list(OVERMAP_ID_SPACE)
+ votable = FALSE
allowed_latejoin_spawns = list()
default_spawn = null
+/datum/map/away_sites_testing/validate()
+ return TRUE // Do not check for level lists, this is not a playable map.
+
// Set the observer spawn to include every flag so that CI flag checks pass.
/decl/spawnpoint/observer
spawn_flags = (SPAWN_FLAG_GHOSTS_CAN_SPAWN | SPAWN_FLAG_JOBS_CAN_SPAWN | SPAWN_FLAG_PRISONERS_CAN_SPAWN | SPAWN_FLAG_PERSISTENCE_CAN_SPAWN)
@@ -16,10 +20,10 @@
var/list/unsorted_sites = list_values(SSmapping.get_templates_by_category(MAP_TEMPLATE_CATEGORY_AWAYSITE))
var/list/sorted_sites = sortTim(unsorted_sites, /proc/cmp_sort_templates_tallest_to_shortest)
for (var/datum/map_template/A in sorted_sites)
- A.load_new_z(centered = FALSE)
+ A.load_new_z()
testing("Spawning [A] in [english_list(SSmapping.get_connected_levels(world.maxz))]")
if(A.template_flags & TEMPLATE_FLAG_TEST_DUPLICATES)
- A.load_new_z(centered = FALSE)
+ A.load_new_z()
testing("Spawning [A] in [english_list(SSmapping.get_connected_levels(world.maxz))]")
/proc/cmp_sort_templates_tallest_to_shortest(var/datum/map_template/a, var/datum/map_template/b)
diff --git a/maps/example/example-3.dmm b/maps/example/example-3.dmm
index 5b89fac02e5..abffda753cc 100644
--- a/maps/example/example-3.dmm
+++ b/maps/example/example-3.dmm
@@ -227,9 +227,8 @@
/turf/floor,
/area/example/third)
"MO" = (
-/obj/abstract/level_data_spawner/main_level{
+/obj/abstract/level_data_spawner/admin_level{
name = "Example Third Deck";
-
},
/turf/space,
/area/space)
diff --git a/maps/example/example_define.dm b/maps/example/example_define.dm
index 9c48d50899f..5f8a3a80c16 100644
--- a/maps/example/example_define.dm
+++ b/maps/example/example_define.dm
@@ -2,6 +2,7 @@
name = "Testing"
full_name = "Testing Site"
path = "example"
+ votable = FALSE
lobby_screens = list(
'maps/example/example_lobby.png'
diff --git a/maps/example/example_jobs.dm b/maps/example/example_jobs.dm
index e3ad5c0c488..28d5cf504c6 100644
--- a/maps/example/example_jobs.dm
+++ b/maps/example/example_jobs.dm
@@ -1,7 +1,6 @@
/datum/map/example
default_job_type = /datum/job/example
default_department_type = /decl/department/example
- id_hud_icons = 'maps/example/hud.dmi'
/datum/job/example
title = "Tourist"
@@ -13,9 +12,10 @@
access = list()
minimal_access = list()
outfit_type = /decl/outfit/job/tourist
+ hud_icon = 'maps/example/hud.dmi'
department_types = list(
/decl/department/example
- )
+ )
/decl/outfit/job/tourist
name = "Job - Testing Site Tourist"
diff --git a/maps/example/hud.dmi b/maps/example/hud.dmi
index 89dd2f9a079..c2c456e9d50 100644
Binary files a/maps/example/hud.dmi and b/maps/example/hud.dmi differ
diff --git a/maps/exodus/exodus-1.dmm b/maps/exodus/exodus-1.dmm
index df58cbab4de..bd953735089 100644
--- a/maps/exodus/exodus-1.dmm
+++ b/maps/exodus/exodus-1.dmm
@@ -3496,8 +3496,7 @@
department = "Atmospherics";
name = "Atmos RC";
pixel_y = 32;
- dir = 1;
-
+ dir = 1
},
/obj/structure/table/steel,
/turf/floor/tiled/steel_grid,
@@ -5467,6 +5466,10 @@
},
/turf/floor/lino,
/area/exodus/maintenance/telecomms)
+"rd" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"rj" = (
/obj/effect/floor_decal/industrial/outline/grey,
/obj/machinery/camera/network/command{
@@ -16599,7 +16602,7 @@ aa
aa
aa
aa
-aa
+rd
aa
aa
aa
@@ -44175,7 +44178,7 @@ aa
aa
aa
aa
-aa
+rd
aa
aa
aa
@@ -49205,7 +49208,7 @@ aa
aa
aa
aa
-aa
+rd
aa
aa
aa
diff --git a/maps/exodus/exodus-2.dmm b/maps/exodus/exodus-2.dmm
index 86bd27bd087..093c3433310 100644
--- a/maps/exodus/exodus-2.dmm
+++ b/maps/exodus/exodus-2.dmm
@@ -30773,7 +30773,7 @@
/obj/machinery/fabricator/imprinter{
id_tag = "science"
},
-/obj/item/chems/glass/beaker/sulphuric,
+/obj/item/chems/glass/beaker/sulfuric,
/obj/structure/reagent_dispensers/acid{
density = 0;
pixel_y = 32
@@ -32592,7 +32592,7 @@
/obj/machinery/fabricator/imprinter{
id_tag = "science"
},
-/obj/item/chems/glass/beaker/sulphuric,
+/obj/item/chems/glass/beaker/sulfuric,
/turf/floor/tiled/dark,
/area/exodus/research/lab)
"bqQ" = (
@@ -63723,6 +63723,10 @@
},
/turf/floor/tiled/steel_grid,
/area/ship/exodus_pod_research)
+"eYg" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"eZK" = (
/obj/effect/floor_decal/corner/purple,
/obj/machinery/light,
@@ -76795,7 +76799,7 @@ cLU
cLU
cLU
cLU
-cLU
+eYg
cLU
cLU
cLU
@@ -88722,7 +88726,7 @@ cLU
cLU
cLU
cLU
-cLU
+eYg
cLU
cLU
cLU
@@ -108695,7 +108699,7 @@ cLU
cLU
cLU
cLU
-cLU
+eYg
cLU
cLU
cLU
@@ -116645,7 +116649,7 @@ cLU
cLU
cLU
cLU
-cLU
+eYg
cLU
cLU
cLU
diff --git a/maps/exodus/exodus-admin.dmm b/maps/exodus/exodus-admin.dmm
index 202bb8b9999..5d94162873e 100644
--- a/maps/exodus/exodus-admin.dmm
+++ b/maps/exodus/exodus-admin.dmm
@@ -2422,7 +2422,8 @@
/turf/unsimulated/floor/vault,
/area/tdome)
"lSj" = (
-/obj/effect/forcefield{
+/obj/effect{
+ density = 1;
desc = "You can't get in. Heh.";
name = "Blocker"
},
@@ -2434,7 +2435,8 @@
/turf/unsimulated/floor/dark,
/area/tdome)
"mgi" = (
-/obj/effect/forcefield{
+/obj/effect{
+ density = 1;
desc = "You can't get in. Heh.";
name = "Blocker"
},
@@ -2799,7 +2801,8 @@
/turf/floor/tiled,
/area/shuttle/escape_shuttle)
"xSD" = (
-/obj/effect/forcefield{
+/obj/effect{
+ density = 1;
desc = "You can't get in. Heh.";
name = "Blocker"
},
diff --git a/maps/exodus/exodus.dm b/maps/exodus/exodus.dm
index 6ad2e80572e..6359c75549c 100644
--- a/maps/exodus/exodus.dm
+++ b/maps/exodus/exodus.dm
@@ -1,21 +1,15 @@
#if !defined(USING_MAP_DATUM)
- #include "../../mods/gamemodes/cult/_cult.dme"
- #include "../../mods/gamemodes/heist/_heist.dme"
- #include "../../mods/gamemodes/meteor/_meteor.dme"
- #include "../../mods/gamemodes/ninja/_ninja.dme"
- #include "../../mods/gamemodes/revolution/_revolution.dme"
- #include "../../mods/gamemodes/traitor/_traitor.dme"
- #include "../../mods/gamemodes/spyvspy/_spyvspy.dme"
- #include "../../mods/gamemodes/mixed/_mixed.dme"
-
#include "../../mods/content/mundane.dm"
+
#include "../../mods/content/baychems/_baychems.dme"
+
#include "../../mods/content/corporate/_corporate.dme"
#include "../../mods/content/government/_government.dme"
#include "../../mods/content/matchmaking/_matchmaking.dme"
#include "../../mods/content/modern_earth/_modern_earth.dme"
#include "../../mods/content/mouse_highlights/_mouse_highlight.dme"
+
#include "../../mods/content/polaris/_polaris.dme"
#include "../../mods/content/scaling_descriptors.dm"
#include "../../mods/content/xenobiology/_xenobiology.dme"
@@ -26,9 +20,22 @@
// Must come after borers for compatibility.
#include "../../mods/content/psionics/_psionics.dme"
-
- // Must come after psionics for counsellor compatibility.
#include "../../mods/content/standard_jobs/_standard_jobs.dme"
+ #include "../../mods/content/supermatter/_supermatter.dme"
+ #include "../../mods/content/xenobiology/_xenobiology.dme"
+ #include "../../mods/content/tabloids/_tabloids.dme"
+
+ #include "../../mods/gamemodes/cult/_cult.dme"
+ #include "../../mods/gamemodes/heist/_heist.dme"
+ #include "../../mods/gamemodes/meteor/_meteor.dme"
+ #include "../../mods/gamemodes/ninja/_ninja.dme"
+ #include "../../mods/gamemodes/revolution/_revolution.dme"
+ #include "../../mods/gamemodes/spyvspy/_spyvspy.dme"
+ #include "../../mods/gamemodes/traitor/_traitor.dme"
+ #include "../../mods/gamemodes/mixed.dm"
+
+ #include "../../mods/mobs/borers/_borers.dme"
+ #include "../../mods/mobs/dionaea/_dionaea.dme"
#include "../../mods/species/skrell/_skrell.dme"
#include "../../mods/species/tajaran/_tajaran.dme"
diff --git a/maps/exodus/exodus_antagonism.dm b/maps/exodus/exodus_antagonism.dm
index 322bebbf1d3..e09d2ddc900 100644
--- a/maps/exodus/exodus_antagonism.dm
+++ b/maps/exodus/exodus_antagonism.dm
@@ -1,16 +1,16 @@
/decl/special_role/traitor/Initialize()
. = ..()
LAZYINITLIST(protected_jobs)
- protected_jobs |= list(/datum/job/officer, /datum/job/warden, /datum/job/detective, /datum/job/captain, /datum/job/lawyer, /datum/job/hos)
+ protected_jobs |= list(/datum/job/standard/officer, /datum/job/standard/warden, /datum/job/standard/detective, /datum/job/standard/captain, /datum/job/standard/lawyer, /datum/job/standard/hos)
/decl/special_role/cultist/Initialize()
. = ..()
LAZYINITLIST(restricted_jobs)
- restricted_jobs |= list(/datum/job/lawyer, /datum/job/captain, /datum/job/hos)
+ restricted_jobs |= list(/datum/job/standard/lawyer, /datum/job/standard/captain, /datum/job/standard/hos)
LAZYINITLIST(protected_jobs)
- protected_jobs |= list(/datum/job/officer, /datum/job/warden, /datum/job/detective)
+ protected_jobs |= list(/datum/job/standard/officer, /datum/job/standard/warden, /datum/job/standard/detective)
LAZYINITLIST(blacklisted_jobs)
- blacklisted_jobs |= list(/datum/job/chaplain, /datum/job/counselor)
+ blacklisted_jobs |= list(/datum/job/standard/chaplain, /datum/job/standard/counselor)
/decl/special_role/loyalist
command_department_id = /decl/department/command
diff --git a/maps/exodus/exodus_define.dm b/maps/exodus/exodus_define.dm
index 0cdfc436956..03a9f450fab 100644
--- a/maps/exodus/exodus_define.dm
+++ b/maps/exodus/exodus_define.dm
@@ -12,8 +12,6 @@
company_short = "NT"
system_name = "Nyx"
- default_law_type = /datum/ai_laws/nanotrasen
-
overmap_ids = list(OVERMAP_ID_SPACE)
num_exoplanets = 3
away_site_budget = 3
diff --git a/maps/exodus/exodus_goals.dm b/maps/exodus/exodus_goals.dm
index 72c324b5c1d..8275bc4173b 100644
--- a/maps/exodus/exodus_goals.dm
+++ b/maps/exodus/exodus_goals.dm
@@ -29,12 +29,12 @@ var/global/list/exodus_paperwork_end_areas = list()
/datum/goal/department/paperwork/exodus
paperwork_types = list(/obj/item/paperwork/exodus)
signatory_job_list = list(
- /datum/job/captain,
- /datum/job/hop,
- /datum/job/cmo,
- /datum/job/chief_engineer,
- /datum/job/rd,
- /datum/job/hos
+ /datum/job/standard/captain,
+ /datum/job/standard/hop,
+ /datum/job/standard/cmo,
+ /datum/job/standard/chief_engineer,
+ /datum/job/standard/rd,
+ /datum/job/standard/hos
)
/datum/goal/department/paperwork/exodus/get_paper_spawn_turfs()
diff --git a/maps/exodus/exodus_jobs.dm b/maps/exodus/exodus_jobs.dm
index 68f1d5b8e67..1e09ef50b52 100644
--- a/maps/exodus/exodus_jobs.dm
+++ b/maps/exodus/exodus_jobs.dm
@@ -7,40 +7,40 @@
spawn_decl = /decl/spawnpoint/gateway
/datum/map/exodus
- default_job_type = /datum/job/assistant
+ default_job_type = /datum/job/standard/assistant
default_department_type = /decl/department/civilian
- id_hud_icons = 'maps/exodus/hud.dmi'
allowed_jobs = list(
- /datum/job/captain,
- /datum/job/hop,
- /datum/job/chaplain,
- /datum/job/bartender,
- /datum/job/chef,
- /datum/job/hydro,
- /datum/job/qm,
- /datum/job/cargo_tech,
- /datum/job/mining,
- /datum/job/janitor,
- /datum/job/librarian,
- /datum/job/lawyer,
- /datum/job/chief_engineer,
- /datum/job/engineer,
- /datum/job/cmo,
- /datum/job/doctor,
- /datum/job/chemist,
- /datum/job/counselor,
- /datum/job/rd,
- /datum/job/scientist,
- /datum/job/roboticist,
- /datum/job/hos,
- /datum/job/detective,
- /datum/job/warden,
- /datum/job/officer,
- /datum/job/robot,
- /datum/job/computer
+ /datum/job/standard/captain,
+ /datum/job/standard/hop,
+ /datum/job/standard/chaplain,
+ /datum/job/standard/bartender,
+ /datum/job/standard/chef,
+ /datum/job/standard/hydro,
+ /datum/job/standard/qm,
+ /datum/job/standard/cargo_tech,
+ /datum/job/standard/mining,
+ /datum/job/standard/janitor,
+ /datum/job/standard/librarian,
+ /datum/job/standard/lawyer,
+ /datum/job/standard/chief_engineer,
+ /datum/job/standard/engineer,
+ /datum/job/standard/cmo,
+ /datum/job/standard/doctor,
+ /datum/job/standard/chemist,
+ /datum/job/standard/counselor,
+ /datum/job/standard/rd,
+ /datum/job/standard/scientist,
+ /datum/job/standard/roboticist,
+ /datum/job/standard/hos,
+ /datum/job/standard/detective,
+ /datum/job/standard/warden,
+ /datum/job/standard/officer,
+ /datum/job/standard/robot,
+ /datum/job/standard/computer
)
-#define HUMAN_ONLY_JOBS /datum/job/captain, /datum/job/hop, /datum/job/hos
+#define HUMAN_ONLY_JOBS /datum/job/standard/captain, /datum/job/standard/hop, /datum/job/standard/hos
+
species_to_job_blacklist = list(
/decl/species/unathi = list(
HUMAN_ONLY_JOBS
diff --git a/maps/exodus/exodus_loadout.dm b/maps/exodus/exodus_loadout.dm
index 107fa0ae8c9..d5f70fdf957 100644
--- a/maps/exodus/exodus_loadout.dm
+++ b/maps/exodus/exodus_loadout.dm
@@ -2,7 +2,7 @@
name = "religious insignia"
path = /obj/item/clothing/insignia
cost = 1
- allowed_roles = list(/datum/job/chaplain)
+ allowed_roles = list(/datum/job/standard/chaplain)
uid = "gear_accessory_insignia"
/decl/loadout_option/accessory/insignia/Initialize()
diff --git a/maps/exodus/exodus_overrides.dm b/maps/exodus/exodus_overrides.dm
index 947cbd184c1..c2babeabe95 100644
--- a/maps/exodus/exodus_overrides.dm
+++ b/maps/exodus/exodus_overrides.dm
@@ -9,3 +9,6 @@
/decl/background_category/heritage = /decl/background_detail/heritage/hidden/cultist,
/decl/background_category/faction = /decl/background_detail/faction/other
)
+
+/datum/map/exodus
+ default_law_type = /datum/ai_laws/nanotrasen
diff --git a/maps/exodus/hud.dmi b/maps/exodus/hud.dmi
deleted file mode 100644
index 952d808b00e..00000000000
Binary files a/maps/exodus/hud.dmi and /dev/null differ
diff --git a/maps/ministation/hud.dmi b/maps/ministation/hud.dmi
index d4fed05d840..8a3e91cf3a7 100644
Binary files a/maps/ministation/hud.dmi and b/maps/ministation/hud.dmi differ
diff --git a/maps/ministation/jobs/civilian.dm b/maps/ministation/jobs/civilian.dm
index 3d1601530d6..18024cc2379 100644
--- a/maps/ministation/jobs/civilian.dm
+++ b/maps/ministation/jobs/civilian.dm
@@ -1,15 +1,14 @@
-/datum/job/assistant/ministation
+/datum/job/standard/assistant/ministation
title = "Recruit"
supervisors = "absolutely everyone"
alt_titles = list("Technical Recruit","Medical Recruit","Research Recruit","Visitor")
outfit_type = /decl/outfit/job/ministation_assistant
event_categories = list(ASSIGNMENT_GARDENER)
- hud_icon = "hudassistant"
/decl/outfit/job/ministation_assistant
name = "Job - Ministation Assistant"
-/datum/job/bartender/ministation
+/datum/job/standard/bartender/ministation
title = "Bartender"
alt_titles = list("Cook","Barista")
supervisors = "the Lieutenant and the Captain"
@@ -30,7 +29,7 @@
)
skill_points = 30
-/datum/job/cargo_tech/ministation
+/datum/job/standard/cargo_tech/ministation
title = "Cargo Technician"
alt_titles = list("Shaft Miner","Drill Technician","Prospector")
supervisors = "the Lieutenant and the Captain"
@@ -73,7 +72,7 @@
)
skill_points = 30
-/datum/job/janitor/ministation
+/datum/job/standard/janitor/ministation
total_positions = 2
supervisors = "the Lieutenant and the Captain"
economic_power = 3
@@ -84,7 +83,7 @@
)
skill_points = 28
-/datum/job/librarian/ministation
+/datum/job/standard/librarian/ministation
spawn_positions = 2
supervisors = "the Lieutenant, the Captain, and the smell of old paper"
economic_power = 5
diff --git a/maps/ministation/jobs/command.dm b/maps/ministation/jobs/command.dm
index a823a716095..1a27ff0736d 100644
--- a/maps/ministation/jobs/command.dm
+++ b/maps/ministation/jobs/command.dm
@@ -1,6 +1,7 @@
-/datum/job/captain/ministation
+/datum/job/standard/captain/ministation
supervisors = "your profit margin, your conscience, and the watchful eye of the Tradehouse Rep"
outfit_type = /decl/outfit/job/ministation/captain
+ hud_icon = 'maps/ministation/hud.dmi'
min_skill = list(
SKILL_LITERACY = SKILL_ADEPT,
SKILL_WEAPONS = SKILL_ADEPT,
@@ -13,7 +14,7 @@
)
skill_points = 40
-/datum/job/captain/ministation/equip_job(var/mob/living/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade)
+/datum/job/standard/captain/ministation/equip_job(var/mob/living/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade)
. = ..()
if(H)
H.verbs |= /mob/proc/freetradeunion_rename_company
@@ -33,10 +34,11 @@
command_announcement.Announce("Congratulations to all members of [capitalize(global.using_map.company_name)] on the new name. Their rebranding has changed the [global.using_map.company_short] market value by [0.01*rand(-10,10)]%.", "Trade Union Name Change")
verbs -= /mob/proc/freetradeunion_rename_company
-/datum/job/hop/ministation
+/datum/job/standard/hop/ministation
title = "Lieutenant"
outfit_type = /decl/outfit/job/ministation/hop
- hud_icon = "hudlieutenant"
+ hud_icon = 'maps/ministation/hud.dmi'
+ hud_icon_state = "hudlieutenant"
min_skill = list(
SKILL_LITERACY = SKILL_ADEPT,
SKILL_WEAPONS = SKILL_BASIC,
diff --git a/maps/ministation/jobs/engineering.dm b/maps/ministation/jobs/engineering.dm
index d780f2353d2..a3cb57fbc0a 100644
--- a/maps/ministation/jobs/engineering.dm
+++ b/maps/ministation/jobs/engineering.dm
@@ -1,4 +1,4 @@
-/datum/job/engineer/ministation
+/datum/job/standard/engineer/ministation
title = "Station Engineer"
supervisors = "the Head Engineer"
total_positions = 2
@@ -32,9 +32,8 @@
skill_points = 30
alt_titles = list("Atmospheric Technician", "Electrician", "Maintenance Technician")
-/datum/job/chief_engineer/ministation
+/datum/job/standard/chief_engineer/ministation
title = "Head Engineer"
- hud_icon = "hudchiefengineer"
access = list(
access_engine,
access_engine_equip,
diff --git a/maps/ministation/jobs/medical.dm b/maps/ministation/jobs/medical.dm
index 0e91a2d945b..1dd568c8176 100644
--- a/maps/ministation/jobs/medical.dm
+++ b/maps/ministation/jobs/medical.dm
@@ -1,4 +1,4 @@
-/datum/job/doctor/ministation
+/datum/job/standard/doctor/ministation
title = "Medical Doctor"
supervisors = "the Head Doctor"
total_positions = 2
@@ -35,13 +35,12 @@
)
outfit_type = /decl/outfit/job/ministation/doctor
-/datum/job/cmo/ministation
+/datum/job/standard/cmo/ministation
title = "Head Doctor"
supervisors = "the Captain and your own ethics"
outfit_type = /decl/outfit/job/ministation/doctor/head
alt_titles = list("Chief Medical Officer", "Head Surgeon")
skill_points = 38
- hud_icon = "hudheaddoctor"
access = list(
access_medical,
access_medical_equip,
diff --git a/maps/ministation/jobs/science.dm b/maps/ministation/jobs/science.dm
index f2d80cbe65f..7b8e61e4591 100644
--- a/maps/ministation/jobs/science.dm
+++ b/maps/ministation/jobs/science.dm
@@ -1,14 +1,13 @@
-/datum/job/scientist/ministation
+/datum/job/standard/scientist/ministation
title = "Researcher"
alt_titles = list("Scientist","Xenobiologist","Roboticist","Xenobotanist")
supervisors = "the Head Researcher"
spawn_positions = 1
total_positions = 2
outfit_type = /decl/outfit/job/ministation/scientist
- hud_icon = "hudscientist"
skill_points = 34
-/datum/job/rd/ministation
+/datum/job/standard/rd/ministation
title = "Research Director"
alt_titles = list("Head Researcher", "Chief Researcher")
outfit_type = /decl/outfit/job/ministation/scientist/head
@@ -27,7 +26,6 @@
SKILL_SCIENCE = SKILL_MAX
)
skill_points = 40
- hud_icon = "hudheadscientist"
access = list(
access_rd,
access_bridge,
diff --git a/maps/ministation/jobs/security.dm b/maps/ministation/jobs/security.dm
index 55ea8e841e2..242c665e7f3 100644
--- a/maps/ministation/jobs/security.dm
+++ b/maps/ministation/jobs/security.dm
@@ -1,4 +1,4 @@
-/datum/job/officer/ministation
+/datum/job/standard/officer/ministation
title = "Security Officer"
alt_titles = list("Warden")
spawn_positions = 1
@@ -22,7 +22,7 @@
)
skill_points = 30
-/datum/job/detective/ministation
+/datum/job/standard/detective/ministation
alt_titles = list("Inspector")
supervisors = "Justice... and the Trademaster"
spawn_positions = 1
@@ -55,9 +55,8 @@
)
skill_points = 34
-/datum/job/hos/ministation
+/datum/job/standard/hos/ministation
outfit_type = /decl/outfit/job/ministation/security/head
- hud_icon = "hudhos"
access = list(
access_security,
access_sec_doors,
diff --git a/maps/ministation/jobs/tradehouse.dm b/maps/ministation/jobs/tradehouse.dm
index 1e167615cf8..daa715dddd5 100644
--- a/maps/ministation/jobs/tradehouse.dm
+++ b/maps/ministation/jobs/tradehouse.dm
@@ -1,7 +1,8 @@
/datum/job/tradehouse_rep
title = "Tradehouse Representative"
alt_titles = list("Narc")
- hud_icon = "hudnarc"
+ hud_icon_state = "hudnarc"
+ hud_icon = 'maps/ministation/hud.dmi'
spawn_positions = 1
total_positions = 2
req_admin_notify = 1
diff --git a/maps/ministation/ministation-0.dmm b/maps/ministation/ministation-0.dmm
index 88dfa842c03..35b21cdc415 100644
--- a/maps/ministation/ministation-0.dmm
+++ b/maps/ministation/ministation-0.dmm
@@ -5556,6 +5556,10 @@
},
/turf/floor/tiled/monotile,
/area/ministation/atmospherics)
+"yY" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"yZ" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -33009,7 +33013,7 @@ aa
aa
aa
aa
-aa
+yY
aa
aa
aa
@@ -49102,7 +49106,7 @@ aa
aa
aa
aa
-aa
+yY
aa
aa
aa
@@ -57125,7 +57129,7 @@ aa
aa
aa
aa
-aa
+yY
aa
aa
aa
diff --git a/maps/ministation/ministation-1.dmm b/maps/ministation/ministation-1.dmm
index 5deccebb931..6646873ff83 100644
--- a/maps/ministation/ministation-1.dmm
+++ b/maps/ministation/ministation-1.dmm
@@ -2713,6 +2713,10 @@
},
/turf/floor/tiled,
/area/ministation/hall/w2)
+"nt" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"nu" = (
/obj/effect/floor_decal/carpet{
dir = 8
@@ -6710,6 +6714,8 @@
},
/obj/structure/table/laminate,
/obj/machinery/reagent_temperature,
+/obj/item/chems/cooking_vessel/pot,
+/obj/item/chems/cooking_vessel/skillet,
/turf/floor/lino,
/area/ministation/cafe)
"Ct" = (
@@ -9758,12 +9764,12 @@
/obj/structure/table/laminate,
/obj/item/eftpos,
/obj/item/chems/spray/cleaner,
+/obj/item/chems/packet/honey_fake,
+/obj/item/chems/packet/honey_fake,
/obj/item/chems/packet/honey,
/obj/item/chems/packet/honey,
/obj/item/chems/packet/honey,
-/obj/item/chems/packet/honey,
-/obj/item/chems/packet/honey,
-/obj/item/chems/packet/honey,
+/obj/item/chems/packet/honey_fake,
/obj/item/chems/packet/honey,
/turf/floor/lino,
/area/ministation/cafe)
@@ -54008,7 +54014,7 @@ aa
aa
aa
aa
-aa
+nt
aa
aa
aa
@@ -54341,7 +54347,7 @@ aa
aa
aa
aa
-aa
+nt
aa
aa
aa
diff --git a/maps/ministation/ministation-2.dmm b/maps/ministation/ministation-2.dmm
index 227f2c065d9..e7fbc07d968 100644
--- a/maps/ministation/ministation-2.dmm
+++ b/maps/ministation/ministation-2.dmm
@@ -781,7 +781,7 @@
},
/obj/item/med_pouch/trauma,
/obj/item/stack/tape_roll/duct_tape,
-/obj/item/shield/buckler,
+/obj/item/shield/crafted/buckler,
/obj/item/gps/explorer,
/obj/item/belt/holster/machete,
/obj/item/tool/machete/deluxe,
@@ -2163,7 +2163,7 @@
"js" = (
/obj/structure/table,
/obj/item/chems/glass/beaker/large,
-/obj/item/chems/glass/beaker/sulphuric,
+/obj/item/chems/glass/beaker/sulfuric,
/obj/item/chems/dropper,
/obj/effect/floor_decal/corner/purple{
dir = 8
@@ -2274,7 +2274,7 @@
},
/obj/item/med_pouch/trauma,
/obj/item/stack/tape_roll/duct_tape,
-/obj/item/shield/buckler,
+/obj/item/shield/crafted/buckler,
/obj/item/gps/explorer,
/obj/item/flashlight/lantern,
/obj/item/bladed/polearm/spear/improvised/steel,
@@ -3536,6 +3536,10 @@
},
/turf/floor/reinforced,
/area/ministation/science)
+"sq" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"sr" = (
/turf/floor/tiled/dark/monotile/telecomms,
/area/ministation/telecomms)
@@ -4430,7 +4434,7 @@
/obj/machinery/light,
/obj/item/med_pouch/trauma,
/obj/item/stack/tape_roll/duct_tape,
-/obj/item/shield/buckler,
+/obj/item/shield/crafted/buckler,
/obj/item/gps/explorer,
/obj/item/flashlight/lantern,
/obj/item/bladed/polearm/spear/improvised/steel,
@@ -29552,7 +29556,7 @@ vA
vA
vA
vA
-vA
+sq
vA
vA
vA
@@ -45788,7 +45792,7 @@ vA
vA
vA
vA
-vA
+sq
vA
vA
vA
@@ -52136,7 +52140,7 @@ vA
vA
vA
vA
-vA
+sq
vA
vA
vA
diff --git a/maps/ministation/ministation-3.dmm b/maps/ministation/ministation-3.dmm
index cbdd8abb538..e5b68a7fe20 100644
--- a/maps/ministation/ministation-3.dmm
+++ b/maps/ministation/ministation-3.dmm
@@ -88,6 +88,10 @@
},
/turf/floor/plating,
/area/ministation/maint/l4central)
+"kH" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"kV" = (
/obj/machinery/atmospherics/pipe/simple/hidden/universal{
dir = 4
@@ -40459,7 +40463,7 @@ aa
aa
aa
aa
-aa
+kH
aa
aa
aa
diff --git a/maps/ministation/ministation.dm b/maps/ministation/ministation.dm
index 2ecca91fa60..fca80d6d647 100644
--- a/maps/ministation/ministation.dm
+++ b/maps/ministation/ministation.dm
@@ -15,31 +15,39 @@ Twice...
#include "../../code/unit_tests/offset_tests.dm"
#endif
+ #include "../random_ruins/exoplanet_ruins/playablecolony/playablecolony.dm"
+
+ #include "../../mods/content/mundane.dm"
+ #include "../../mods/content/scaling_descriptors.dm"
+
+ #include "../../mods/content/bigpharma/_bigpharma.dme"
+ #include "../../mods/content/corporate/_corporate.dme"
+ #include "../../mods/content/government/_government.dme"
+ #include "../../mods/content/matchmaking/_matchmaking.dme"
+ #include "../../mods/content/modern_earth/_modern_earth.dme"
+ #include "../../mods/content/mouse_highlights/_mouse_highlight.dme"
+ #include "../../mods/content/pheromones/_pheromones.dme"
+ #include "../../mods/content/psionics/_psionics.dme"
+ #include "../../mods/content/standard_jobs/_standard_jobs.dme"
+ #include "../../mods/content/supermatter/_supermatter.dme"
+ #include "../../mods/content/xenobiology/_xenobiology.dme"
+
#include "../../mods/gamemodes/cult/_cult.dme"
#include "../../mods/gamemodes/heist/_heist.dme"
#include "../../mods/gamemodes/ninja/_ninja.dme"
#include "../../mods/gamemodes/revolution/_revolution.dme"
#include "../../mods/gamemodes/traitor/_traitor.dme"
#include "../../mods/gamemodes/spyvspy/_spyvspy.dme"
- #include "../../mods/gamemodes/mixed/_mixed.dme"
+ #include "../../mods/gamemodes/mixed.dm"
- #include "../random_ruins/exoplanet_ruins/playablecolony/playablecolony.dm"
+ #include "../../mods/mobs/dionaea/_dionaea.dme"
+ #include "../../mods/mobs/borers/_borers.dme"
- #include "../../mods/content/standard_jobs/_standard_jobs.dme"
- #include "../../mods/content/xenobiology/_xenobiology.dme"
- #include "../../mods/content/corporate/_corporate.dme"
- #include "../../mods/content/matchmaking/_matchmaking.dme"
+ #include "../../mods/content/tabloids/_tabloids.dme"
#include "../../mods/species/ascent/_ascent.dme"
+ #include "../../mods/species/bayliens/_bayliens.dme"
#include "../../mods/species/neoavians/_neoavians.dme"
- #include "../../mods/content/pheromones/_pheromones.dme"
#include "../../mods/species/serpentid/_serpentid.dme"
- #include "../../mods/species/bayliens/_bayliens.dme"
- #include "../../mods/content/mundane.dm"
- #include "../../mods/content/bigpharma/_bigpharma.dme"
- #include "../../mods/content/government/_government.dme"
- #include "../../mods/content/modern_earth/_modern_earth.dme"
- #include "../../mods/content/mouse_highlights/_mouse_highlight.dme"
- #include "../../mods/content/scaling_descriptors.dm"
#include "ministation_antagonists.dm"
#include "ministation_areas.dm"
@@ -70,12 +78,6 @@ Twice...
#include "../away/yacht/yacht.dm"
#include "../away/liberia/liberia.dm"
- #include "../../mods/mobs/dionaea/_dionaea.dme"
- #include "../../mods/mobs/borers/_borers.dme"
-
- // Must come after borers for compatibility.
- #include "../../mods/content/psionics/_psionics.dme"
-
#include "ministation_overmap.dm"
#include "jobs/command.dm"
diff --git a/maps/ministation/ministation_jobs.dm b/maps/ministation/ministation_jobs.dm
index 92e28630c1f..17bb28b7b9e 100644
--- a/maps/ministation/ministation_jobs.dm
+++ b/maps/ministation/ministation_jobs.dm
@@ -1,25 +1,24 @@
/datum/map/ministation
- default_job_type = /datum/job/assistant/ministation
+ default_job_type = /datum/job/standard/assistant/ministation
default_department_type = /decl/department/civilian
- id_hud_icons = 'maps/ministation/hud.dmi'
allowed_jobs = list(
- /datum/job/assistant/ministation,
- /datum/job/bartender/ministation,
- /datum/job/captain/ministation,
- /datum/job/cargo_tech/ministation,
- /datum/job/robot,
- /datum/job/computer,
- /datum/job/detective/ministation,
- /datum/job/doctor/ministation,
- /datum/job/cmo/ministation,
- /datum/job/engineer/ministation,
- /datum/job/chief_engineer/ministation,
- /datum/job/hop/ministation,
- /datum/job/janitor/ministation,
- /datum/job/scientist/ministation,
- /datum/job/rd/ministation,
- /datum/job/officer/ministation,
- /datum/job/hos/ministation,
- /datum/job/librarian/ministation,
+ /datum/job/standard/assistant/ministation,
+ /datum/job/standard/bartender/ministation,
+ /datum/job/standard/captain/ministation,
+ /datum/job/standard/cargo_tech/ministation,
+ /datum/job/standard/robot,
+ /datum/job/standard/computer,
+ /datum/job/standard/detective/ministation,
+ /datum/job/standard/doctor/ministation,
+ /datum/job/standard/cmo/ministation,
+ /datum/job/standard/engineer/ministation,
+ /datum/job/standard/chief_engineer/ministation,
+ /datum/job/standard/hop/ministation,
+ /datum/job/standard/janitor/ministation,
+ /datum/job/standard/scientist/ministation,
+ /datum/job/standard/rd/ministation,
+ /datum/job/standard/officer/ministation,
+ /datum/job/standard/hos/ministation,
+ /datum/job/standard/librarian/ministation,
/datum/job/tradehouse_rep
)
\ No newline at end of file
diff --git a/maps/modpack_testing/modpack_testing.dm b/maps/modpack_testing/modpack_testing.dm
index f94fbbc844c..33b776920fb 100644
--- a/maps/modpack_testing/modpack_testing.dm
+++ b/maps/modpack_testing/modpack_testing.dm
@@ -3,45 +3,47 @@
#include "modpack_testing_lobby.dm"
#include "blank.dmm"
- #include "../../mods/gamemodes/cult/_cult.dme"
- #include "../../mods/gamemodes/heist/_heist.dme"
- #include "../../mods/gamemodes/meteor/_meteor.dme"
- #include "../../mods/gamemodes/ninja/_ninja.dme"
- #include "../../mods/gamemodes/revolution/_revolution.dme"
- #include "../../mods/gamemodes/traitor/_traitor.dme"
- #include "../../mods/gamemodes/spyvspy/_spyvspy.dme"
- #include "../../mods/gamemodes/mixed/_mixed.dme"
-
#include "../../mods/content/mundane.dm"
#include "../../mods/content/scaling_descriptors.dm"
+ #include "../../mods/content/standard_jobs/_standard_jobs.dme"
+ #include "../../mods/content/tabloids/_tabloids.dme"
- #include "../../mods/content/dungeon_loot/_dungeon_loot.dme"
#include "../../mods/content/bigpharma/_bigpharma.dme"
#include "../../mods/content/byond_membership/_byond_membership.dm"
#include "../../mods/content/corporate/_corporate.dme"
+ #include "../../mods/content/dungeon_loot/_dungeon_loot.dme"
+ #include "../../mods/content/fantasy/_fantasy.dme"
#include "../../mods/content/generic_shuttles/_generic_shuttles.dme"
#include "../../mods/content/government/_government.dme"
+ #include "../../mods/content/inertia/_inertia.dme"
#include "../../mods/content/matchmaking/_matchmaking.dme"
#include "../../mods/content/modern_earth/_modern_earth.dme"
#include "../../mods/content/mouse_highlights/_mouse_highlight.dme"
+ #include "../../mods/content/pheromones/_pheromones.dme"
+ #include "../../mods/content/psionics/_psionics.dme"
#include "../../mods/content/shackles/_shackles.dme"
+ #include "../../mods/content/supermatter/_supermatter.dme"
#include "../../mods/content/xenobiology/_xenobiology.dme"
- #include "../../mods/content/pheromones/_pheromones.dme"
- #include "../../mods/species/drakes/_drakes.dme" // include before _fantasy.dme so overrides work
- #include "../../mods/content/fantasy/_fantasy.dme"
- #include "../../mods/content/inertia/_inertia.dme"
+ #include "../../mods/content/item_sharpening/_item_sharpening.dme"
- #include "../../mods/mobs/dionaea/_dionaea.dme"
- #include "../../mods/mobs/borers/_borers.dme"
+ #include "../../mods/gamemodes/cult/_cult.dme"
+ #include "../../mods/gamemodes/heist/_heist.dme"
+ #include "../../mods/gamemodes/meteor/_meteor.dme"
+ #include "../../mods/gamemodes/ninja/_ninja.dme"
+ #include "../../mods/gamemodes/revolution/_revolution.dme"
+ #include "../../mods/gamemodes/traitor/_traitor.dme"
+ #include "../../mods/gamemodes/spyvspy/_spyvspy.dme"
+ #include "../../mods/gamemodes/mixed.dm"
- // Must come after borers for compatibility.
- #include "../../mods/content/psionics/_psionics.dme"
+ #include "../../mods/mobs/borers/_borers.dme"
+ #include "../../mods/mobs/dionaea/_dionaea.dme"
- #include "../../mods/species/serpentid/_serpentid.dme"
#include "../../mods/species/ascent/_ascent.dme"
+ #include "../../mods/species/bayliens/_bayliens.dme"
+ #include "../../mods/species/drakes/_drakes.dme"
#include "../../mods/species/neoavians/_neoavians.dme"
+ #include "../../mods/species/serpentid/_serpentid.dme"
#include "../../mods/species/utility_frames/_utility_frames.dme"
- #include "../../mods/species/bayliens/_bayliens.dme"
#include "../../mods/species/vox/_vox.dme"
#define USING_MAP_DATUM /datum/map/modpack_testing
diff --git a/maps/modpack_testing/modpack_testing_define.dm b/maps/modpack_testing/modpack_testing_define.dm
index f5b09decd1f..8ed4837727c 100644
--- a/maps/modpack_testing/modpack_testing_define.dm
+++ b/maps/modpack_testing/modpack_testing_define.dm
@@ -4,3 +4,7 @@
path = "modpack_testing"
allowed_latejoin_spawns = list()
default_spawn = null
+ votable = FALSE
+
+/datum/map/modpack_testing/validate()
+ return TRUE // Do not check for level lists, this is not a playable map.
diff --git a/maps/planets/test_planet/neutralia-2.dmm b/maps/planets/test_planet/neutralia-2.dmm
index 8b5e82e76e8..cc84b991ea8 100644
--- a/maps/planets/test_planet/neutralia-2.dmm
+++ b/maps/planets/test_planet/neutralia-2.dmm
@@ -3,11 +3,11 @@
/turf/unsimulated/mineral,
/area/exoplanet/underground/neutralia)
"b" = (
-/turf/floor,
+/turf/floor/barren,
/area/exoplanet/underground/neutralia)
"c" = (
/obj/abstract/level_data_spawner/neutralia/underground,
-/turf/floor,
+/turf/floor/barren,
/area/exoplanet/underground/neutralia)
(1,1,1) = {"
diff --git a/maps/planets/test_planet/neutralia-3.dmm b/maps/planets/test_planet/neutralia-3.dmm
index 768772a0f91..f7d1ff768ee 100644
--- a/maps/planets/test_planet/neutralia-3.dmm
+++ b/maps/planets/test_planet/neutralia-3.dmm
@@ -1,6 +1,6 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
-/turf/floor,
+/turf/floor/barren,
/area/exoplanet/neutralia)
"b" = (
/turf/unsimulated/mineral,
@@ -17,15 +17,15 @@
/area/exoplanet/neutralia)
"j" = (
/obj/abstract/landmark/exoplanet_spawn/large_plant,
-/turf/floor,
+/turf/floor/barren,
/area/exoplanet/neutralia)
"o" = (
/obj/abstract/landmark/exoplanet_spawn/animal,
-/turf/floor,
+/turf/floor/barren,
/area/exoplanet/neutralia)
"x" = (
/obj/abstract/landmark/exoplanet_spawn/plant,
-/turf/floor,
+/turf/floor/barren,
/area/exoplanet/neutralia)
(1,1,1) = {"
diff --git a/maps/planets/test_planet/test_planet.dm b/maps/planets/test_planet/test_planet.dm
index 159722fde19..83c42703e65 100644
--- a/maps/planets/test_planet/test_planet.dm
+++ b/maps/planets/test_planet/test_planet.dm
@@ -131,14 +131,14 @@
name = "neutralia surface"
level_id = NEUTRALIA_SURFACE_LEVEL_ID
base_area = /area/exoplanet/neutralia
- base_turf = /turf/floor
+ base_turf = /turf/floor/barren
border_filler = /turf/unsimulated/dark_filler
/datum/level_data/planetoid/neutralia/underground
name = "neutralia underground"
level_id = "neutralia_underground"
base_area = /area/exoplanet/underground/neutralia
- base_turf = /turf/floor
+ base_turf = /turf/floor/barren
border_filler = /turf/unsimulated/mineral
/datum/level_data/planetoid/neutralia/underground/bottom
diff --git a/maps/planets_testing/planets_testing_define.dm b/maps/planets_testing/planets_testing_define.dm
index c82359943fd..8380842377f 100644
--- a/maps/planets_testing/planets_testing_define.dm
+++ b/maps/planets_testing/planets_testing_define.dm
@@ -3,8 +3,12 @@
full_name = "Planets Testing"
path = "planets_testing"
overmap_ids = list(OVERMAP_ID_SPACE)
- allowed_latejoin_spawns = list()
default_spawn = null
+ votable = FALSE
+ allowed_latejoin_spawns = list()
+
+/datum/map/planet_testing/validate()
+ return FALSE // Testing map, do not validate levels.
// Set the observer spawn to include every flag so that CI flag checks pass.
/decl/spawnpoint/observer
diff --git a/maps/random_ruins/space_ruins/space_ruins.dm b/maps/random_ruins/space_ruins/space_ruins.dm
index 6310e536a7e..460f5a6995a 100644
--- a/maps/random_ruins/space_ruins/space_ruins.dm
+++ b/maps/random_ruins/space_ruins/space_ruins.dm
@@ -5,6 +5,7 @@
material = /decl/material/solid/gemstone/diamond
/datum/map_template/ruin/space
+ abstract_type = /datum/map_template/ruin/space
template_categories = list(MAP_TEMPLATE_CATEGORY_SPACE)
prefix = "maps/random_ruins/space_ruins/"
cost = 1
diff --git a/maps/shaded_hills/areas/_areas.dm b/maps/shaded_hills/areas/_areas.dm
index b33bf376d84..e31eff6ce28 100644
--- a/maps/shaded_hills/areas/_areas.dm
+++ b/maps/shaded_hills/areas/_areas.dm
@@ -20,13 +20,6 @@
)
sound_env = GENERIC
ambience = list()
- var/list/additional_fishing_results
-
-/area/shaded_hills/Initialize()
- if(additional_fishing_results)
- for(var/fish in additional_fishing_results)
- fishing_results[fish] = additional_fishing_results[fish]
- . = ..()
/area/shaded_hills/outside
name = "\improper Grasslands"
diff --git a/maps/shaded_hills/areas/grassland.dm b/maps/shaded_hills/areas/grassland.dm
index 9b7de6659e1..803f9a5e920 100644
--- a/maps/shaded_hills/areas/grassland.dm
+++ b/maps/shaded_hills/areas/grassland.dm
@@ -34,12 +34,15 @@
color = COLOR_BLUE
description = "The soft susurration of running water mingles with the hum of insects and croak of frogs."
area_blurb_category = /area/shaded_hills/outside/river
- additional_fishing_results = list(
+
+/area/shaded_hills/outside/river/get_additional_fishing_results()
+ var/static/list/additional_fishing_results = list(
/mob/living/simple_animal/aquatic/fish/large = 5,
/mob/living/simple_animal/aquatic/fish/large/salmon = 5,
/mob/living/simple_animal/aquatic/fish/large/trout = 5,
/mob/living/simple_animal/aquatic/fish/large/pike = 3
)
+ return additional_fishing_results
/area/shaded_hills/caves
name = "\improper Deep Tunnels"
diff --git a/maps/shaded_hills/areas/woods.dm b/maps/shaded_hills/areas/woods.dm
index 0fd8dca0685..73c262300a6 100644
--- a/maps/shaded_hills/areas/woods.dm
+++ b/maps/shaded_hills/areas/woods.dm
@@ -4,13 +4,16 @@
/area/shaded_hills/outside/river/lake
name = "Woodland Lake"
- additional_fishing_results = list(
- /mob/living/simple_animal/aquatic/fish/large/bass = 5,
- /mob/living/simple_animal/aquatic/fish/large/trout = 5,
- /mob/living/simple_animal/aquatic/fish/large/javelin = 5,
- /mob/living/simple_animal/hostile/aquatic/carp = 3,
- /mob/living/simple_animal/aquatic/fish/large/koi = 1
+
+/area/shaded_hills/outside/river/lake/get_additional_fishing_results()
+ var/static/list/additional_fishing_results = list(
+ /mob/living/simple_animal/aquatic/fish/large/bass = 5,
+ /mob/living/simple_animal/aquatic/fish/large/trout = 5,
+ /mob/living/simple_animal/aquatic/fish/large/javelin = 5,
+ /mob/living/simple_animal/hostile/aquatic/carp = 3,
+ /mob/living/simple_animal/aquatic/fish/large/koi = 1
)
+ return additional_fishing_results
/area/shaded_hills/outside/woods
name = "Woodlands"
diff --git a/maps/shaded_hills/icons/hud.dmi b/maps/shaded_hills/icons/hud.dmi
deleted file mode 100644
index c8c2fcf8bd1..00000000000
Binary files a/maps/shaded_hills/icons/hud.dmi and /dev/null differ
diff --git a/maps/shaded_hills/jobs/_jobs.dm b/maps/shaded_hills/jobs/_jobs.dm
index 638c6ff7bf5..7eb2719f661 100644
--- a/maps/shaded_hills/jobs/_jobs.dm
+++ b/maps/shaded_hills/jobs/_jobs.dm
@@ -1,6 +1,5 @@
/datum/map/shaded_hills
- id_hud_icons = 'maps/shaded_hills/icons/hud.dmi'
- allowed_jobs = list(
+ allowed_jobs = list(
/datum/job/shaded_hills/visitor/traveller,
/datum/job/shaded_hills/visitor/traveller/learned,
/datum/job/shaded_hills/visitor/beggar_knight,
@@ -48,6 +47,7 @@
/datum/job/shaded_hills
abstract_type = /datum/job/shaded_hills
+ hud_icon_state = "hudblank"
department_types = list(
/decl/department/shaded_hills/locals
)
diff --git a/maps/shaded_hills/levels/_levels.dm b/maps/shaded_hills/levels/_levels.dm
index 9150072af91..dc2d59ddcc5 100644
--- a/maps/shaded_hills/levels/_levels.dm
+++ b/maps/shaded_hills/levels/_levels.dm
@@ -1,11 +1,11 @@
/obj/abstract/map_data/shaded_hills
height = 2
-/datum/level_data/player_level/shaded_hills
+/datum/level_data/main_level/shaded_hills
use_global_exterior_ambience = FALSE
base_area = null
base_turf = /turf/floor/dirt
- abstract_type = /datum/level_data/player_level/shaded_hills
+ abstract_type = /datum/level_data/main_level/shaded_hills
ambient_light_level = 1
ambient_light_color = "#f3e6ca"
strata = /decl/strata/shaded_hills
@@ -16,10 +16,6 @@
daycycle_type = /datum/daycycle/shaded_hills
daycycle_id = "daycycle_shaded_hills"
template_edge_padding = 0 // we use a strictly delineated subarea, no need for this guard
- var/submap_budget = 0
- var/submap_category = null
- var/submap_area
- var/list/mobs_to_spawn = list()
/datum/daycycle/shaded_hills
cycle_duration = 2 HOURS // 1 hour of daylight, 1 hour of night
@@ -29,33 +25,7 @@
time_in_cycle = rand(cycle_duration)
..()
-/datum/level_data/player_level/shaded_hills/get_subtemplate_areas(template_category, blacklist, whitelist)
- return submap_area ? (islist(submap_area) ? submap_area : list(submap_area)) : null
-
-/datum/level_data/player_level/shaded_hills/get_subtemplate_budget()
- return submap_budget
-
-/datum/level_data/player_level/shaded_hills/get_subtemplate_category()
- return submap_category
-
-/datum/level_data/player_level/shaded_hills/after_generate_level()
- . = ..()
- if(length(mobs_to_spawn))
- for(var/list/mob_category in mobs_to_spawn)
- var/list/mob_types = mob_category[1]
- var/mob_turf = mob_category[2]
- var/mob_count = mob_category[3]
- var/sanity = 1000
- while(mob_count && sanity)
- sanity--
- var/turf/place_mob_at = locate(rand(level_inner_min_x, level_inner_max_x), rand(level_inner_min_y, level_inner_max_y), level_z)
- if(istype(place_mob_at, mob_turf) && !(locate(/mob/living) in place_mob_at))
- var/mob_type = pickweight(mob_types)
- new mob_type(place_mob_at)
- mob_count--
- CHECK_TICK
-
-/datum/level_data/player_level/shaded_hills/grassland
+/datum/level_data/main_level/shaded_hills/grassland
name = "Shaded Hills - Grassland"
level_id = "shaded_hills_grassland"
level_generators = list(
@@ -68,11 +38,12 @@
"shaded_hills_swamp" = SOUTH,
"shaded_hills_downlands" = EAST
)
- submap_budget = 5
- submap_category = MAP_TEMPLATE_CATEGORY_SH_GRASSLAND
- submap_area = /area/shaded_hills/outside/poi
+ subtemplate_budget = 5
+ subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_GRASSLAND
+ subtemplate_area = /area/shaded_hills/outside/poi
- mobs_to_spawn = list(
+/datum/level_data/main_level/shaded_hills/grassland/get_mobs_to_populate_level()
+ var/static/list/mobs_to_spawn = list(
list(
list(
/mob/living/simple_animal/passive/mouse = 9,
@@ -85,9 +56,9 @@
10
)
)
+ return mobs_to_spawn
-
-/datum/level_data/player_level/shaded_hills/swamp
+/datum/level_data/main_level/shaded_hills/swamp
name = "Shaded Hills - Swamp"
level_id = "shaded_hills_swamp"
connected_levels = list(
@@ -97,11 +68,12 @@
/datum/random_map/noise/shaded_hills/swamp,
/datum/random_map/noise/forage/shaded_hills/swamp
)
- submap_budget = 5
- submap_category = MAP_TEMPLATE_CATEGORY_SH_SWAMP
- submap_area = /area/shaded_hills/outside/swamp/poi
+ subtemplate_budget = 5
+ subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_SWAMP
+ subtemplate_area = /area/shaded_hills/outside/swamp/poi
- mobs_to_spawn = list(
+/datum/level_data/main_level/shaded_hills/swamp/get_mobs_to_populate_level()
+ var/static/list/mobs_to_spawn = list(
list(
list(
/mob/living/simple_animal/passive/mouse = 6,
@@ -127,8 +99,9 @@
10
)
)
+ return mobs_to_spawn
-/datum/level_data/player_level/shaded_hills/woods
+/datum/level_data/main_level/shaded_hills/woods
name = "Shaded Hills - Woods"
level_id = "shaded_hills_woods"
connected_levels = list(
@@ -138,11 +111,12 @@
/datum/random_map/noise/shaded_hills/woods,
/datum/random_map/noise/forage/shaded_hills/woods
)
- submap_budget = 5
- submap_category = MAP_TEMPLATE_CATEGORY_SH_WOODS
- submap_area = /area/shaded_hills/outside/woods/poi
+ subtemplate_budget = 5
+ subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_WOODS
+ subtemplate_area = /area/shaded_hills/outside/woods/poi
- mobs_to_spawn = list(
+/datum/level_data/main_level/shaded_hills/woods/get_mobs_to_populate_level()
+ var/static/list/mobs_to_spawn = list(
list(
list(
/mob/living/simple_animal/passive/mouse = 6,
@@ -162,8 +136,9 @@
5
)
)
+ return mobs_to_spawn
-/datum/level_data/player_level/shaded_hills/downlands
+/datum/level_data/main_level/shaded_hills/downlands
name = "Shaded Hills - Downlands"
level_id = "shaded_hills_downlands"
level_generators = list(
@@ -173,50 +148,50 @@
connected_levels = list(
"shaded_hills_grassland" = WEST
)
- submap_budget = 5
- submap_category = MAP_TEMPLATE_CATEGORY_SH_DOWNLANDS
- submap_area = /area/shaded_hills/outside/downlands/poi
+ subtemplate_budget = 5
+ subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_DOWNLANDS
+ subtemplate_area = /area/shaded_hills/outside/downlands/poi
-/datum/level_data/player_level/shaded_hills/caverns
+/datum/level_data/main_level/shaded_hills/caverns
name = "Shaded Hills - Caverns"
level_id = "shaded_hills_caverns"
connected_levels = list(
"shaded_hills_dungeon" = EAST
)
- submap_budget = 5
- submap_category = MAP_TEMPLATE_CATEGORY_SH_CAVERNS
- submap_area = /area/shaded_hills/caves/deep/poi
+ subtemplate_budget = 5
+ subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_CAVERNS
+ subtemplate_area = /area/shaded_hills/caves/deep/poi
level_generators = list(
/datum/random_map/automata/cave_system/shaded_hills,
/datum/random_map/noise/ore/rich
)
base_turf = /turf/floor/rock/basalt
-/datum/level_data/player_level/shaded_hills/dungeon
+/datum/level_data/main_level/shaded_hills/dungeon
name = "Shaded Hills - Dungeon"
level_id = "shaded_hills_dungeon"
connected_levels = list(
"shaded_hills_caverns" = WEST
)
- submap_budget = 5
- submap_category = MAP_TEMPLATE_CATEGORY_SH_DUNGEON
- submap_area = /area/shaded_hills/caves/dungeon/poi
+ subtemplate_budget = 5
+ subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_DUNGEON
+ subtemplate_area = /area/shaded_hills/caves/dungeon/poi
base_turf = /turf/floor/rock/basalt
/obj/abstract/level_data_spawner/shaded_hills_grassland
- level_data_type = /datum/level_data/player_level/shaded_hills/grassland
+ level_data_type = /datum/level_data/main_level/shaded_hills/grassland
/obj/abstract/level_data_spawner/shaded_hills_swamp
- level_data_type = /datum/level_data/player_level/shaded_hills/swamp
+ level_data_type = /datum/level_data/main_level/shaded_hills/swamp
/obj/abstract/level_data_spawner/shaded_hills_woods
- level_data_type = /datum/level_data/player_level/shaded_hills/woods
+ level_data_type = /datum/level_data/main_level/shaded_hills/woods
/obj/abstract/level_data_spawner/shaded_hills_downlands
- level_data_type = /datum/level_data/player_level/shaded_hills/downlands
+ level_data_type = /datum/level_data/main_level/shaded_hills/downlands
/obj/abstract/level_data_spawner/shaded_hills_caverns
- level_data_type = /datum/level_data/player_level/shaded_hills/caverns
+ level_data_type = /datum/level_data/main_level/shaded_hills/caverns
/obj/abstract/level_data_spawner/shaded_hills_dungeon
- level_data_type = /datum/level_data/player_level/shaded_hills/dungeon
+ level_data_type = /datum/level_data/main_level/shaded_hills/dungeon
diff --git a/maps/shaded_hills/shaded_hills-dungeon.dmm b/maps/shaded_hills/shaded_hills-dungeon.dmm
index dc6ee7b450e..6d1ab918e6f 100644
--- a/maps/shaded_hills/shaded_hills-dungeon.dmm
+++ b/maps/shaded_hills/shaded_hills-dungeon.dmm
@@ -466,8 +466,6 @@
/area/shaded_hills/caves/dungeon/poi)
"GA" = (
/obj/structure/door/ebony,
-/obj/structure/door/ebony,
-/obj/structure/door/ebony,
/obj/abstract/landmark/lock_preset{
lock_preset_id = "sunken keep";
name = "sunken keep locked door"
diff --git a/maps/shaded_hills/shaded_hills-grassland.dmm b/maps/shaded_hills/shaded_hills-grassland.dmm
index b885f19cf3f..3adbafa7443 100644
--- a/maps/shaded_hills/shaded_hills-grassland.dmm
+++ b/maps/shaded_hills/shaded_hills-grassland.dmm
@@ -67,7 +67,7 @@
/area/shaded_hills/outside)
"kr" = (
/obj/item/tool/pickaxe/iron,
-/obj/item/tool/axe,
+/obj/item/tool/axe/iron,
/obj/abstract/exterior_marker/inside,
/obj/structure/closet/crate/chest/ebony,
/turf/floor/woven,
@@ -125,6 +125,10 @@
/obj/item/bag/sack,
/turf/floor/woven,
/area/shaded_hills/caves/unexplored/south)
+"qj" = (
+/obj/abstract/force_fluid_flow/north,
+/turf/floor/mud/water/deep,
+/area/shaded_hills/outside/river)
"qy" = (
/turf/wall/natural/basalt/shaded_hills,
/area/shaded_hills/caves/river)
@@ -136,6 +140,10 @@
"sS" = (
/turf/floor/mud/water,
/area/shaded_hills/caves/unexplored/south)
+"sT" = (
+/obj/abstract/force_fluid_flow/north,
+/turf/floor/mud/water/deep,
+/area/shaded_hills/outside/river)
"te" = (
/turf/unsimulated/mask,
/area/shaded_hills/caves/unexplored/south)
@@ -19512,7 +19520,7 @@ Gh
Gh
My
My
-My
+sT
lC
lC
lC
@@ -19529,8 +19537,8 @@ lC
lC
lC
lC
-My
-My
+qj
+sT
My
Gh
Gh
@@ -19572,12 +19580,12 @@ My
My
My
My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -19662,9 +19670,9 @@ Gh
Gh
Gh
My
-My
-My
-My
+sT
+sT
+sT
lC
lC
lC
@@ -19681,9 +19689,9 @@ lC
lC
lC
lC
-My
-My
-My
+sT
+sT
+sT
My
My
Gh
@@ -19717,23 +19725,23 @@ Gh
Gh
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
Gh
@@ -19753,14 +19761,14 @@ JN
My
My
My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -19771,15 +19779,15 @@ My
Gh
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
Gh
Gh
@@ -19814,9 +19822,9 @@ My
My
My
My
-My
-My
-My
+sT
+sT
+sT
lC
lC
lC
@@ -19833,11 +19841,11 @@ lC
lC
lC
lC
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
My
My
Gh
@@ -19867,27 +19875,27 @@ Gh
Gh
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -19901,38 +19909,38 @@ Gh
Xd
vX
Xd
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -19960,15 +19968,15 @@ My
My
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
lC
lC
lC
@@ -19986,12 +19994,12 @@ lC
lC
lC
My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -20017,6 +20025,13 @@ Gh
Gh
Gh
My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -20028,20 +20043,13 @@ My
My
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -20053,42 +20061,42 @@ My
Xd
vX
Xd
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
Gh
Gh
@@ -20107,19 +20115,19 @@ My
My
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
lC
lC
@@ -20140,15 +20148,15 @@ lC
Gh
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -20170,10 +20178,10 @@ Gh
Gh
My
My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
My
My
Gh
@@ -20190,57 +20198,57 @@ Gh
My
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
EE
EE
Xd
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
Gh
Gh
@@ -20252,21 +20260,21 @@ zp
zp
Gh
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -20299,18 +20307,18 @@ My
My
My
My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
My
Gh
Gh
@@ -20345,38 +20353,38 @@ Gh
My
My
My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
JN
EE
EE
EE
JN
+sT
+sT
My
My
My
+sT
+sT
+sT
My
My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
Gh
My
@@ -20404,14 +20412,14 @@ zp
Gh
Gh
My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
My
My
@@ -20456,14 +20464,14 @@ My
My
My
My
-My
-My
-My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
+sT
+sT
+sT
My
Gh
Gh
@@ -20501,15 +20509,15 @@ My
My
My
My
-My
-My
-My
-My
-My
+sT
+sT
+sT
+sT
+sT
EE
vX
EE
-My
+sT
My
My
Gh
@@ -20524,9 +20532,9 @@ My
My
My
My
-My
-My
-My
+sT
+sT
+sT
My
My
Gh
diff --git a/maps/shaded_hills/shaded_hills-woods.dmm b/maps/shaded_hills/shaded_hills-woods.dmm
index 66168daa63f..06a9695d634 100644
--- a/maps/shaded_hills/shaded_hills-woods.dmm
+++ b/maps/shaded_hills/shaded_hills-woods.dmm
@@ -71,9 +71,6 @@
"te" = (
/turf/floor/rock/basalt,
/area/shaded_hills/outside/woods)
-"ul" = (
-/turf/floor/mud/water,
-/area/shaded_hills/outside/river/woods)
"uA" = (
/turf/unsimulated/dark_filler,
/area/shaded_hills/outside/river/woods)
@@ -112,6 +109,9 @@
"DX" = (
/turf/floor/mud/water/deep,
/area/shaded_hills/caves/river/woods)
+"En" = (
+/turf/floor/mud/water,
+/area/shaded_hills/outside/river/woods)
"ES" = (
/turf/floor/grass,
/area/shaded_hills/outside/river/woods)
@@ -178,8 +178,9 @@
/turf/floor/wood/rough/walnut,
/area/shaded_hills/forester_hut)
"PO" = (
+/obj/abstract/force_fluid_flow/north,
/turf/floor/mud/water/deep,
-/area/shaded_hills/outside/river/woods)
+/area/shaded_hills/outside/river/lake)
"SI" = (
/turf/wall/log/walnut,
/area/shaded_hills/forester_hut)
@@ -199,6 +200,10 @@
/obj/abstract/landmark/start/shaded_hills/traveller,
/turf/floor/barren,
/area/shaded_hills/caves/woods)
+"Wo" = (
+/obj/abstract/force_fluid_flow/north,
+/turf/floor/mud/water/deep,
+/area/shaded_hills/outside/river/woods)
"Xt" = (
/turf/floor/mud,
/area/shaded_hills/caves/woods)
@@ -209,6 +214,9 @@
"YO" = (
/turf/unsimulated/mask,
/area/shaded_hills/outside/river/woods)
+"Zo" = (
+/turf/floor/mud/water/deep,
+/area/shaded_hills/outside/river/woods)
"Zs" = (
/obj/structure/wall_sconce/lantern{
dir = 1;
@@ -15657,11 +15665,11 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
zp
zp
zp
@@ -15806,21 +15814,21 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -15953,29 +15961,29 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
kx
kx
@@ -16103,32 +16111,32 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
dp
JI
AN
@@ -16254,34 +16262,34 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
JI
AN
zp
@@ -16405,35 +16413,35 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
JI
AN
zp
@@ -16556,39 +16564,39 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
JI
AN
-ul
+En
zp
zp
zp
@@ -16707,41 +16715,41 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
dp
JI
AN
dp
-ul
+En
zp
zp
zp
@@ -16857,44 +16865,44 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+En
+En
+En
+En
JI
AN
-ul
-ul
-ul
+En
+En
+En
zp
zp
zp
@@ -17008,45 +17016,45 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+En
JI
AN
-ul
-ul
-ul
+En
+En
+En
zp
zp
zp
@@ -17158,49 +17166,49 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
JI
AN
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
zp
zp
zp
@@ -17310,50 +17318,50 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
dp
JI
AN
dp
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
zp
zp
zp
@@ -17460,54 +17468,54 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+Zo
+En
+En
+Zo
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
JI
AN
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+Zo
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -17611,57 +17619,57 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
JI
AN
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -17748,7 +17756,7 @@ ma
ma
ma
ma
-ul
+En
zp
zp
zp
@@ -17762,60 +17770,60 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
JI
AN
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+Wo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -17834,9 +17842,9 @@ zp
zp
zp
zp
-ul
-ul
-ul
+En
+En
+En
zp
zp
zp
@@ -17901,9 +17909,9 @@ ma
ma
ma
ma
-ul
-ul
-ul
+En
+En
+En
zp
zp
zp
@@ -17913,63 +17921,63 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
dp
JI
AN
dp
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+Wo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -17983,15 +17991,15 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -18053,78 +18061,78 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
zp
zp
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
JI
AN
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -18132,19 +18140,19 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -18206,40 +18214,40 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -18250,55 +18258,55 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
JI
AN
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
uA
@@ -18359,37 +18367,37 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
zp
zp
zp
@@ -18402,56 +18410,56 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
+En
+En
+En
+En
+En
+En
+Zo
+Zo
JI
AN
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
uA
uA
@@ -18512,35 +18520,35 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -18555,56 +18563,56 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
dp
JI
AN
dp
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
uA
uA
uA
@@ -18664,34 +18672,34 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -18707,56 +18715,56 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
JI
AN
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
uA
uA
uA
@@ -18817,30 +18825,30 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
zp
zp
zp
@@ -18861,54 +18869,54 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
JI
AN
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
+En
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
uA
uA
uA
@@ -18969,30 +18977,30 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
zp
zp
zp
@@ -19014,53 +19022,53 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
+En
+En
+En
+En
JI
AN
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
+En
+En
+En
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+En
+En
+En
uA
uA
uA
@@ -19112,8 +19120,8 @@ hT
hT
hT
hT
-hT
-hT
+PO
+PO
hT
hT
ma
@@ -19122,28 +19130,28 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
zp
zp
zp
@@ -19168,51 +19176,51 @@ zp
zp
zp
zp
-ul
+En
dp
JI
AN
dp
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+Zo
+En
+En
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
uA
uA
uA
@@ -19262,40 +19270,40 @@ hT
hT
hT
hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-ma
-ma
-ma
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
PO
PO
PO
PO
PO
PO
-ul
-ul
-ul
-ul
-ul
+hT
+hT
+hT
+ma
+ma
+ma
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
zp
zp
zp
@@ -19324,47 +19332,47 @@ zp
zp
JI
AN
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
uA
uA
uA
@@ -19413,24 +19421,6 @@ hT
hT
hT
hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-ul
-ul
-ul
-PO
-PO
PO
PO
PO
@@ -19441,12 +19431,30 @@ PO
PO
PO
PO
-ul
-ul
-ul
-ul
-ul
-ul
+hT
+hT
+hT
+En
+En
+En
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -19477,46 +19485,46 @@ zp
JI
AN
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-ul
-ul
-ul
-PO
-PO
-PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Zo
+Zo
+En
+En
+En
+Zo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
uA
uA
uA
@@ -19564,20 +19572,6 @@ hT
hT
hT
hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
PO
PO
PO
@@ -19592,12 +19586,26 @@ PO
PO
PO
PO
-ul
-ul
-ul
-ul
-ul
-ul
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -19631,44 +19639,44 @@ AN
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
+Wo
+Wo
uA
uA
uA
@@ -19716,20 +19724,6 @@ hT
hT
hT
hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
PO
PO
PO
@@ -19743,13 +19737,27 @@ PO
PO
PO
PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+PO
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -19784,43 +19792,43 @@ dp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
-PO
-PO
+En
+En
+En
+En
+En
+En
+En
+Zo
+Zo
+Wo
uA
uA
uA
@@ -19868,20 +19876,6 @@ hT
hT
hT
hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
PO
PO
PO
@@ -19894,13 +19888,27 @@ PO
PO
PO
PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+PO
+PO
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Wo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -19940,16 +19948,16 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -19965,14 +19973,14 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-PO
+En
+En
+En
+En
+En
+En
+En
+Zo
uA
uA
uA
@@ -20020,19 +20028,6 @@ hT
hT
hT
hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
PO
PO
PO
@@ -20044,14 +20039,27 @@ PO
PO
PO
PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+PO
+PO
+Wo
+Wo
+Zo
+Zo
+Zo
+Wo
+Wo
+Wo
+Zo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -20095,9 +20103,9 @@ zp
zp
zp
zp
-ul
-ul
-ul
+En
+En
+En
zp
zp
zp
@@ -20119,12 +20127,12 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
uA
uA
uA
@@ -20173,36 +20181,36 @@ hT
hT
hT
hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
-hT
PO
PO
-ul
-ul
-ul
PO
PO
PO
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+PO
+PO
+PO
+PO
+PO
+hT
+hT
+Zo
+Zo
+En
+En
+En
+Zo
+Zo
+Zo
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -20273,10 +20281,10 @@ zp
zp
zp
zp
-ul
-ul
-ul
-ul
+En
+En
+En
+En
uA
uA
uA
@@ -20326,35 +20334,35 @@ hT
hT
hT
hT
+PO
+PO
+PO
+PO
+PO
hT
hT
hT
hT
hT
-hT
-hT
-hT
-hT
-hT
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -20427,8 +20435,8 @@ zp
zp
zp
zp
-ul
-ul
+En
+En
uA
uA
uA
@@ -20480,7 +20488,7 @@ hT
hT
hT
hT
-hT
+PO
hT
hT
ma
@@ -20488,24 +20496,24 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -20639,23 +20647,23 @@ ma
ma
ma
ma
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -20791,22 +20799,22 @@ ma
ma
ma
ma
-ul
-ul
-ul
+En
+En
+En
zp
zp
zp
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
-ul
+En
+En
+En
+En
+En
+En
+En
+En
+En
+En
zp
zp
zp
@@ -20942,8 +20950,8 @@ ma
ma
ma
ma
-ul
-ul
+En
+En
zp
zp
zp
@@ -20951,9 +20959,9 @@ zp
zp
zp
zp
-ul
-ul
-ul
+En
+En
+En
zp
zp
zp
@@ -21093,8 +21101,8 @@ ma
ma
ma
ma
-ul
-ul
+En
+En
zp
zp
zp
@@ -21244,7 +21252,7 @@ ma
ma
ma
ma
-ul
+En
zp
zp
zp
diff --git a/maps/shaded_hills/shaded_hills.dm b/maps/shaded_hills/shaded_hills.dm
index 1931b81ef34..ae5cb32e946 100644
--- a/maps/shaded_hills/shaded_hills.dm
+++ b/maps/shaded_hills/shaded_hills.dm
@@ -5,6 +5,7 @@
#include "../../mods/content/mouse_highlights/_mouse_highlight.dme"
#include "../../mods/content/scaling_descriptors.dm"
#include "../../mods/species/drakes/_drakes.dme" // include before _fantasy.dme so overrides work
+ #include "../../mods/content/item_sharpening/_item_sharpening.dme"
#include "../../mods/content/fantasy/_fantasy.dme"
#include "areas/_areas.dm"
@@ -20,18 +21,6 @@
#include "jobs/visitors.dm"
#include "jobs/wilderness.dm"
- #include "submaps/_submaps.dm"
- #include "submaps/downlands/_downlands.dm"
- #include "submaps/grassland/_grassland.dm"
- #include "submaps/swamp/_swamp.dm"
- #include "submaps/woods/_woods.dm"
- #include "submaps/woods/bear_den/bear_den.dm"
- #include "submaps/woods/chemistry_shack/chemistry_shack.dm"
- #include "submaps/woods/fairy_rings/fairy_rings.dm"
- #include "submaps/woods/fox_den/fox_den.dm"
- #include "submaps/woods/hunter_camp/hunter_camp.dm"
- #include "submaps/woods/old_cabin/old_cabin.dm"
-
#include "levels/_levels.dm"
#include "levels/random_map.dm"
#include "levels/strata.dm"
diff --git a/maps/shaded_hills/submaps/_submaps.dm b/maps/shaded_hills/submaps/_submaps.dm
deleted file mode 100644
index 14b3948c927..00000000000
--- a/maps/shaded_hills/submaps/_submaps.dm
+++ /dev/null
@@ -1,23 +0,0 @@
-#define MAP_TEMPLATE_CATEGORY_SH_GRASSLAND "template_sh_grassland"
-#define MAP_TEMPLATE_CATEGORY_SH_SWAMP "template_sh_swamp"
-#define MAP_TEMPLATE_CATEGORY_SH_WOODS "template_sh_woods"
-#define MAP_TEMPLATE_CATEGORY_SH_DOWNLANDS "template_sh_downlands"
-#define MAP_TEMPLATE_CATEGORY_SH_DUNGEON "template_sh_dungeon"
-#define MAP_TEMPLATE_CATEGORY_SH_CAVERNS "template_sh_caverns"
-
-/datum/map_template/shaded_hills
- abstract_type = /datum/map_template/shaded_hills
- template_parent_type = /datum/map_template/shaded_hills
- template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS
- area_usage_test_exempted_root_areas = list(
- /area/shaded_hills/outside/point_of_interest
- )
- var/cost = 1
-
-/datum/map_template/shaded_hills/get_template_cost()
- return cost
-
-/area/shaded_hills/outside/point_of_interest
- name = "Point Of Interest"
- description = null
- area_blurb_category = /area/shaded_hills/outside/point_of_interest
diff --git a/maps/shaded_hills/submaps/downlands/_downlands.dm b/maps/shaded_hills/submaps/downlands/_downlands.dm
deleted file mode 100644
index 22721f265b8..00000000000
--- a/maps/shaded_hills/submaps/downlands/_downlands.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-/datum/map_template/shaded_hills/downlands
- abstract_type = /datum/map_template/shaded_hills/downlands
- template_categories = list(MAP_TEMPLATE_CATEGORY_SH_DOWNLANDS)
- template_parent_type = /datum/map_template/shaded_hills/downlands
-
-/datum/map_template/shaded_hills/dungeon
- abstract_type = /datum/map_template/shaded_hills/dungeon
- template_categories = list(MAP_TEMPLATE_CATEGORY_SH_DUNGEON)
- template_parent_type = /datum/map_template/shaded_hills/dungeon
diff --git a/maps/shaded_hills/submaps/grassland/_grassland.dm b/maps/shaded_hills/submaps/grassland/_grassland.dm
deleted file mode 100644
index 39f0722666b..00000000000
--- a/maps/shaded_hills/submaps/grassland/_grassland.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-/datum/map_template/shaded_hills/grassland
- abstract_type = /datum/map_template/shaded_hills/grassland
- template_categories = list(MAP_TEMPLATE_CATEGORY_SH_GRASSLAND)
- template_parent_type = /datum/map_template/shaded_hills/grassland
-
-/datum/map_template/shaded_hills/cavern
- abstract_type = /datum/map_template/shaded_hills/cavern
- template_categories = list(MAP_TEMPLATE_CATEGORY_SH_CAVERNS)
- template_parent_type = /datum/map_template/shaded_hills/cavern
\ No newline at end of file
diff --git a/maps/shaded_hills/submaps/swamp/_swamp.dm b/maps/shaded_hills/submaps/swamp/_swamp.dm
deleted file mode 100644
index 9f4f963c1ee..00000000000
--- a/maps/shaded_hills/submaps/swamp/_swamp.dm
+++ /dev/null
@@ -1,4 +0,0 @@
-/datum/map_template/shaded_hills/swamp
- abstract_type = /datum/map_template/shaded_hills/swamp
- template_categories = list(MAP_TEMPLATE_CATEGORY_SH_SWAMP)
- template_parent_type = /datum/map_template/shaded_hills/swamp
\ No newline at end of file
diff --git a/maps/shaded_hills/submaps/woods/_woods.dm b/maps/shaded_hills/submaps/woods/_woods.dm
deleted file mode 100644
index 0baea8f75c5..00000000000
--- a/maps/shaded_hills/submaps/woods/_woods.dm
+++ /dev/null
@@ -1,4 +0,0 @@
-/datum/map_template/shaded_hills/woods
- abstract_type = /datum/map_template/shaded_hills/woods
- template_categories = list(MAP_TEMPLATE_CATEGORY_SH_WOODS)
- template_parent_type = /datum/map_template/shaded_hills/woods
diff --git a/maps/shaded_hills/submaps/woods/bear_den/bear_den.dm b/maps/shaded_hills/submaps/woods/bear_den/bear_den.dm
deleted file mode 100644
index ee4d7f30849..00000000000
--- a/maps/shaded_hills/submaps/woods/bear_den/bear_den.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/map_template/shaded_hills/woods/bear_den
- name = "bear den"
- mappaths = list("maps/shaded_hills/submaps/woods/bear_den/bear_den.dmm")
-
-/area/shaded_hills/outside/point_of_interest/bear_den
- name = "Point of Interest - Bear Den"
diff --git a/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dm b/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dm
deleted file mode 100644
index 19de9faa978..00000000000
--- a/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/map_template/shaded_hills/woods/chemistry_shack
- name = "chemistry shack"
- mappaths = list("maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dmm")
-
-/area/shaded_hills/outside/point_of_interest/chemistry_shack
- name = "Point of Interest - Chemistry Shack"
diff --git a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_rings.dm b/maps/shaded_hills/submaps/woods/fairy_rings/fairy_rings.dm
deleted file mode 100644
index 89ec23e18dc..00000000000
--- a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_rings.dm
+++ /dev/null
@@ -1,15 +0,0 @@
-/datum/map_template/shaded_hills/woods/fairy_ring
- name = "fairy ring"
- mappaths = list("maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring.dmm")
- template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS | TEMPLATE_FLAG_ALLOW_DUPLICATES | TEMPLATE_FLAG_GENERIC_REPEATABLE
- template_categories = list(
- MAP_TEMPLATE_CATEGORY_SH_WOODS
- )
- area_coherency_test_exempt_areas = list(/area/shaded_hills/outside/point_of_interest/fairy_ring)
-
-/datum/map_template/shaded_hills/woods/fairy_ring/glowing
- name = "glowing fairy ring"
- mappaths = list("maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring_glowing.dmm")
-
-/area/shaded_hills/outside/point_of_interest/fairy_ring
- name = "Point of Interest - Fairy Ring"
diff --git a/maps/shaded_hills/submaps/woods/fox_den/fox_den.dm b/maps/shaded_hills/submaps/woods/fox_den/fox_den.dm
deleted file mode 100644
index de7b5dcfd5f..00000000000
--- a/maps/shaded_hills/submaps/woods/fox_den/fox_den.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/map_template/shaded_hills/woods/fox_den
- name = "fox den"
- mappaths = list("maps/shaded_hills/submaps/woods/fox_den/fox_den.dmm")
-
-/area/shaded_hills/outside/point_of_interest/fox_den
- name = "Point of Interest - Fox Den"
diff --git a/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dm b/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dm
deleted file mode 100644
index 3cf4e2edc68..00000000000
--- a/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/map_template/shaded_hills/woods/hunter_camp
- name = "hunter camp"
- mappaths = list("maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dmm")
-
-/area/shaded_hills/outside/point_of_interest/hunter_camp
- name = "Point of Interest - Hunter Camp"
diff --git a/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dm b/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dm
deleted file mode 100644
index 2d56e5161b3..00000000000
--- a/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/map_template/shaded_hills/woods/old_cabin
- name = "old cabin"
- mappaths = list("maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dmm")
-
-/area/shaded_hills/outside/point_of_interest/old_cabin
- name = "Point of Interest - Old Cabin"
diff --git a/maps/tradeship/jobs/_goals.dm b/maps/tradeship/jobs/_goals.dm
index e9d719bd211..ac7cc4422dc 100644
--- a/maps/tradeship/jobs/_goals.dm
+++ b/maps/tradeship/jobs/_goals.dm
@@ -26,7 +26,7 @@ var/global/list/tradeship_paperwork_end_areas = list()
/datum/goal/department/paperwork/tradeship
paperwork_types = list(/obj/item/paperwork/tradeship)
signatory_job_list = list(
- /datum/job/captain/tradeship,
+ /datum/job/standard/captain/tradeship,
/datum/job/tradeship_first_mate
)
diff --git a/maps/tradeship/jobs/civilian.dm b/maps/tradeship/jobs/civilian.dm
index f491bc953a3..edb03def44a 100644
--- a/maps/tradeship/jobs/civilian.dm
+++ b/maps/tradeship/jobs/civilian.dm
@@ -1,4 +1,4 @@
-/datum/job/assistant/tradeship
+/datum/job/standard/assistant/tradeship
title = "Deck Hand"
supervisors = "literally everyone, you bottom feeder"
outfit_type = /decl/outfit/job/tradeship/hand
diff --git a/maps/tradeship/jobs/command.dm b/maps/tradeship/jobs/command.dm
index 0d124a9841e..3647a632760 100644
--- a/maps/tradeship/jobs/command.dm
+++ b/maps/tradeship/jobs/command.dm
@@ -1,4 +1,4 @@
-/datum/job/captain/tradeship
+/datum/job/standard/captain/tradeship
title = "Captain"
supervisors = "your profit margin, your conscience, and the Trademaster"
outfit_type = /decl/outfit/job/tradeship/captain
@@ -11,7 +11,7 @@
ideal_character_age = 70
forced_spawnpoint = /decl/spawnpoint/cryo/captain
-/datum/job/captain/tradeship/equip_job(var/mob/living/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade)
+/datum/job/standard/captain/tradeship/equip_job(var/mob/living/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade)
. = ..()
if(H)
H.verbs |= /mob/proc/tradehouse_rename_ship
@@ -55,6 +55,7 @@
/datum/job/tradeship_first_mate
title = "First Mate"
supervisors = "the Captain"
+ hud_icon = 'maps/tradeship/hud.dmi'
outfit_type = /decl/outfit/job/tradeship/mate
head_position = 1
department_types = list(
diff --git a/maps/tradeship/jobs/engineering.dm b/maps/tradeship/jobs/engineering.dm
index 1938f034a31..62a9c6659c4 100644
--- a/maps/tradeship/jobs/engineering.dm
+++ b/maps/tradeship/jobs/engineering.dm
@@ -1,10 +1,10 @@
-/datum/job/engineer/tradeship
+/datum/job/standard/engineer/tradeship
title = "Junior Engineer"
supervisors = "the Head Engineer"
outfit_type = /decl/outfit/job/tradeship/hand/engine
alt_titles = list()
-/datum/job/chief_engineer/tradeship
+/datum/job/standard/chief_engineer/tradeship
title = "Head Engineer"
outfit_type = /decl/outfit/job/tradeship/chief_engineer
alt_titles = list()
diff --git a/maps/tradeship/jobs/medical.dm b/maps/tradeship/jobs/medical.dm
index 03b480321b8..bedcf558453 100644
--- a/maps/tradeship/jobs/medical.dm
+++ b/maps/tradeship/jobs/medical.dm
@@ -1,4 +1,4 @@
-/datum/job/doctor/tradeship
+/datum/job/standard/doctor/tradeship
title = "Junior Doctor"
supervisors = "the Head Doctor and the Captain"
alt_titles = list()
@@ -33,7 +33,7 @@
outfit_type = /decl/outfit/job/tradeship/doc/junior
event_categories = list(ASSIGNMENT_MEDICAL)
-/datum/job/cmo/tradeship
+/datum/job/standard/cmo/tradeship
title = "Head Doctor"
supervisors = "the Captain and your own ethics"
outfit_type = /decl/outfit/job/tradeship/doc
diff --git a/maps/tradeship/jobs/science.dm b/maps/tradeship/jobs/science.dm
index c14bb9e5b92..d941587b27d 100644
--- a/maps/tradeship/jobs/science.dm
+++ b/maps/tradeship/jobs/science.dm
@@ -1,4 +1,4 @@
-/datum/job/scientist/tradeship
+/datum/job/standard/scientist/tradeship
title = "Junior Researcher"
supervisors = "the Head Researcher and the Captain"
total_positions = 2
@@ -8,7 +8,7 @@
// Smaller crew, more points.
skill_points = 24
-/datum/job/rd/tradeship
+/datum/job/standard/rd/tradeship
title = "Head Researcher"
alt_titles = list()
outfit_type = /decl/outfit/job/tradeship/hand/researcher
diff --git a/maps/tradeship/tradeship-0.dmm b/maps/tradeship/tradeship-0.dmm
index f68f5a6eeb9..625326ea625 100644
--- a/maps/tradeship/tradeship-0.dmm
+++ b/maps/tradeship/tradeship-0.dmm
@@ -1009,7 +1009,7 @@
"dN" = (
/obj/machinery/portable_atmospherics/hydroponics/soil,
/obj/item/tool/hoe/mini,
-/turf/floor,
+/turf/floor/plating/dirt,
/area/ship/trade/aft_port_underside_maint)
"en" = (
/turf/floor/laminate/walnut,
@@ -1179,7 +1179,7 @@
icon_state = "4-8"
},
/obj/machinery/portable_atmospherics/hydroponics/soil,
-/turf/floor,
+/turf/floor/plating/dirt,
/area/ship/trade/aft_port_underside_maint)
"lv" = (
/obj/effect/decal/cleanable/dirt/visible,
@@ -1197,6 +1197,10 @@
/obj/item/stack/cable_coil/random/three,
/turf/floor,
/area/ship/trade/loading_bay)
+"lG" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"ne" = (
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
@@ -1227,11 +1231,11 @@
/area/ship/trade/fore_port_underside_maint)
"oo" = (
/obj/machinery/portable_atmospherics/hydroponics/soil,
-/turf/floor,
+/turf/floor/plating/dirt,
/area/ship/trade/aft_starboard_underside_maint)
"or" = (
/obj/machinery/portable_atmospherics/hydroponics/soil,
-/turf/floor,
+/turf/floor/plating/dirt,
/area/ship/trade/aft_port_underside_maint)
"os" = (
/obj/structure/lattice,
@@ -1479,7 +1483,7 @@
/obj/machinery/light{
dir = 4
},
-/turf/floor,
+/turf/floor/plating/dirt,
/area/ship/trade/aft_port_underside_maint)
"xP" = (
/obj/structure/disposalpipe/segment{
@@ -2049,7 +2053,7 @@
/obj/machinery/light{
dir = 4
},
-/turf/floor,
+/turf/floor/plating/dirt,
/area/ship/trade/aft_starboard_underside_maint)
"QW" = (
/obj/item/stack/tile/floor/five,
@@ -3507,7 +3511,7 @@ aa
aa
aa
aa
-aa
+lG
aa
aa
aa
@@ -7360,7 +7364,7 @@ aa
aa
aa
aa
-aa
+lG
aa
aa
aa
diff --git a/maps/tradeship/tradeship-1.dmm b/maps/tradeship/tradeship-1.dmm
index 8a068ace688..fd28e95fb89 100644
--- a/maps/tradeship/tradeship-1.dmm
+++ b/maps/tradeship/tradeship-1.dmm
@@ -1763,6 +1763,10 @@
},
/turf/floor/plating,
/area/ship/trade/maintenance/eva)
+"eH" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"eJ" = (
/obj/machinery/vending/materials{
dir = 4
@@ -4589,7 +4593,7 @@ aa
aa
aa
aa
-aa
+eH
aa
aa
aa
@@ -8689,7 +8693,7 @@ aa
aa
aa
aa
-aa
+eH
aa
aa
aa
diff --git a/maps/tradeship/tradeship-2.dmm b/maps/tradeship/tradeship-2.dmm
index 2eb597a678c..0084e4d8d71 100644
--- a/maps/tradeship/tradeship-2.dmm
+++ b/maps/tradeship/tradeship-2.dmm
@@ -1282,7 +1282,7 @@
/obj/machinery/recharger,
/obj/structure/sign/poster{
pixel_x = 32;
- dir = 8
+ dir = 4
},
/obj/item/plate/tray,
/obj/item/circular_saw,
@@ -2002,6 +2002,15 @@
/obj/structure/cable{
icon_state = "4-8"
},
+/obj/item/chems/glass/beaker{
+ pixel_x = 5
+ },
+/obj/item/chems/condiment/small/peppermill{
+ pixel_x = 3
+ },
+/obj/item/chems/condiment/enzyme,
+/obj/item/chems/glass/rag,
+/obj/item/chems/cooking_vessel/pot,
/turf/floor/tiled,
/area/ship/trade/crew/kitchen)
"eQ" = (
@@ -4684,14 +4693,8 @@
"nH" = (
/obj/structure/table,
/obj/effect/floor_decal/corner/red/diagonal,
-/obj/item/chems/glass/beaker{
- pixel_x = 5
- },
-/obj/item/chems/condiment/small/peppermill{
- pixel_x = 3
- },
-/obj/item/chems/condiment/enzyme,
-/obj/item/chems/glass/rag,
+/obj/machinery/reagent_temperature,
+/obj/item/chems/cooking_vessel/skillet,
/turf/floor/tiled,
/area/ship/trade/crew/kitchen)
"nR" = (
@@ -5412,6 +5415,10 @@
},
/turf/floor/plating/airless,
/area/ship/trade/maintenance/engine/aft)
+"vN" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"vP" = (
/obj/machinery/light{
dir = 8;
@@ -9045,7 +9052,7 @@ aa
aa
aa
aa
-aa
+vN
aa
aa
aa
@@ -9259,7 +9266,7 @@ aa
aa
aa
aa
-aa
+vN
aa
aa
aa
@@ -13196,7 +13203,7 @@ aa
aa
aa
aa
-aa
+vN
aa
aa
aa
@@ -13639,7 +13646,7 @@ aa
aa
aa
aa
-aa
+vN
aa
aa
aa
diff --git a/maps/tradeship/tradeship-3.dmm b/maps/tradeship/tradeship-3.dmm
index 1a4f81e3fb3..bc596cfeecd 100644
--- a/maps/tradeship/tradeship-3.dmm
+++ b/maps/tradeship/tradeship-3.dmm
@@ -1181,6 +1181,10 @@
/obj/machinery/commsrelay,
/turf/floor/bluegrid,
/area/ship/trade/comms)
+"UX" = (
+/obj/effect/shuttle_landmark/automatic,
+/turf/space,
+/area/space)
"UY" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
@@ -2382,7 +2386,7 @@ aa
aa
aa
aa
-aa
+UX
aa
aa
aa
@@ -6665,7 +6669,7 @@ aa
aa
aa
aa
-aa
+UX
aa
aa
aa
diff --git a/maps/tradeship/tradeship.dm b/maps/tradeship/tradeship.dm
index 3815dcc7845..d747204cc30 100644
--- a/maps/tradeship/tradeship.dm
+++ b/maps/tradeship/tradeship.dm
@@ -4,43 +4,43 @@
#include "../../code/unit_tests/offset_tests.dm"
#endif
- #include "../../mods/gamemodes/cult/_cult.dme"
- #include "../../mods/gamemodes/heist/_heist.dme"
- #include "../../mods/gamemodes/ninja/_ninja.dme"
- #include "../../mods/gamemodes/revolution/_revolution.dme"
- #include "../../mods/gamemodes/traitor/_traitor.dme"
- #include "../../mods/gamemodes/spyvspy/_spyvspy.dme"
- #include "../../mods/gamemodes/mixed/_mixed.dme"
+ #include "../../mods/content/tabloids/_tabloids.dme"
#include "../random_ruins/exoplanet_ruins/playablecolony/playablecolony.dm"
#include "../../mods/content/government/away_sites/icarus/icarus.dm"
#include "../../mods/content/corporate/away_sites/lar_maria/lar_maria.dm"
- #include "../../mods/content/standard_jobs/_standard_jobs.dme"
- #include "../../mods/content/dungeon_loot/_dungeon_loot.dme"
#include "../../mods/content/mundane.dm"
#include "../../mods/content/baychems/_baychems.dme"
+
#include "../../mods/content/bigpharma/_bigpharma.dme"
#include "../../mods/content/corporate/_corporate.dme"
+ #include "../../mods/content/dungeon_loot/_dungeon_loot.dme"
#include "../../mods/content/government/_government.dme"
+ #include "../../mods/content/matchmaking/_matchmaking.dme"
#include "../../mods/content/modern_earth/_modern_earth.dme"
#include "../../mods/content/mouse_highlights/_mouse_highlight.dme"
- #include "../../mods/content/scaling_descriptors.dm"
- #include "../../mods/content/xenobiology/_xenobiology.dme"
- #include "../../mods/content/matchmaking/_matchmaking.dme"
#include "../../mods/content/pheromones/_pheromones.dme"
+ #include "../../mods/content/psionics/_psionics.dme"
+ #include "../../mods/content/standard_jobs/_standard_jobs.dme"
+ #include "../../mods/content/supermatter/_supermatter.dme"
+ #include "../../mods/content/xenobiology/_xenobiology.dme"
- #include "../../mods/mobs/dionaea/_dionaea.dme"
- #include "../../mods/mobs/borers/_borers.dme"
+ #include "../../mods/gamemodes/cult/_cult.dme"
+ #include "../../mods/gamemodes/heist/_heist.dme"
+ #include "../../mods/gamemodes/ninja/_ninja.dme"
+ #include "../../mods/gamemodes/revolution/_revolution.dme"
+ #include "../../mods/gamemodes/spyvspy/_spyvspy.dme"
+ #include "../../mods/gamemodes/traitor/_traitor.dme"
+ #include "../../mods/gamemodes/mixed.dm"
- // Must come after borers for compatibility.
- #include "../../mods/content/psionics/_psionics.dme"
+ #include "../../mods/mobs/borers/_borers.dme"
+ #include "../../mods/mobs/dionaea/_dionaea.dme"
+ #include "../../mods/species/bayliens/_bayliens.dme"
#include "../../mods/species/drakes/_drakes.dme"
// #include "../../mods/species/utility_frames/_utility_frames.dme"
- #include "../../mods/species/neoavians/_neoavians.dme"
- #include "../../mods/species/bayliens/_bayliens.dme"
#include "../../mods/species/vox/_vox.dme"
#include "../../mods/content/polaris/_polaris.dme"
diff --git a/maps/tradeship/tradeship_jobs.dm b/maps/tradeship/tradeship_jobs.dm
index 61b526624e0..71ba7143cc3 100644
--- a/maps/tradeship/tradeship_jobs.dm
+++ b/maps/tradeship/tradeship_jobs.dm
@@ -1,19 +1,18 @@
/datum/map/tradeship
- default_job_type = /datum/job/assistant/tradeship
+ default_job_type = /datum/job/standard/assistant/tradeship
default_department_type = /decl/department/civilian
default_law_type = /datum/ai_laws/corporate
- id_hud_icons = 'maps/tradeship/hud.dmi'
allowed_jobs = list(
- /datum/job/assistant/tradeship,
- /datum/job/captain/tradeship,
+ /datum/job/standard/assistant/tradeship,
+ /datum/job/standard/captain/tradeship,
/datum/job/tradeship_first_mate,
- /datum/job/cmo/tradeship,
- /datum/job/doctor/tradeship,
- /datum/job/chief_engineer/tradeship,
- /datum/job/engineer/tradeship,
- /datum/job/rd/tradeship,
- /datum/job/scientist/tradeship,
- /datum/job/robot
+ /datum/job/standard/cmo/tradeship,
+ /datum/job/standard/doctor/tradeship,
+ /datum/job/standard/chief_engineer/tradeship,
+ /datum/job/standard/engineer/tradeship,
+ /datum/job/standard/rd/tradeship,
+ /datum/job/standard/scientist/tradeship,
+ /datum/job/standard/robot
)
/obj/machinery/suit_cycler/tradeship
diff --git a/maps/tradeship/tradeship_spawnpoints.dm b/maps/tradeship/tradeship_spawnpoints.dm
index c4be5d21c35..36e4d8acdb7 100644
--- a/maps/tradeship/tradeship_spawnpoints.dm
+++ b/maps/tradeship/tradeship_spawnpoints.dm
@@ -9,7 +9,7 @@
/decl/spawnpoint/cryo
name = "Port Cryogenic Storage"
spawn_announcement = "has completed revival in the port cryogenics bay"
- disallow_job = list(/datum/job/robot)
+ disallow_job = list(/datum/job/standard/robot)
/decl/spawnpoint/cryo/two
name = "Starboard Cryogenic Storage"
@@ -22,7 +22,7 @@
/decl/spawnpoint/cryo/captain
name = "Captain Compartment"
spawn_announcement = "has completed revival in the captain compartment"
- restrict_job = list(/datum/job/captain/tradeship)
+ restrict_job = list(/datum/job/standard/captain/tradeship)
uid = "spawn_cryo_captain"
/obj/abstract/landmark/latejoin/cryo_captain
diff --git a/maps/~mapsystem/maps.dm b/maps/~mapsystem/maps.dm
index 46850d244ed..ee1696d6e61 100644
--- a/maps/~mapsystem/maps.dm
+++ b/maps/~mapsystem/maps.dm
@@ -1,21 +1,30 @@
-var/global/datum/map/using_map = new USING_MAP_DATUM
-var/global/list/all_maps = list()
+var/global/datum/map/using_map = new USING_MAP_DATUM
+var/global/list/all_maps = list()
+var/global/list/votable_maps = list()
var/global/const/MAP_HAS_BRANCH = 1 //Branch system for occupations, togglable
-var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable
+var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable
/proc/initialise_map_list()
- for(var/type in subtypesof(/datum/map))
- var/datum/map/M
- if(type == global.using_map.type)
- M = global.using_map
- M.setup_map()
- else
- M = new type
- if(!M.path)
- log_error("Map '[M]' ([type]) does not have a defined path, not adding to map list!")
+ for(var/map_type in subtypesof(/datum/map))
+
+ var/datum/map/map_instance = map_type
+ if(TYPE_IS_ABSTRACT(map_instance))
+ continue
+
+ if(map_type == global.using_map.type)
+ map_instance = global.using_map
+ map_instance.setup_map()
+ else if(map_instance::path)
+ map_instance = new map_instance
else
- global.all_maps[M.path] = M
+ log_error("Map '[map_type]' does not have a defined path, not adding to map list!")
+ continue
+
+ global.all_maps[map_instance.path] = map_instance
+ if(map_instance.votable)
+ global.votable_maps[map_instance.path] = map_instance
+
return 1
/datum/map
@@ -104,7 +113,9 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable
var/default_law_type = /datum/ai_laws/asimov // The default lawset use by synth units, if not overriden by their laws var.
var/security_state = /decl/security_state/default // The default security state system to use.
- var/id_hud_icons = 'icons/mob/hud.dmi' // Used by the ID HUD (primarily sechud) overlay.
+ var/hud_icons = 'icons/screen/hud.dmi' // Used by the ID HUD (primarily sechud) overlay.
+ var/implant_hud_icons = 'icons/screen/hud_implants.dmi'
+ var/med_hud_icons = 'icons/screen/hud_med.dmi'
var/num_exoplanets = 0
var/force_exoplanet_type // Used to override exoplanet weighting and always pick the same exoplanet.
@@ -127,6 +138,9 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable
var/default_species = SPECIES_HUMAN
+ // Can this map be voted for by players?
+ var/votable = TRUE
+
var/list/available_background_info = list(
/decl/background_category/homeworld = list(/decl/background_detail/location/other),
/decl/background_category/faction = list(/decl/background_detail/faction/other),
@@ -188,6 +202,12 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable
)
+ var/default_ui_style
+
+/datum/map/New()
+ ..()
+ default_ui_style ||= DEFAULT_UI_STYLE
+
/datum/map/proc/get_background_categories()
if(!background_categories_generated)
if(isnull(_background_categories))
@@ -262,10 +282,9 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable
if(!allowed_jobs)
allowed_jobs = list()
- for(var/jtype in subtypesof(/datum/job))
- var/datum/job/job = jtype
- if(initial(job.available_by_default))
- allowed_jobs += jtype
+ for(var/datum/job/job as anything in subtypesof(/datum/job))
+ if(!TYPE_IS_ABSTRACT(job) && job::available_by_default)
+ allowed_jobs += job
if(ispath(default_job_type, /datum/job))
var/datum/job/J = default_job_type
@@ -534,5 +553,24 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable
/datum/map/proc/finalize_map_generation()
return
+/datum/map/proc/validate()
+ . = TRUE
+ if(!length(SSmapping.player_levels))
+ log_error("[name] has no player levels!")
+ . = FALSE
+ if(!length(SSmapping.station_levels))
+ log_error("[name] has no station levels!")
+ . = FALSE
+ // TODO: add an admin level loaded from template for maps like tradeship (generic admin level modpack?)
+ /*
+ if(!length(SSmapping.admin_levels))
+ log_error("[name] has no admin levels!")
+ . = FALSE
+ */
+ if(!length(SSmapping.contact_levels))
+ log_error("[name] has no contact levels!")
+ . = FALSE
+
/datum/map/proc/get_available_submap_archetypes()
return decls_repository.get_decls_of_subtype_unassociated(/decl/submap_archetype)
+
diff --git a/mods/_modpack.dm b/mods/_modpack.dm
index 81c16e69f7a..0fb1d5d7908 100644
--- a/mods/_modpack.dm
+++ b/mods/_modpack.dm
@@ -8,7 +8,11 @@
var/secrets_directory
/// The folder to load additional NanoUI templates from. Must be relative to the DME's location (root game folder).
var/nanoui_directory
- var/list/dreams //! A list of strings to be added to the random dream proc.
+
+ var/list/dreams //! A list of strings to be added to the random dream proc.
+
+ var/list/tabloid_headlines //! A list of headline and article data used by the tabloids modpack.
+ var/list/tabloid_publishers //! A list of name strings used by the tabloids modpack.
var/list/credits_other //! A list of strings that are used by the end of round credits roll.
var/list/credits_adventure_names //! A list of strings that are used by the end of round credits roll.
diff --git a/mods/content/fantasy/_fantasy.dme b/mods/content/fantasy/_fantasy.dme
index 2dcfaa8cde5..87b99cb04e9 100644
--- a/mods/content/fantasy/_fantasy.dme
+++ b/mods/content/fantasy/_fantasy.dme
@@ -37,5 +37,16 @@
#include "items\clothing\loincloth.dm"
#include "items\clothing\trousers.dm"
#include "props\signpost.dm"
+#include "submaps\_submaps.dm"
+#include "submaps\downlands\_downlands.dm"
+#include "submaps\grassland\_grassland.dm"
+#include "submaps\swamp\_swamp.dm"
+#include "submaps\woods\_woods.dm"
+#include "submaps\woods\bear_den\bear_den.dm"
+#include "submaps\woods\chemistry_shack\chemistry_shack.dm"
+#include "submaps\woods\fairy_rings\fairy_rings.dm"
+#include "submaps\woods\fox_den\fox_den.dm"
+#include "submaps\woods\hunter_camp\hunter_camp.dm"
+#include "submaps\woods\old_cabin\old_cabin.dm"
// END_INCLUDE
#endif
diff --git a/mods/content/fantasy/datum/hnoll/bodytypes.dm b/mods/content/fantasy/datum/hnoll/bodytypes.dm
index 218068362ce..1edda9e8e99 100644
--- a/mods/content/fantasy/datum/hnoll/bodytypes.dm
+++ b/mods/content/fantasy/datum/hnoll/bodytypes.dm
@@ -16,6 +16,7 @@
base_color = "#ae7d32"
base_eye_color = "#00aa00"
uid = "bodytype_hnoll"
+ footprints_icon = 'icons/mob/footprints/footprints_paw.dmi'
default_sprite_accessories = list(
SAC_HAIR = list(
diff --git a/mods/content/fantasy/datum/hnoll/species.dm b/mods/content/fantasy/datum/hnoll/species.dm
index 31ebc61a61e..8bb1cd7496e 100644
--- a/mods/content/fantasy/datum/hnoll/species.dm
+++ b/mods/content/fantasy/datum/hnoll/species.dm
@@ -30,13 +30,6 @@
move_trail = /obj/effect/decal/cleanable/blood/tracks/paw
base_external_prosthetics_model = null
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite/sharp
- )
-
available_background_info = list(
/decl/background_category/homeworld = list(
/decl/background_detail/location/fantasy,
diff --git a/mods/content/fantasy/datum/overrides.dm b/mods/content/fantasy/datum/overrides.dm
index 0726866427d..08b4b54f4de 100644
--- a/mods/content/fantasy/datum/overrides.dm
+++ b/mods/content/fantasy/datum/overrides.dm
@@ -31,28 +31,33 @@
/decl/background_category/religion = /decl/background_detail/religion/other
)
-// Rename grafadreka
-/decl/species/grafadreka
- name = "Meredrake"
- name_plural = "Meredrakes"
- description = "Meredrakes, sometimes called mire-drakes, are large reptillian pack predators, widely assumed to be cousins to true dragons. \
- They are commonly found living in caves or burrows bordering grassland or forest, and while they prefer to hunt deer or rabbits, they will sometimes attack travellers if pickings are slim enough. \
- While they are not domesticated, they can be habituated and trained as working animals if captured young enough."
-
-/decl/sprite_accessory/marking/grafadreka
- species_allowed = list("Meredrake")
-
-/decl/language/grafadreka
- desc = "Hiss hiss, feed me rabbits."
-
-/decl/material/liquid/sifsap
- name = "drake spittle"
- lore_text = "A complex chemical slurry brewed up in the gullet of meredrakes."
-
-/obj/aura/sifsap_salve
- name = "Drakespittle Salve"
- descriptor = "glowing spittle"
-
// Rename wooden prostheses
/decl/bodytype/prosthetic/wooden
name = "carved wooden" // weird to call it 'crude' when it's cutting-edge for the setting
+
+// Just some fun overrides for when robot debris shows up in maint.
+/obj/effect/decal/cleanable/blood/gibs/robot
+ name = "mysterious debris"
+ desc = "Some kind of complex, oily detritus. What could it be?"
+
+/obj/item/remains/robot
+ name = "mysterious remains"
+ desc = "The oily remains of some complex, metallic object. What could they be from?"
+
+// Override to remove non-fantasy stuff.
+/obj/random/trash/spawn_choices()
+ var/static/list/spawnable_choices = list(
+ /obj/item/remains/lizard,
+ /obj/effect/decal/cleanable/blood/gibs/robot,
+ /obj/effect/decal/cleanable/spiderling_remains,
+ /obj/item/remains/mouse,
+ /obj/effect/decal/cleanable/vomit,
+ /obj/effect/decal/cleanable/blood/splatter,
+ /obj/effect/decal/cleanable/ash,
+ /obj/effect/decal/cleanable/generic,
+ /obj/effect/decal/cleanable/flour,
+ /obj/effect/decal/cleanable/filth,
+ /obj/effect/decal/cleanable/dirt/visible,
+ /obj/item/remains/robot
+ )
+ return spawnable_choices
diff --git a/mods/content/fantasy/icons/areas.dmi b/mods/content/fantasy/icons/areas.dmi
new file mode 100644
index 00000000000..9849d6f87d8
Binary files /dev/null and b/mods/content/fantasy/icons/areas.dmi differ
diff --git a/mods/content/fantasy/submaps/_submaps.dm b/mods/content/fantasy/submaps/_submaps.dm
new file mode 100644
index 00000000000..64c03240f4b
--- /dev/null
+++ b/mods/content/fantasy/submaps/_submaps.dm
@@ -0,0 +1,52 @@
+#define MAP_TEMPLATE_CATEGORY_FANTASY_GRASSLAND "template_fantasy_grassland"
+#define MAP_TEMPLATE_CATEGORY_FANTASY_SWAMP "template_fantasy_swamp"
+#define MAP_TEMPLATE_CATEGORY_FANTASY_WOODS "template_fantasy_woods"
+#define MAP_TEMPLATE_CATEGORY_FANTASY_DOWNLANDS "template_fantasy_downlands"
+#define MAP_TEMPLATE_CATEGORY_FANTASY_DUNGEON "template_fantasy_dungeon"
+#define MAP_TEMPLATE_CATEGORY_FANTASY_CAVERNS "template_fantasy_caverns"
+
+/datum/map_template/fantasy
+ abstract_type = /datum/map_template/fantasy
+ template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS
+ area_usage_test_exempted_root_areas = list(
+ /area/fantasy/outside/point_of_interest
+ )
+ var/cost = 1
+
+/datum/map_template/fantasy/get_template_cost()
+ return cost
+
+/datum/map/New()
+ LAZYSET(apc_test_exempt_areas, /area/fantasy, NO_SCRUBBER|NO_VENT|NO_APC)
+ ..()
+
+/area/fantasy
+ abstract_type = /area/fantasy
+ allow_xenoarchaeology_finds = FALSE
+ icon = 'mods/content/fantasy/icons/areas.dmi'
+ icon_state = "area"
+ base_turf = /turf/floor/rock/basalt
+ sound_env = GENERIC
+ ambience = list()
+
+/area/fantasy/outside
+ name = "\improper Wilderness"
+ abstract_type = /area/fantasy/outside
+ color = COLOR_GREEN
+ is_outside = OUTSIDE_YES
+ sound_env = PLAIN
+ ambience = list(
+ 'sound/effects/wind/wind_2_1.ogg',
+ 'sound/effects/wind/wind_2_2.ogg',
+ 'sound/effects/wind/wind_3_1.ogg',
+ 'sound/effects/wind/wind_4_1.ogg',
+ 'sound/effects/wind/wind_4_2.ogg',
+ 'sound/effects/wind/wind_5_1.ogg'
+ )
+ interior_ambient_light_modifier = -0.3
+ area_flags = AREA_FLAG_EXTERNAL | AREA_FLAG_IS_BACKGROUND
+
+/area/fantasy/outside/point_of_interest
+ name = "Point Of Interest"
+ description = null
+ area_blurb_category = /area/fantasy/outside/point_of_interest
diff --git a/mods/content/fantasy/submaps/downlands/_downlands.dm b/mods/content/fantasy/submaps/downlands/_downlands.dm
new file mode 100644
index 00000000000..5086d54dc54
--- /dev/null
+++ b/mods/content/fantasy/submaps/downlands/_downlands.dm
@@ -0,0 +1,7 @@
+/datum/map_template/fantasy/downlands
+ abstract_type = /datum/map_template/fantasy/downlands
+ template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_DOWNLANDS)
+
+/datum/map_template/fantasy/dungeon
+ abstract_type = /datum/map_template/fantasy/dungeon
+ template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_DUNGEON)
diff --git a/mods/content/fantasy/submaps/grassland/_grassland.dm b/mods/content/fantasy/submaps/grassland/_grassland.dm
new file mode 100644
index 00000000000..19b70b9367f
--- /dev/null
+++ b/mods/content/fantasy/submaps/grassland/_grassland.dm
@@ -0,0 +1,7 @@
+/datum/map_template/fantasy/grassland
+ abstract_type = /datum/map_template/fantasy/grassland
+ template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_GRASSLAND)
+
+/datum/map_template/fantasy/cavern
+ abstract_type = /datum/map_template/fantasy/cavern
+ template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_CAVERNS)
\ No newline at end of file
diff --git a/mods/content/fantasy/submaps/swamp/_swamp.dm b/mods/content/fantasy/submaps/swamp/_swamp.dm
new file mode 100644
index 00000000000..6a3c2054ea9
--- /dev/null
+++ b/mods/content/fantasy/submaps/swamp/_swamp.dm
@@ -0,0 +1,3 @@
+/datum/map_template/fantasy/swamp
+ abstract_type = /datum/map_template/fantasy/swamp
+ template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_SWAMP)
\ No newline at end of file
diff --git a/mods/content/fantasy/submaps/woods/_woods.dm b/mods/content/fantasy/submaps/woods/_woods.dm
new file mode 100644
index 00000000000..dc1429ef559
--- /dev/null
+++ b/mods/content/fantasy/submaps/woods/_woods.dm
@@ -0,0 +1,3 @@
+/datum/map_template/fantasy/woods
+ abstract_type = /datum/map_template/fantasy/woods
+ template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_WOODS)
diff --git a/mods/content/fantasy/submaps/woods/bear_den/bear_den.dm b/mods/content/fantasy/submaps/woods/bear_den/bear_den.dm
new file mode 100644
index 00000000000..cb4da036c7c
--- /dev/null
+++ b/mods/content/fantasy/submaps/woods/bear_den/bear_den.dm
@@ -0,0 +1,6 @@
+/datum/map_template/fantasy/woods/bear_den
+ name = "bear den"
+ mappaths = list("mods/content/fantasy/submaps/woods/bear_den/bear_den.dmm")
+
+/area/fantasy/outside/point_of_interest/bear_den
+ name = "Point of Interest - Bear Den"
diff --git a/maps/shaded_hills/submaps/woods/bear_den/bear_den.dmm b/mods/content/fantasy/submaps/woods/bear_den/bear_den.dmm
similarity index 76%
rename from maps/shaded_hills/submaps/woods/bear_den/bear_den.dmm
rename to mods/content/fantasy/submaps/woods/bear_den/bear_den.dmm
index 01ac1b5988a..021df578e9b 100644
--- a/maps/shaded_hills/submaps/woods/bear_den/bear_den.dmm
+++ b/mods/content/fantasy/submaps/woods/bear_den/bear_den.dmm
@@ -8,19 +8,19 @@
"k" = (
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"n" = (
/turf/floor/rock/basalt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"o" = (
/turf/floor/grass,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"p" = (
/turf/floor/grass,
/area/template_noop)
"r" = (
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"w" = (
/obj/item/bladed/knife,
/obj/item/cash/imperial/crown,
@@ -29,20 +29,20 @@
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/floor/rock/basalt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"y" = (
/obj/abstract/exterior_marker/inside,
/turf/floor/rock/basalt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"z" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/natural/dirt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"C" = (
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/floor/rock/basalt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"G" = (
/obj/item/bone/skull/deer,
/obj/item/food/butchery/stomach,
@@ -50,7 +50,7 @@
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"J" = (
/turf/floor/grass/wild,
/area/template_noop)
@@ -61,16 +61,16 @@
/mob/living/simple_animal/hostile/bear,
/obj/abstract/exterior_marker/inside,
/turf/floor/rock/basalt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"O" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/natural/basalt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"U" = (
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/wall/natural/basalt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"V" = (
/obj/item/cash/imperial/quin,
/obj/item/cash/imperial/quin,
@@ -79,12 +79,12 @@
/obj/item/cash/imperial/crown,
/obj/abstract/exterior_marker/inside,
/turf/floor/rock/basalt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
"W" = (
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/wall/natural/dirt,
-/area/shaded_hills/outside/point_of_interest/bear_den)
+/area/fantasy/outside/point_of_interest/bear_den)
(1,1,1) = {"
K
diff --git a/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dm b/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dm
new file mode 100644
index 00000000000..158824c417b
--- /dev/null
+++ b/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dm
@@ -0,0 +1,6 @@
+/datum/map_template/fantasy/woods/chemistry_shack
+ name = "chemistry shack"
+ mappaths = list("mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dmm")
+
+/area/fantasy/outside/point_of_interest/chemistry_shack
+ name = "Point of Interest - Chemistry Shack"
diff --git a/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dmm b/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dmm
similarity index 75%
rename from maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dmm
rename to mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dmm
index fa4f65d3fd7..6ed42c83589 100644
--- a/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dmm
+++ b/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dmm
@@ -5,7 +5,7 @@
dir = 4
},
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"h" = (
/obj/abstract/exterior_marker/inside,
/obj/item/rock/hematite{
@@ -33,7 +33,7 @@
},
/obj/structure/table/desk/ebony,
/turf/floor/path/herringbone/basalt,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"k" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/table/wood/ebony,
@@ -41,12 +41,12 @@
/obj/item/chems/glass/handmade/teapot,
/obj/abstract/landmark/organize/vertical,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"m" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/reagent_dispensers/barrel/ebony/oil,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"n" = (
/obj/structure/wall_sconce/lantern{
dir = 1;
@@ -60,7 +60,7 @@
/obj/item/chems/glass/mortar,
/obj/item/rock/basalt,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"q" = (
/obj/structure/drying_rack/ebony,
/turf/floor/dirt,
@@ -69,11 +69,11 @@
/obj/abstract/exterior_marker/inside,
/obj/structure/filter_stand/mapped,
/turf/floor/path/herringbone/basalt,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"s" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/log/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"z" = (
/turf/template_noop,
/area/template_noop)
@@ -81,30 +81,30 @@
/obj/abstract/exterior_marker/inside,
/obj/structure/door/walnut,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"F" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/brick/basalt,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"H" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/brick/basalt/shutter,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"I" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/reagent_dispensers/barrel/ebony/water,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"J" = (
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"K" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/bed/simple/ebony/cloth,
/obj/item/bedsheet/furs,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"L" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/table/wood/ebony,
@@ -115,22 +115,22 @@
/obj/item/food/grown/carrot,
/obj/item/kitchen/rollingpin,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"M" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/reagent_dispensers/barrel/ebony/wine,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"N" = (
/obj/abstract/exterior_marker/inside,
/turf/floor/path/herringbone/basalt,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"R" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/closet/crate/chest/ebony,
/obj/random/jewelry,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"U" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/wall_sconce/lantern{
@@ -149,19 +149,19 @@
pixel_y = 9
},
/turf/floor/path/herringbone/basalt,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"W" = (
/turf/floor/dirt,
/area/template_noop)
"X" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/log/walnut/shutter,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
"Y" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/fire_source/stove,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/chemistry_shack)
+/area/fantasy/outside/point_of_interest/chemistry_shack)
(1,1,1) = {"
W
diff --git a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring.dmm b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring.dmm
similarity index 75%
rename from maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring.dmm
rename to mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring.dmm
index b3c1314f552..2611fe47b34 100644
--- a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring.dmm
+++ b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring.dmm
@@ -1,14 +1,14 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
/turf/floor/fake_grass,
-/area/shaded_hills/outside/point_of_interest/fairy_ring)
+/area/fantasy/outside/point_of_interest/fairy_ring)
"w" = (
/obj/structure/flora/plant/random_mushroom,
/turf/floor/fake_grass,
-/area/shaded_hills/outside/point_of_interest/fairy_ring)
+/area/fantasy/outside/point_of_interest/fairy_ring)
"D" = (
/turf/floor/grass/wild,
-/area/shaded_hills/outside/point_of_interest/fairy_ring)
+/area/fantasy/outside/point_of_interest/fairy_ring)
"N" = (
/turf/template_noop,
/area/template_noop)
diff --git a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring_glowing.dmm b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring_glowing.dmm
similarity index 75%
rename from maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring_glowing.dmm
rename to mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring_glowing.dmm
index bbd7d2ae036..b86a4adcb0f 100644
--- a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring_glowing.dmm
+++ b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring_glowing.dmm
@@ -4,14 +4,14 @@
/area/template_noop)
"h" = (
/turf/floor/grass,
-/area/shaded_hills/outside/point_of_interest/fairy_ring)
+/area/fantasy/outside/point_of_interest/fairy_ring)
"j" = (
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/fairy_ring)
+/area/fantasy/outside/point_of_interest/fairy_ring)
"A" = (
/obj/structure/flora/plant/random_mushroom/glowing,
/turf/floor/grass,
-/area/shaded_hills/outside/point_of_interest/fairy_ring)
+/area/fantasy/outside/point_of_interest/fairy_ring)
(1,1,1) = {"
a
diff --git a/mods/content/fantasy/submaps/woods/fairy_rings/fairy_rings.dm b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_rings.dm
new file mode 100644
index 00000000000..76140bdb759
--- /dev/null
+++ b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_rings.dm
@@ -0,0 +1,15 @@
+/datum/map_template/fantasy/woods/fairy_ring
+ name = "fairy ring"
+ mappaths = list("mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring.dmm")
+ template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS | TEMPLATE_FLAG_ALLOW_DUPLICATES | TEMPLATE_FLAG_GENERIC_REPEATABLE
+ template_categories = list(
+ MAP_TEMPLATE_CATEGORY_FANTASY_WOODS
+ )
+ area_coherency_test_exempt_areas = list(/area/fantasy/outside/point_of_interest/fairy_ring)
+
+/datum/map_template/fantasy/woods/fairy_ring/glowing
+ name = "glowing fairy ring"
+ mappaths = list("mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring_glowing.dmm")
+
+/area/fantasy/outside/point_of_interest/fairy_ring
+ name = "Point of Interest - Fairy Ring"
diff --git a/mods/content/fantasy/submaps/woods/fox_den/fox_den.dm b/mods/content/fantasy/submaps/woods/fox_den/fox_den.dm
new file mode 100644
index 00000000000..894f6f7fb50
--- /dev/null
+++ b/mods/content/fantasy/submaps/woods/fox_den/fox_den.dm
@@ -0,0 +1,6 @@
+/datum/map_template/fantasy/woods/fox_den
+ name = "fox den"
+ mappaths = list("mods/content/fantasy/submaps/woods/fox_den/fox_den.dmm")
+
+/area/fantasy/outside/point_of_interest/fox_den
+ name = "Point of Interest - Fox Den"
diff --git a/maps/shaded_hills/submaps/woods/fox_den/fox_den.dmm b/mods/content/fantasy/submaps/woods/fox_den/fox_den.dmm
similarity index 82%
rename from maps/shaded_hills/submaps/woods/fox_den/fox_den.dmm
rename to mods/content/fantasy/submaps/woods/fox_den/fox_den.dmm
index 6e1c6e5ce94..8053ead1e47 100644
--- a/maps/shaded_hills/submaps/woods/fox_den/fox_den.dmm
+++ b/mods/content/fantasy/submaps/woods/fox_den/fox_den.dmm
@@ -9,7 +9,7 @@
/mob/living/simple_animal/passive/fox,
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/fox_den)
+/area/fantasy/outside/point_of_interest/fox_den)
"x" = (
/turf/floor/grass/wild,
/area/template_noop)
@@ -23,7 +23,7 @@
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/fox_den)
+/area/fantasy/outside/point_of_interest/fox_den)
"B" = (
/turf/floor/grass,
/area/template_noop)
@@ -31,32 +31,32 @@
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/wall/natural/dirt,
-/area/shaded_hills/outside/point_of_interest/fox_den)
+/area/fantasy/outside/point_of_interest/fox_den)
"O" = (
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/fox_den)
+/area/fantasy/outside/point_of_interest/fox_den)
"P" = (
/obj/item/food/butchery/offal/small,
/obj/item/stack/material/bone/mapped/bone,
/obj/abstract/exterior_marker/inside,
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/fox_den)
+/area/fantasy/outside/point_of_interest/fox_den)
"S" = (
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/fox_den)
+/area/fantasy/outside/point_of_interest/fox_den)
"W" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/natural/dirt,
-/area/shaded_hills/outside/point_of_interest/fox_den)
+/area/fantasy/outside/point_of_interest/fox_den)
"Y" = (
/obj/item/seeds/extracted/foxglove,
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/fox_den)
+/area/fantasy/outside/point_of_interest/fox_den)
(1,1,1) = {"
n
diff --git a/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dm b/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dm
new file mode 100644
index 00000000000..262e1b71d55
--- /dev/null
+++ b/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dm
@@ -0,0 +1,6 @@
+/datum/map_template/fantasy/woods/hunter_camp
+ name = "hunter camp"
+ mappaths = list("mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dmm")
+
+/area/fantasy/outside/point_of_interest/hunter_camp
+ name = "Point of Interest - Hunter Camp"
diff --git a/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dmm b/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dmm
similarity index 69%
rename from maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dmm
rename to mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dmm
index 0d8357987fe..b269d8d4cdd 100644
--- a/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dmm
+++ b/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dmm
@@ -1,93 +1,93 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
/turf/floor/grass/wild,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"b" = (
/obj/structure/drying_rack,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"e" = (
/turf/floor/grass,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"h" = (
/obj/structure/flora/tree/hardwood/ebony,
/turf/floor/grass,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"j" = (
/obj/item/stack/material/skin/mapped/leather/twenty,
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"k" = (
/obj/item/food/butchery/offal/beef,
/obj/item/food/butchery/offal/small/beef,
/obj/structure/pit,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"n" = (
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"q" = (
/obj/structure/closet/crate/chest/ebony,
/obj/item/food/butchery/haunch/shoulder/beef,
/obj/item/food/butchery/haunch/side/beef,
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"A" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/log/walnut,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"B" = (
/obj/structure/flora/stump/tree/ebony,
/turf/floor/grass/wild,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"C" = (
/obj/structure/flora/stump/tree/ebony,
/turf/floor/grass,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"D" = (
/obj/abstract/exterior_marker/inside,
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"E" = (
/obj/structure/reagent_dispensers/barrel/ebony/water,
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"F" = (
/obj/structure/drying_rack,
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"I" = (
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"J" = (
/obj/structure/flora/tree/hardwood/ebony,
/turf/floor/grass/wild,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"K" = (
/turf/template_noop,
/area/template_noop)
"P" = (
/obj/structure/flora/tree/hardwood/mahogany,
/turf/floor/grass/wild,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"Q" = (
/obj/structure/bed/bedroll/fur,
/obj/abstract/exterior_marker/inside,
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"S" = (
/obj/structure/fire_source/firepit/basalt,
/obj/item/stack/material/log/mapped/walnut/fifteen,
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"U" = (
/obj/abstract/exterior_marker/inside,
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
"Z" = (
/obj/item/bladed/knife,
/turf/floor/barren,
-/area/shaded_hills/outside/point_of_interest/hunter_camp)
+/area/fantasy/outside/point_of_interest/hunter_camp)
(1,1,1) = {"
K
diff --git a/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dm b/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dm
new file mode 100644
index 00000000000..4a2130efce2
--- /dev/null
+++ b/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dm
@@ -0,0 +1,6 @@
+/datum/map_template/fantasy/woods/old_cabin
+ name = "old cabin"
+ mappaths = list("mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dmm")
+
+/area/fantasy/outside/point_of_interest/old_cabin
+ name = "Point of Interest - Old Cabin"
diff --git a/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dmm b/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dmm
similarity index 73%
rename from maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dmm
rename to mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dmm
index 84ac9a1af5e..18e12175274 100644
--- a/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dmm
+++ b/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dmm
@@ -3,33 +3,33 @@
/obj/structure/door/walnut,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"g" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/table/end,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"h" = (
/turf/template_noop,
/area/template_noop)
"i" = (
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"k" = (
/obj/structure/closet/crate/chest/ebony,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"o" = (
/obj/structure/drying_rack/ebony,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"u" = (
/obj/structure/reagent_dispensers/barrel/ebony/beer,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"x" = (
/obj/structure/table/wood/ebony,
/obj/item/flame/torch,
@@ -38,7 +38,7 @@
/obj/item/rock/hematite,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"z" = (
/obj/effect/spider/spiderling/mundane,
/obj/structure/table/wood/ebony,
@@ -48,23 +48,23 @@
},
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"B" = (
/obj/effect/decal/cleanable/blood,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"D" = (
/obj/effect/spider/spiderling/mundane,
/obj/structure/table/wood/ebony,
/obj/item/food/grown/carrot,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"G" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/log/walnut/shutter,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"H" = (
/obj/structure/table/wood/ebony,
/obj/item/bladed/knife,
@@ -73,37 +73,37 @@
/obj/item/food/grown/carrot,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"I" = (
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"L" = (
/obj/effect/spider/spiderling/mundane,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"M" = (
/obj/abstract/exterior_marker/inside,
/turf/wall/log/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"N" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/coatrack/ebony,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"T" = (
/obj/abstract/exterior_marker/inside,
/obj/structure/table/desk/dresser,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"W" = (
/obj/structure/wall_sconce/torch{
dir = 1;
pixel_y = 24
},
/turf/floor/dirt,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
"Z" = (
/obj/item/remains/human,
/obj/structure/bed/simple/ebony/cloth,
@@ -112,7 +112,7 @@
/obj/random/jewelry,
/obj/abstract/exterior_marker/inside,
/turf/floor/wood/rough/walnut,
-/area/shaded_hills/outside/point_of_interest/old_cabin)
+/area/fantasy/outside/point_of_interest/old_cabin)
(1,1,1) = {"
i
diff --git a/maps/shaded_hills/submaps/woods/suspicious_cabin/suspicious_cabin.dmm b/mods/content/fantasy/submaps/woods/suspicious_cabin/suspicious_cabin.dmm
similarity index 100%
rename from maps/shaded_hills/submaps/woods/suspicious_cabin/suspicious_cabin.dmm
rename to mods/content/fantasy/submaps/woods/suspicious_cabin/suspicious_cabin.dmm
diff --git a/mods/content/item_sharpening/_item_sharpening.dm b/mods/content/item_sharpening/_item_sharpening.dm
new file mode 100644
index 00000000000..3807839161b
--- /dev/null
+++ b/mods/content/item_sharpening/_item_sharpening.dm
@@ -0,0 +1,8 @@
+#define IE_PAR_SHARP_DAM_MULT "sharp_dam_mult"
+
+/decl/modpack/item_sharpening
+ name = "Item Sharpening"
+
+/obj/proc/get_sharpening_material()
+ RETURN_TYPE(/decl/material)
+ return get_material()
diff --git a/mods/content/item_sharpening/_item_sharpening.dme b/mods/content/item_sharpening/_item_sharpening.dme
new file mode 100644
index 00000000000..c9af243f5e9
--- /dev/null
+++ b/mods/content/item_sharpening/_item_sharpening.dme
@@ -0,0 +1,11 @@
+#ifndef MODPACK_ITEM_SHARPENING
+#define MODPACK_ITEM_SHARPENING
+// BEGIN_INCLUDE
+#include "_item_sharpening.dm"
+#include "blade_sharpen.dm"
+#include "effect_sharpen.dm"
+#include "grindstone.dm"
+#include "item_sharpen.dm"
+#include "whetstone.dm"
+//END_INCLUDE
+#endif
diff --git a/mods/content/item_sharpening/blade_sharpen.dm b/mods/content/item_sharpening/blade_sharpen.dm
new file mode 100644
index 00000000000..a46b8d69033
--- /dev/null
+++ b/mods/content/item_sharpening/blade_sharpen.dm
@@ -0,0 +1,24 @@
+/obj/item/bladed/proc/get_sharpened_effect_params()
+ return list(
+ (IE_CAT_DAMAGE) = list(
+ (IE_PAR_USES) = max(1, max(1, rand(round(10 * 0.3), round(20 * 0.6)))),
+ (IE_PAR_MAX_USES) = 30,
+ (IE_PAR_SHARP_DAM_MULT) = 0.25
+ ),
+ (IE_CAT_EXAMINE)
+ )
+
+/obj/item/bladed/Initialize(ml, material_key, _hilt_mat, _guard_mat, _pommel_mat)
+ var/list/sharpened_params = get_sharpened_effect_params()
+ if(length(sharpened_params))
+ add_item_effect(/decl/item_effect/sharpened, sharpened_params)
+ . = ..()
+ if(length(sharpened_params))
+ update_attack_force()
+ update_name()
+
+/obj/item/bladed/folding/try_sharpen_with(mob/user, obj/sharpening_with)
+ if(!open)
+ to_chat(user, SPAN_WARNING("You cannot sharpen \the [src] while it's closed!"))
+ return FALSE
+ return ..()
diff --git a/mods/content/item_sharpening/effect_sharpen.dm b/mods/content/item_sharpening/effect_sharpen.dm
new file mode 100644
index 00000000000..5847ac347b3
--- /dev/null
+++ b/mods/content/item_sharpening/effect_sharpen.dm
@@ -0,0 +1,21 @@
+/decl/item_effect/sharpened/modify_attack_damage(base_damage, obj/item/used_item, mob/user, list/parameters)
+ var/uses = LAZYACCESS(parameters, IE_PAR_USES)
+ if(uses <= 0)
+ return base_damage
+ . = (1 + ((uses / max(1, LAZYACCESS(parameters, IE_PAR_MAX_USES))) * LAZYACCESS(parameters, IE_PAR_SHARP_DAM_MULT)))
+
+/decl/item_effect/sharpened/expend_attack_use(obj/item/used_item, mob/user, list/parameters)
+ var/uses = LAZYACCESS(parameters, IE_PAR_USES)
+ uses = max(0, uses-1)
+ used_item.set_item_effect_parameter(src, IE_CAT_DAMAGE, IE_PAR_USES, uses)
+ if(uses == 0) // We've gone dull!
+ used_item.update_attack_force()
+ used_item.update_name()
+
+/decl/item_effect/sharpened/on_examined(obj/item/item, mob/user, distance, list/parameters)
+ if(distance <= 1)
+ var/uses = item.get_item_effect_parameter(src, IE_CAT_DAMAGE, IE_PAR_USES)
+ if(uses > 0)
+ to_chat(user, SPAN_NOTICE("\The [item] has been honed to a keen edge."))
+ else
+ to_chat(user, SPAN_NOTICE("\The [item] in need of sharpening."))
diff --git a/mods/content/item_sharpening/grindstone.dm b/mods/content/item_sharpening/grindstone.dm
new file mode 100644
index 00000000000..13d8f126052
--- /dev/null
+++ b/mods/content/item_sharpening/grindstone.dm
@@ -0,0 +1,46 @@
+// TODO: better sound effects for working.
+/obj/structure/working/grindstone
+ name = "grindstone"
+ desc = "A rotating section of coarse stone used to polish and sharpen metalwork like blades."
+ icon = 'mods/content/item_sharpening/icons/grindstone.dmi'
+ material_alteration = MAT_FLAG_ALTERATION_COLOR // Name and desc handled manually.
+ var/decl/material/stone_material = /decl/material/solid/quartz
+
+/obj/structure/working/grindstone/Initialize()
+ stone_material = GET_DECL(stone_material)
+ . = ..()
+ update_material_name()
+ update_material_desc()
+
+/obj/structure/working/grindstone/update_material_name(override_name)
+ . = ..()
+ if(stone_material)
+ SetName("[stone_material.adjective_name] [name]")
+
+/obj/structure/working/grindstone/update_material_desc(override_desc)
+ . = ..()
+ if(stone_material && istype(material))
+ desc = "[desc] This one is made from [stone_material.solid_name] with \a [material.adjective_name] frame."
+
+/obj/structure/working/grindstone/on_update_icon()
+ . = ..()
+ underlays = list(
+ overlay_image(icon, "[icon_state]-grindstone", stone_material.color, RESET_COLOR),
+ overlay_image(icon, "[initial(icon_state)]-backdrop")
+ )
+
+// Slightly wonky override, but this basically intercepts items being used on the grindstone.
+/obj/structure/working/grindstone/try_take_input(obj/item/used_item, mob/user, silent)
+ if(working)
+ if(!silent)
+ to_chat(user, SPAN_WARNING("\The [src] is already in use, please wait for it to be free."))
+ else
+ start_working()
+ used_item.try_sharpen_with(user, src)
+ if(!QDELETED(src) && working)
+ stop_working()
+ return TRUE
+
+/obj/structure/working/grindstone/get_sharpening_material()
+ RETURN_TYPE(/decl/material)
+ return stone_material
diff --git a/mods/content/item_sharpening/icons/grindstone.dmi b/mods/content/item_sharpening/icons/grindstone.dmi
new file mode 100644
index 00000000000..70b311b63b5
Binary files /dev/null and b/mods/content/item_sharpening/icons/grindstone.dmi differ
diff --git a/mods/content/item_sharpening/item_sharpen.dm b/mods/content/item_sharpening/item_sharpen.dm
new file mode 100644
index 00000000000..a72e928e5e8
--- /dev/null
+++ b/mods/content/item_sharpening/item_sharpen.dm
@@ -0,0 +1,49 @@
+/obj/item/update_name()
+ . = ..()
+ if(has_item_effect(/decl/item_effect/sharpened, IE_CAT_EXAMINE) && get_item_effect_parameter(/decl/item_effect/sharpened, IE_CAT_DAMAGE, IE_PAR_USES) <= 0)
+ SetName("dulled [name]")
+
+/obj/item/proc/can_sharpen_with(obj/sharpening_with)
+ if(!has_item_effect(/decl/item_effect/sharpened, IE_CAT_DAMAGE) || !material || !istype(sharpening_with))
+ return FALSE
+ var/list/params = get_item_effect_parameters(/decl/item_effect/sharpened, IE_CAT_DAMAGE)
+ if(!islist(params) || params[IE_PAR_USES] >= params[IE_PAR_MAX_USES])
+ return FALSE
+ return material.hardness <= sharpening_with.get_sharpening_material()?.hardness
+
+/obj/item/proc/sharpen_with(mob/user, obj/sharpen_with)
+ if(!has_item_effect(/decl/item_effect/sharpened, IE_CAT_DAMAGE))
+ return FALSE
+ var/list/params = get_item_effect_parameters(/decl/item_effect/sharpened, IE_CAT_DAMAGE)
+ if(!islist(params))
+ return FALSE
+ var/max_uses = params[IE_PAR_MAX_USES]
+ if(max_uses <= 0)
+ return FALSE
+ var/uses = params[IE_PAR_USES] || 0
+ if(uses >= max_uses)
+ return FALSE
+ set_item_effect_parameter(/decl/item_effect/sharpened, IE_CAT_DAMAGE, IE_PAR_USES, max_uses)
+ if(uses == 0) // We've sharpened up from dull.
+ update_attack_force()
+ update_name()
+ return TRUE
+
+/obj/item/proc/try_sharpen_with(mob/user, obj/sharpening_with)
+ if(!has_item_effect(/decl/item_effect/sharpened, IE_CAT_DAMAGE))
+ return FALSE
+ if(can_sharpen_with(sharpening_with))
+ user.visible_message("\The [user] begins sharpening \the [src] with \the [sharpening_with].")
+ playsound(loc, 'sound/foley/knife1.ogg', 50) // metallic scrape, TODO better sound
+ if(user.do_skilled(10 SECONDS, SKILL_WEAPONS, src, check_holding = TRUE) && !QDELETED(sharpening_with) && can_sharpen_with(sharpening_with) && sharpen_with(user, sharpening_with))
+ playsound(loc, 'sound/foley/knife1.ogg', 50)
+ user.visible_message("\The [user] sharpens \the [src] with \the [sharpening_with].")
+ else
+ to_chat(user, SPAN_WARNING("\The [src] cannot be [initial(sharp) ? "further sharpened" : "sharpened"] with \the [sharpening_with]."))
+ return TRUE
+
+// We don't override sharp because it's probably still pointy even if it isn't sharpened.
+/obj/item/has_edge()
+ . = ..()
+ if(. && has_item_effect(/decl/item_effect/sharpened, IE_CAT_DAMAGE))
+ return get_item_effect_parameter(/decl/item_effect/sharpened, IE_CAT_DAMAGE, IE_PAR_USES) > 0
diff --git a/mods/content/item_sharpening/whetstone.dm b/mods/content/item_sharpening/whetstone.dm
new file mode 100644
index 00000000000..cdfbb09eea5
--- /dev/null
+++ b/mods/content/item_sharpening/whetstone.dm
@@ -0,0 +1,18 @@
+/obj/item/whetstone
+ name = "whetstone"
+ desc = "A worn-down lozenge used to sharpen blades."
+ icon = 'icons/obj/items/striker.dmi' // TODO unique icon?
+ w_class = ITEM_SIZE_TINY
+ material_alteration = MAT_FLAG_ALTERATION_ALL
+ material = /decl/material/solid/quartz
+
+/obj/item/attackby(obj/item/used_item, mob/user)
+ if(istype(used_item, /obj/item/whetstone))
+ return try_sharpen_with(user, used_item)
+ return ..()
+
+/decl/loadout_option/utility/whetstone
+ name = "whetstone"
+ path = /obj/item/whetstone
+ loadout_flags = null
+ uid = "gear_utility_whetstone"
diff --git a/mods/content/psionics/_psionics.dm b/mods/content/psionics/_psionics.dm
index 9092fd88ae6..fa58ed18f58 100644
--- a/mods/content/psionics/_psionics.dm
+++ b/mods/content/psionics/_psionics.dm
@@ -30,3 +30,12 @@
var/datum/ability_handler/psionics/psi = !is_preview_copy && istype(character) && character.get_ability_handler(/datum/ability_handler/psionics)
if(psi)
psi.update()
+
+/decl/ability/can_use_ability(mob/user, list/metadata, silent = FALSE)
+ . = ..()
+ if(. && is_supernatural)
+ var/spell_leech = user.disrupts_psionics()
+ if(spell_leech)
+ if(!silent)
+ to_chat(user, SPAN_WARNING("You try to marshal your energy, but find it leeched away by \the [spell_leech]!"))
+ return FALSE
diff --git a/mods/content/psionics/_psionics.dme b/mods/content/psionics/_psionics.dme
index df5544cffe1..d52fd095516 100644
--- a/mods/content/psionics/_psionics.dme
+++ b/mods/content/psionics/_psionics.dme
@@ -9,7 +9,6 @@
#include "datum\jobs.dm"
#include "datum\mind.dm"
#include "datum\security_state.dm"
-#include "datum\spells.dm"
#include "datum\surgery.dm"
#include "datum\uplink.dm"
#include "datum\antagonists\foundation.dm"
@@ -27,7 +26,6 @@
#include "items\literature.dm"
#include "items\null_ammo.dm"
#include "items\nullrod.dm"
-#include "items\soulstone.dm"
#include "machines\psimeter.dm"
#include "machines\psimonitor.dm"
#include "system\subsystem_psi.dm"
@@ -54,7 +52,6 @@
#include "system\psionics\interface\ui.dm"
#include "system\psionics\interface\ui_hub.dm"
#include "system\psionics\interface\ui_toggles.dm"
-#include "system\psionics\mob\borer_power.dm"
#include "system\psionics\mob\mob.dm"
#include "system\psionics\mob\mob_assay.dm"
#include "system\psionics\mob\mob_interactions.dm"
diff --git a/mods/content/psionics/datum/chems.dm b/mods/content/psionics/datum/chems.dm
index 1bc713de0eb..e859f0dc515 100644
--- a/mods/content/psionics/datum/chems.dm
+++ b/mods/content/psionics/datum/chems.dm
@@ -1,34 +1,7 @@
/decl/material/liquid/crystal_agent/do_material_check(var/mob/living/M)
. = !!M.get_ability_handler(/datum/ability_handler/psionics) ? /decl/material/nullglass : ..()
-/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/M, total_dose)
+/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/victim, total_dose)
..()
- var/datum/ability_handler/psionics/psi = M.get_ability_handler(/datum/ability_handler/psionics)
+ var/datum/ability_handler/psionics/psi = victim.get_ability_handler(/datum/ability_handler/psionics)
psi?.check_latency_trigger(30, "a [name] overdose")
-
-/decl/chemical_reaction/synthesis/nullglass
- name = "Soulstone"
- result = null
- required_reagents = list(/decl/material/liquid/blood = 15, /decl/material/liquid/crystal_agent = 1)
- result_amount = 1
-
-#ifdef GAMEMODE_PACK_CULT
-/decl/chemical_reaction/synthesis/nullglass/get_alternate_reaction_indicator(var/datum/reagents/holder)
- var/list/blood_data = REAGENT_DATA(holder, /decl/material/liquid/blood)
- var/weakref/donor_ref = LAZYACCESS(blood_data, DATA_BLOOD_DONOR)
- var/mob/living/donor = donor_ref?.resolve()
- . = istype(donor) && !!donor.get_ability_handler(/datum/ability_handler/psionics)
-#endif
-
-/decl/chemical_reaction/synthesis/nullglass/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data)
- var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
- if(reaction_flags)
- #ifdef GAMEMODE_PACK_CULT
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/soulstone(location)
- #else
- CRASH("Nullglass alternate reaction triggered in [holder.my_atom] without cult modpack loaded!")
- #endif
- else
- for(var/i = 1, i <= created_volume*2, i++)
- new /obj/item/shard(location, /decl/material/solid/gemstone/crystal)
\ No newline at end of file
diff --git a/mods/content/psionics/datum/spells.dm b/mods/content/psionics/datum/spells.dm
deleted file mode 100644
index 7c02c352000..00000000000
--- a/mods/content/psionics/datum/spells.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-/spell/cast_check(skipcharge = 0,mob/user = usr, var/list/targets) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
- var/spell_leech = user.disrupts_psionics()
- if(spell_leech)
- to_chat(user, SPAN_WARNING("You try to marshal your energy, but find it leeched away by \the [spell_leech]!"))
- return 0
- . = ..()
-
\ No newline at end of file
diff --git a/mods/content/psionics/items/soulstone.dm b/mods/content/psionics/items/soulstone.dm
deleted file mode 100644
index 3d984a0711c..00000000000
--- a/mods/content/psionics/items/soulstone.dm
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifdef GAMEMODE_PACK_CULT
-/obj/item/soulstone/disrupts_psionics()
- . = !full ? src : FALSE
-
-/obj/item/soulstone/shatter()
- for(var/i=1 to rand(2,5))
- new /obj/item/shard(get_turf(src), /decl/material/nullglass)
- . = ..()
-
-/obj/item/soulstone/withstand_psi_stress(var/stress, var/atom/source)
- . = ..(stress, source)
- if(. > 0)
- . = max(0, . - rand(2,5))
- shatter()
-#endif
\ No newline at end of file
diff --git a/mods/content/psionics/system/psionics/complexus/complexus.dm b/mods/content/psionics/system/psionics/complexus/complexus.dm
index 990edecd13e..0ce5f4cfc18 100644
--- a/mods/content/psionics/system/psionics/complexus/complexus.dm
+++ b/mods/content/psionics/system/psionics/complexus/complexus.dm
@@ -1,5 +1,4 @@
/datum/ability_handler/psionics
-
var/announced = FALSE // Whether or not we have been announced to our holder yet.
var/suppressed = TRUE // Whether or not we are suppressing our psi powers.
var/use_psi_armour = TRUE // Whether or not we should automatically deflect/block incoming damage.
diff --git a/mods/content/psionics/system/psionics/equipment/psipower.dm b/mods/content/psionics/system/psionics/equipment/psipower.dm
index 3d850f27cf2..8aa0afca352 100644
--- a/mods/content/psionics/system/psionics/equipment/psipower.dm
+++ b/mods/content/psionics/system/psionics/equipment/psipower.dm
@@ -15,7 +15,9 @@
. = ..()
/obj/item/ability/psionic/attack_self(var/mob/user)
- sound_to(owner, 'sound/effects/psi/power_fail.ogg')
+ var/mob/owner = owner_ref?.resolve()
+ if(istype(owner))
+ sound_to(owner, 'sound/effects/psi/power_fail.ogg')
. = ..()
/obj/item/ability/psionic/use_on_mob(mob/living/target, mob/living/user, animate = TRUE)
@@ -31,6 +33,7 @@
. = ..(target, user, proximity)
/obj/item/ability/psionic/Process()
+ var/mob/living/owner = owner_ref?.resolve()
var/datum/ability_handler/psionics/psi = istype(owner) && owner.get_ability_handler(/datum/ability_handler/psionics)
psi?.spend_power(maintain_cost, backblast_on_failure = FALSE)
if((!owner || owner.do_psionics_check(maintain_cost, owner) || loc != owner || !(src in owner.get_held_items())) && !QDELETED(src))
diff --git a/mods/content/psionics/system/psionics/equipment/psipower_blade.dm b/mods/content/psionics/system/psionics/equipment/psipower_blade.dm
index fd8b4f947c8..94163e32012 100644
--- a/mods/content/psionics/system/psionics/equipment/psipower_blade.dm
+++ b/mods/content/psionics/system/psionics/equipment/psipower_blade.dm
@@ -1,8 +1,8 @@
/obj/item/ability/psionic/psiblade
name = "psychokinetic slash"
_base_attack_force = 10
- sharp = 1
- edge = 1
+ sharp = TRUE
+ edge = TRUE
maintain_cost = 1
icon_state = "psiblade_short"
diff --git a/mods/content/psionics/system/psionics/equipment/psipower_tk.dm b/mods/content/psionics/system/psionics/equipment/psipower_tk.dm
index 787d2a59050..ee529a0d922 100644
--- a/mods/content/psionics/system/psionics/equipment/psipower_tk.dm
+++ b/mods/content/psionics/system/psionics/equipment/psipower_tk.dm
@@ -9,6 +9,7 @@
. = ..()
/obj/item/ability/psionic/telekinesis/Process()
+ var/mob/living/owner = owner_ref?.resolve()
var/datum/ability_handler/psionics/psi = istype(owner) && owner.get_ability_handler(/datum/ability_handler/psionics)
if(!focus || !isturf(focus.loc) || get_dist(get_turf(focus), get_turf(owner)) > psi?.get_rank(PSI_PSYCHOKINESIS))
owner.drop_from_inventory(src)
@@ -30,6 +31,7 @@
else
return FALSE
+ var/mob/living/owner = owner_ref?.resolve()
var/datum/ability_handler/psionics/psi = istype(owner) && owner.get_ability_handler(/datum/ability_handler/psionics)
if(_focus.anchored || (check_paramount && psi?.get_rank(PSI_PSYCHOKINESIS) < PSI_RANK_PARAMOUNT))
focus = _focus
@@ -88,7 +90,7 @@
else
if(!focus.anchored)
var/user_rank = psi?.get_rank(PSI_PSYCHOKINESIS)
- focus.throw_at(target, user_rank*2, user_rank*10, owner)
+ focus.throw_at(target, user_rank*2, user_rank*10, owner_ref?.resolve())
sleep(1)
sparkle()
@@ -104,5 +106,4 @@
O.icon = 'icons/effects/effects.dmi'
O.icon_state = "nothing"
flick("empdisable",O)
- sleep(5)
- qdel(O)
+ QDEL_IN(src, 0.5 SECONDS)
diff --git a/mods/content/psionics/system/psionics/faculties/coercion.dm b/mods/content/psionics/system/psionics/faculties/coercion.dm
index 2af44aa9335..8a92f058ad1 100644
--- a/mods/content/psionics/system/psionics/faculties/coercion.dm
+++ b/mods/content/psionics/system/psionics/faculties/coercion.dm
@@ -179,7 +179,7 @@
return TRUE
if(accepted_glamour == "Yes")
- to_chat(user, SPAN_DANGER("You layer a glamour across the \the [target]'s senses, beguiling them to unwittingly follow your commands."))
+ to_chat(user, SPAN_DANGER("You layer a glamour across \the [target]'s senses, beguiling them to unwittingly follow your commands."))
to_chat(target, SPAN_DANGER("You have been ensnared by \the [user]'s glamour!"))
beguiled.add_antagonist(target.mind, new_controller = user)
else
diff --git a/mods/content/psionics/system/psionics/interface/ui.dm b/mods/content/psionics/system/psionics/interface/ui.dm
index 4e8adfa83bd..3d8255b2030 100644
--- a/mods/content/psionics/system/psionics/interface/ui.dm
+++ b/mods/content/psionics/system/psionics/interface/ui.dm
@@ -1,14 +1,17 @@
/obj/screen/psi
icon = 'mods/content/psionics/icons/psi.dmi'
requires_ui_style = FALSE
+ apply_screen_overlay = FALSE
var/hidden = TRUE
+ var/can_hide = TRUE
/obj/screen/psi/Initialize(mapload, mob/_owner, ui_style, ui_color, ui_alpha, ui_cat)
. = ..()
update_icon()
/obj/screen/psi/on_update_icon()
- if(hidden)
+ ..()
+ if(hidden && can_hide)
set_invisibility(INVISIBILITY_ABSTRACT)
else
set_invisibility(INVISIBILITY_NONE)
\ No newline at end of file
diff --git a/mods/content/psionics/system/psionics/interface/ui_hub.dm b/mods/content/psionics/system/psionics/interface/ui_hub.dm
index cd87e528211..97c5ba41adc 100644
--- a/mods/content/psionics/system/psionics/interface/ui_hub.dm
+++ b/mods/content/psionics/system/psionics/interface/ui_hub.dm
@@ -6,6 +6,7 @@
maptext_x = 6
maptext_y = -8
requires_ui_style = FALSE
+ can_hide = FALSE
var/image/on_cooldown
var/list/components
@@ -19,6 +20,7 @@
START_PROCESSING(SSprocessing, src)
/obj/screen/psi/hub/on_update_icon()
+ ..()
var/mob/living/owner = owner_ref?.resolve()
var/datum/ability_handler/psionics/psi = istype(owner) && owner.get_ability_handler(/datum/ability_handler/psionics)
icon_state = psi?.suppressed ? "psi_suppressed" : "psi_active"
diff --git a/mods/content/psionics/system/psionics/interface/ui_toggles.dm b/mods/content/psionics/system/psionics/interface/ui_toggles.dm
index 5585ac5d802..93c34b82a27 100644
--- a/mods/content/psionics/system/psionics/interface/ui_toggles.dm
+++ b/mods/content/psionics/system/psionics/interface/ui_toggles.dm
@@ -29,6 +29,7 @@
name = "Show/Hide Psi UI"
icon_state = "arrow_left"
requires_ui_style = FALSE
+ can_hide = FALSE
var/obj/screen/psi/hub/controller
/obj/screen/psi/toggle_psi_menu/Initialize(mapload, mob/_owner, ui_style, ui_color, ui_alpha, ui_cat, obj/screen/psi/hub/_controller)
@@ -43,6 +44,7 @@
controller.update_icon()
/obj/screen/psi/toggle_psi_menu/on_update_icon()
+ ..()
if(hidden)
icon_state = "arrow_left"
else
diff --git a/mods/content/psionics/system/psionics/mob/mob.dm b/mods/content/psionics/system/psionics/mob/mob.dm
index c85902acde4..15cc7914742 100644
--- a/mods/content/psionics/system/psionics/mob/mob.dm
+++ b/mods/content/psionics/system/psionics/mob/mob.dm
@@ -1,4 +1,5 @@
/datum/ability_handler/psionics/refresh_login()
+ . = ..()
update(TRUE)
if(!suppressed)
show_auras()
diff --git a/mods/content/psionics/system/psionics/mob/mob_interactions.dm b/mods/content/psionics/system/psionics/mob/mob_interactions.dm
index 366adb30882..aba8eeb102c 100644
--- a/mods/content/psionics/system/psionics/mob/mob_interactions.dm
+++ b/mods/content/psionics/system/psionics/mob/mob_interactions.dm
@@ -6,8 +6,6 @@
power.handle_post_power(user, target); \
if(istype(result)) { \
sound_to(user, sound('sound/effects/psi/power_evoke.ogg')); \
- LAZYADD(ability_items, result); \
- user.put_in_hands(result); \
} \
return TRUE; \
} \
@@ -28,15 +26,19 @@
INVOKE_PSI_POWERS(user, get_grab_powers(SSpsi.get_faculty_by_intent(user.get_intent())), target)
/datum/ability_handler/psionics/can_do_melee_invocation(mob/user, atom/target)
+ SHOULD_CALL_PARENT(FALSE)
return TRUE
/datum/ability_handler/psionics/do_melee_invocation(mob/user, atom/target)
+ SHOULD_CALL_PARENT(FALSE)
INVOKE_PSI_POWERS(user, get_melee_powers(SSpsi.get_faculty_by_intent(user.get_intent())), target)
/datum/ability_handler/psionics/can_do_ranged_invocation(mob/user, atom/target)
+ SHOULD_CALL_PARENT(FALSE)
return TRUE
/datum/ability_handler/psionics/do_ranged_invocation(mob/user, atom/target)
+ SHOULD_CALL_PARENT(FALSE)
INVOKE_PSI_POWERS(user, get_ranged_powers(SSpsi.get_faculty_by_intent(user.get_intent())), target)
-#undef INVOKE_PSI_POWERS
\ No newline at end of file
+#undef INVOKE_PSI_POWERS
diff --git a/mods/content/standard_jobs/_standard_jobs.dme b/mods/content/standard_jobs/_standard_jobs.dme
index cbba09eacef..a17a75892bb 100644
--- a/mods/content/standard_jobs/_standard_jobs.dme
+++ b/mods/content/standard_jobs/_standard_jobs.dme
@@ -11,6 +11,7 @@
#include "departments\security.dm"
#include "departments\service.dm"
#include "departments\supply.dm"
+#include "jobs\_job.dm"
#include "jobs\captain.dm"
#include "jobs\civilian.dm"
#include "jobs\engineering.dm"
diff --git a/mods/content/standard_jobs/icons/hud.dmi b/mods/content/standard_jobs/icons/hud.dmi
new file mode 100644
index 00000000000..ccea1d4a211
Binary files /dev/null and b/mods/content/standard_jobs/icons/hud.dmi differ
diff --git a/mods/content/standard_jobs/jobs/_job.dm b/mods/content/standard_jobs/jobs/_job.dm
new file mode 100644
index 00000000000..6869734493a
--- /dev/null
+++ b/mods/content/standard_jobs/jobs/_job.dm
@@ -0,0 +1,3 @@
+/datum/job/standard
+ abstract_type = /datum/job/standard
+ hud_icon = 'mods/content/standard_jobs/icons/hud.dmi'
diff --git a/mods/content/standard_jobs/jobs/captain.dm b/mods/content/standard_jobs/jobs/captain.dm
index c0782377252..d7abb62e0cd 100644
--- a/mods/content/standard_jobs/jobs/captain.dm
+++ b/mods/content/standard_jobs/jobs/captain.dm
@@ -1,5 +1,6 @@
-/datum/job/captain
+/datum/job/standard/captain
title = "Captain"
+ hud_icon_state = "hudcaptain"
head_position = 1
department_types = list(/decl/department/command)
total_positions = 1
@@ -33,16 +34,17 @@
/datum/computer_file/program/reports
)
-/datum/job/captain/equip_job(var/mob/living/human/H)
+/datum/job/standard/captain/equip_job(var/mob/living/human/H)
. = ..()
if(.)
H.implant_loyalty(src)
-/datum/job/captain/get_access()
+/datum/job/standard/captain/get_access()
return get_all_station_access()
-/datum/job/hop
+/datum/job/standard/hop
title = "Head of Personnel"
+ hud_icon_state = "hudhop"
head_position = 1
department_types = list(
/decl/department/command,
diff --git a/mods/content/standard_jobs/jobs/civilian.dm b/mods/content/standard_jobs/jobs/civilian.dm
index af71d84e536..1ce8eeb39d0 100644
--- a/mods/content/standard_jobs/jobs/civilian.dm
+++ b/mods/content/standard_jobs/jobs/civilian.dm
@@ -1,5 +1,6 @@
-/datum/job/assistant
+/datum/job/standard/assistant
title = "Assistant"
+ hud_icon_state = "hudassistant"
total_positions = -1
spawn_positions = -1
supervisors = "absolutely everyone"
@@ -10,13 +11,14 @@
outfit_type = /decl/outfit/job/generic/assistant
department_types = list(/decl/department/civilian)
-/datum/job/assistant/get_access()
+/datum/job/standard/assistant/get_access()
if(get_config_value(/decl/config/toggle/assistant_maint))
return list(access_maint_tunnels)
return list()
-/datum/job/chaplain
+/datum/job/standard/chaplain
title = "Chaplain"
+ hud_icon_state = "hudchaplain" // TODO: not always a crucifix
department_types = list(/decl/department/civilian)
total_positions = 1
spawn_positions = 1
@@ -42,9 +44,10 @@
software_on_spawn = list(/datum/computer_file/program/reports)
//Food
-/datum/job/bartender
+/datum/job/standard/bartender
title = "Bartender"
department_types = list(/decl/department/service)
+ hud_icon_state = "hudbartender"
total_positions = 1
spawn_positions = 1
supervisors = "the head of personnel"
@@ -68,8 +71,9 @@
SKILL_CHEMISTRY = SKILL_BASIC
)
-/datum/job/chef
+/datum/job/standard/chef
title = "Chef"
+ hud_icon_state = "hudchef"
department_types = list(/decl/department/service)
total_positions = 2
spawn_positions = 2
@@ -89,8 +93,9 @@
SKILL_CHEMISTRY = SKILL_BASIC
)
-/datum/job/hydro
+/datum/job/standard/hydro
title = "Gardener"
+ hud_icon_state = "hudgardener"
department_types = list(/decl/department/service)
total_positions = 2
spawn_positions = 1
@@ -111,8 +116,9 @@
event_categories = list(ASSIGNMENT_GARDENER)
//Cargo
-/datum/job/qm
+/datum/job/standard/qm
title = "Quartermaster"
+ hud_icon_state = "hudqm"
department_types = list(/decl/department/supply)
total_positions = 1
spawn_positions = 1
@@ -156,11 +162,12 @@
/datum/computer_file/program/reports
)
-/datum/job/cargo_tech
+/datum/job/standard/cargo_tech
title = "Cargo Technician"
department_types = list(/decl/department/supply)
total_positions = 2
spawn_positions = 2
+ hud_icon_state = "hudcargo"
supervisors = "the quartermaster and the head of personnel"
access = list(
access_maint_tunnels,
@@ -192,8 +199,9 @@
/datum/computer_file/program/reports
)
-/datum/job/mining
+/datum/job/standard/mining
title = "Shaft Miner"
+ hud_icon_state = "hudminer"
department_types = list(/decl/department/supply)
total_positions = 3
spawn_positions = 3
@@ -227,11 +235,12 @@
SKILL_PILOT = SKILL_MAX
)
-/datum/job/janitor
+/datum/job/standard/janitor
title = "Janitor"
department_types = list(/decl/department/service)
total_positions = 1
spawn_positions = 1
+ hud_icon_state = "hudjanitor"
supervisors = "the head of personnel"
access = list(
access_janitor,
@@ -261,8 +270,9 @@
event_categories = list(ASSIGNMENT_JANITOR)
//More or less assistants
-/datum/job/librarian
+/datum/job/standard/librarian
title = "Librarian"
+ hud_icon_state = "hudlibrarian"
department_types = list(/decl/department/civilian)
total_positions = 1
spawn_positions = 1
@@ -281,8 +291,9 @@
skill_points = 20
software_on_spawn = list(/datum/computer_file/program/reports)
-/datum/job/lawyer
+/datum/job/standard/lawyer
title = "Internal Affairs Agent"
+ hud_icon_state = "hudia"
department_types = list(/decl/department/support)
total_positions = 2
spawn_positions = 2
@@ -308,7 +319,7 @@
skill_points = 20
software_on_spawn = list(/datum/computer_file/program/reports)
-/datum/job/lawyer/equip_job(var/mob/living/human/H)
+/datum/job/standard/lawyer/equip_job(var/mob/living/human/H)
. = ..()
if(.)
H.implant_loyalty(H)
diff --git a/mods/content/standard_jobs/jobs/engineering.dm b/mods/content/standard_jobs/jobs/engineering.dm
index 40cba546489..84630cb60ba 100644
--- a/mods/content/standard_jobs/jobs/engineering.dm
+++ b/mods/content/standard_jobs/jobs/engineering.dm
@@ -1,5 +1,6 @@
-/datum/job/chief_engineer
+/datum/job/standard/chief_engineer
title = "Chief Engineer"
+ hud_icon_state = "hudce"
head_position = 1
department_types = list(
/decl/department/engineering,
@@ -69,16 +70,15 @@
max_skill = list(
SKILL_CONSTRUCTION = SKILL_MAX,
- SKILL_ELECTRICAL = SKILL_MAX,
- SKILL_ATMOS = SKILL_MAX,
- SKILL_ENGINES = SKILL_MAX
+ SKILL_ELECTRICAL = SKILL_MAX,
+ SKILL_ATMOS = SKILL_MAX,
+ SKILL_ENGINES = SKILL_MAX
)
skill_points = 30
software_on_spawn = list(
/datum/computer_file/program/comm,
/datum/computer_file/program/network_monitor,
/datum/computer_file/program/power_monitor,
- /datum/computer_file/program/supermatter_monitor,
/datum/computer_file/program/alarm_monitor,
/datum/computer_file/program/atmos_control,
/datum/computer_file/program/rcon_console,
@@ -88,10 +88,10 @@
)
event_categories = list(ASSIGNMENT_ENGINEER)
-/datum/job/engineer
+/datum/job/standard/engineer
title = "Engineer"
department_types = list(/decl/department/engineering)
-
+ hud_icon_state = "hudengineer"
total_positions = 8
spawn_positions = 7
supervisors = "the chief engineer"
@@ -130,22 +130,21 @@
min_skill = list(
SKILL_LITERACY = SKILL_ADEPT,
SKILL_COMPUTER = SKILL_BASIC,
- SKILL_EVA = SKILL_BASIC,
- SKILL_CONSTRUCTION = SKILL_ADEPT,
- SKILL_ELECTRICAL = SKILL_BASIC,
- SKILL_ATMOS = SKILL_BASIC,
- SKILL_ENGINES = SKILL_BASIC
+ SKILL_EVA = SKILL_BASIC,
+ SKILL_CONSTRUCTION = SKILL_ADEPT,
+ SKILL_ELECTRICAL = SKILL_BASIC,
+ SKILL_ATMOS = SKILL_BASIC,
+ SKILL_ENGINES = SKILL_BASIC
)
max_skill = list(
SKILL_CONSTRUCTION = SKILL_MAX,
- SKILL_ELECTRICAL = SKILL_MAX,
- SKILL_ATMOS = SKILL_MAX,
- SKILL_ENGINES = SKILL_MAX
+ SKILL_ELECTRICAL = SKILL_MAX,
+ SKILL_ATMOS = SKILL_MAX,
+ SKILL_ENGINES = SKILL_MAX
)
skill_points = 20
software_on_spawn = list(
/datum/computer_file/program/power_monitor,
- /datum/computer_file/program/supermatter_monitor,
/datum/computer_file/program/alarm_monitor,
/datum/computer_file/program/atmos_control,
/datum/computer_file/program/rcon_console,
diff --git a/mods/content/standard_jobs/jobs/medical.dm b/mods/content/standard_jobs/jobs/medical.dm
index 22e4090ebb3..1d281434a51 100644
--- a/mods/content/standard_jobs/jobs/medical.dm
+++ b/mods/content/standard_jobs/jobs/medical.dm
@@ -1,5 +1,6 @@
-/datum/job/cmo
+/datum/job/standard/cmo
title = "Chief Medical Officer"
+ hud_icon_state = "hudcmo"
head_position = 1
department_types = list(
/decl/department/medical,
@@ -74,8 +75,9 @@
)
event_categories = list(ASSIGNMENT_MEDICAL)
-/datum/job/doctor
+/datum/job/standard/doctor
title = "Medical Doctor"
+ hud_icon_state = "hudmed"
department_types = list(/decl/department/medical)
minimal_player_age = 3
total_positions = 5
@@ -129,8 +131,9 @@
skill_points = 22
event_categories = list(ASSIGNMENT_MEDICAL)
-/datum/job/chemist
+/datum/job/standard/chemist
title = "Pharmacist"
+ hud_icon_state = "hudpharmacist"
department_types = list(/decl/department/medical)
minimal_player_age = 7
total_positions = 2
@@ -164,8 +167,9 @@
)
skill_points = 16
-/datum/job/counselor
+/datum/job/standard/counselor
title = "Counselor"
+ hud_icon_state = "hudmed"
alt_titles = list("Mentalist")
department_types = list(/decl/department/medical)
total_positions = 1
@@ -202,15 +206,6 @@
)
give_psionic_implant_on_join = FALSE
-#ifdef MODPACK_PSIONICS
-/datum/job/counselor/equip_job(var/mob/living/human/H)
- if(H.mind.role_alt_title == "Counselor")
- psi_faculties = list("[PSI_REDACTION]" = PSI_RANK_OPERANT)
- if(H.mind.role_alt_title == "Mentalist")
- psi_faculties = list("[PSI_COERCION]" = PSI_RANK_OPERANT)
- return ..()
-#endif
-
// Department-flavor IDs
/obj/item/card/id/medical
name = "identification card"
diff --git a/mods/content/standard_jobs/jobs/science.dm b/mods/content/standard_jobs/jobs/science.dm
index a7a074efbce..548f9147ea7 100644
--- a/mods/content/standard_jobs/jobs/science.dm
+++ b/mods/content/standard_jobs/jobs/science.dm
@@ -1,10 +1,11 @@
-/datum/job/rd
+/datum/job/standard/rd
title = "Chief Science Officer"
head_position = 1
department_types = list(
/decl/department/science,
/decl/department/command
)
+ hud_icon_state = "hudrd"
total_positions = 1
spawn_positions = 1
supervisors = "the captain"
@@ -74,13 +75,14 @@
skill_points = 30
event_categories = list(ASSIGNMENT_SCIENTIST)
-/datum/job/scientist
+/datum/job/standard/scientist
title = "Scientist"
department_types = list(/decl/department/science)
total_positions = 6
spawn_positions = 4
supervisors = "the Chief Science Officer"
selection_color = "#633d63"
+ hud_icon_state = "hudscientist"
economic_power = 7
access = list(
access_robotics,
@@ -122,8 +124,9 @@
skill_points = 20
event_categories = list(ASSIGNMENT_SCIENTIST)
-/datum/job/roboticist
+/datum/job/standard/roboticist
title = "Roboticist"
+ hud_icon_state = "hudroboticist"
department_types = list(/decl/department/science)
total_positions = 2
spawn_positions = 2
diff --git a/mods/content/standard_jobs/jobs/security.dm b/mods/content/standard_jobs/jobs/security.dm
index f58305f7ae2..345f595a635 100644
--- a/mods/content/standard_jobs/jobs/security.dm
+++ b/mods/content/standard_jobs/jobs/security.dm
@@ -1,5 +1,6 @@
-/datum/job/hos
+/datum/job/standard/hos
title = "Head of Security"
+ hud_icon_state = "hudhos"
head_position = 1
department_types = list(
/decl/department/security,
@@ -87,14 +88,15 @@
)
event_categories = list(ASSIGNMENT_SECURITY)
-/datum/job/hos/equip_job(var/mob/living/human/H)
+/datum/job/standard/hos/equip_job(var/mob/living/human/H)
. = ..()
if(.)
H.implant_loyalty(H)
-/datum/job/warden
+/datum/job/standard/warden
title = "Warden"
department_types = list(/decl/department/security)
+ hud_icon_state = "hudwarden"
total_positions = 1
spawn_positions = 1
supervisors = "the head of security"
@@ -142,10 +144,10 @@
/datum/computer_file/program/camera_monitor
)
-/datum/job/detective
+/datum/job/standard/detective
title = "Detective"
department_types = list(/decl/department/security)
-
+ hud_icon_state = "huddetective"
total_positions = 2
spawn_positions = 2
supervisors = "the head of security"
@@ -192,8 +194,9 @@
/datum/computer_file/program/camera_monitor
)
-/datum/job/officer
+/datum/job/standard/officer
title = "Security Officer"
+ hud_icon_state = "hudsec"
department_types = list(/decl/department/security)
total_positions = 4
spawn_positions = 4
diff --git a/mods/content/standard_jobs/jobs/synthetics.dm b/mods/content/standard_jobs/jobs/synthetics.dm
index e787da9e011..fa023f0a0d0 100644
--- a/mods/content/standard_jobs/jobs/synthetics.dm
+++ b/mods/content/standard_jobs/jobs/synthetics.dm
@@ -1,4 +1,4 @@
-/datum/job/computer
+/datum/job/standard/computer
title = "Computer"
event_categories = list(ASSIGNMENT_COMPUTER)
total_positions = 0 // Not used for AI, see is_position_available below and modules/mob/living/silicon/ai/latejoin.dm
@@ -11,7 +11,8 @@
economic_power = 0
outfit_type = /decl/outfit/job/silicon/ai
loadout_allowed = FALSE
- hud_icon = "hudblank"
+ hud_icon_state = "hudblank"
+ hud_icon = null
skill_points = 0
no_skill_buffs = TRUE
guestbanned = 1
@@ -19,16 +20,16 @@
skip_loadout_preview = TRUE
department_types = list(/decl/department/miscellaneous)
-/datum/job/computer/equip_job(var/mob/living/human/H)
+/datum/job/standard/computer/equip_job(var/mob/living/human/H)
return !!H
-/datum/job/computer/is_position_available()
+/datum/job/standard/computer/is_position_available()
return (empty_playable_ai_cores.len != 0)
-/datum/job/computer/handle_variant_join(var/mob/living/human/H, var/alt_title)
+/datum/job/standard/computer/handle_variant_join(var/mob/living/human/H, var/alt_title)
return H
-/datum/job/computer/do_spawn_special(var/mob/living/character, var/mob/new_player/new_player_mob, var/latejoin)
+/datum/job/standard/computer/do_spawn_special(var/mob/living/character, var/mob/new_player/new_player_mob, var/latejoin)
character = character.AIize() // AIize the character, but don't move them yet
// is_available for AI checks that there is an empty core available in this list
@@ -46,7 +47,7 @@
qdel(C)
return TRUE
-/datum/job/robot
+/datum/job/standard/robot
title = "Robot"
event_categories = list(ASSIGNMENT_ROBOT)
total_positions = 2
@@ -58,7 +59,8 @@
economic_power = 0
loadout_allowed = FALSE
outfit_type = /decl/outfit/job/silicon/cyborg
- hud_icon = "hudblank"
+ hud_icon_state = "hudblank"
+ hud_icon = null
skill_points = 0
no_skill_buffs = TRUE
guestbanned = 1
@@ -66,14 +68,14 @@
skip_loadout_preview = TRUE
department_types = list(/decl/department/miscellaneous)
-/datum/job/robot/handle_variant_join(var/mob/living/human/H, var/alt_title)
+/datum/job/standard/robot/handle_variant_join(var/mob/living/human/H, var/alt_title)
if(H)
return H.Robotize(SSrobots.get_mob_type_by_title(alt_title || title))
-/datum/job/robot/equip_job(var/mob/living/human/H)
+/datum/job/standard/robot/equip_job(var/mob/living/human/H)
return !!H
-/datum/job/robot/New()
+/datum/job/standard/robot/New()
..()
alt_titles = SSrobots.robot_alt_titles.Copy()
alt_titles -= title // So the unit test doesn't flip out if a mob or brain type is declared for our main title.
diff --git a/mods/content/supermatter/_supermatter.dm b/mods/content/supermatter/_supermatter.dm
new file mode 100644
index 00000000000..78daa387234
--- /dev/null
+++ b/mods/content/supermatter/_supermatter.dm
@@ -0,0 +1,23 @@
+// These are used by supermatter and supermatter monitor program, mostly for UI updating purposes. Higher should always be worse!
+#define SUPERMATTER_ERROR -1 // Unknown status, shouldn't happen but just in case.
+#define SUPERMATTER_INACTIVE 0 // No or minimal energy
+#define SUPERMATTER_NORMAL 1 // Normal operation
+#define SUPERMATTER_NOTIFY 2 // Ambient temp > 80% of CRITICAL_TEMPERATURE
+#define SUPERMATTER_WARNING 3 // Ambient temp > CRITICAL_TEMPERATURE OR integrity damaged
+#define SUPERMATTER_DANGER 4 // Integrity < 50%
+#define SUPERMATTER_EMERGENCY 5 // Integrity < 25%
+#define SUPERMATTER_DELAMINATING 6 // Pretty obvious.
+
+#define SUPERMATTER_DATA_EER "Relative EER"
+#define SUPERMATTER_DATA_TEMPERATURE "Temperature"
+#define SUPERMATTER_DATA_PRESSURE "Pressure"
+#define SUPERMATTER_DATA_EPR "Chamber EPR"
+
+/decl/modpack/supermatter
+ name = "Supermatter Content"
+ desc = "This modpack includes the supermatter engine and related content."
+ nanoui_directory = "mods/content/supermatter/nano_templates/"
+
+/decl/modpack/supermatter/pre_initialize()
+ . = ..()
+ global.debug_verbs |= /datum/admins/proc/setup_supermatter
\ No newline at end of file
diff --git a/mods/content/supermatter/_supermatter.dme b/mods/content/supermatter/_supermatter.dme
new file mode 100644
index 00000000000..fb6723cce50
--- /dev/null
+++ b/mods/content/supermatter/_supermatter.dme
@@ -0,0 +1,30 @@
+#ifndef CONTENT_PACK_SUPERMATTER
+#define CONTENT_PACK_SUPERMATTER
+// BEGIN_INCLUDE
+#include "_supermatter.dm"
+#include "admin_setup_supermatter.dm"
+#include "datums\sm_codex.dm"
+#include "datums\sm_follow.dm"
+#include "datums\sm_grief_fix.dm"
+#include "datums\sm_looping_sound.dm"
+#include "datums\sm_supply_drop.dm"
+#include "datums\sm_supply_pack.dm"
+#include "datums\supermatter_monitor.dm"
+#include "endgame_cascade\cascade_blob.dm"
+#include "endgame_cascade\portal.dm"
+#include "endgame_cascade\universe.dm"
+#include "items\sm_book.dm"
+#include "items\sm_grenade.dm"
+#include "machinery\sm_supply_beacon.dm"
+#include "machinery\supermatter.dm"
+#include "machinery\supermatter_core_console.dm"
+#include "overrides\sm_fuel_compressor.dm"
+#include "overrides\sm_meteor.dm"
+#include "overrides\sm_singularity.dm"
+#include "overrides\sm_strings.dm"
+#include "overrides\sm_trader.dm"
+#include "overrides\sm_unit_tests.dm"
+#include "overrides\sm_xenoarchaeology.dm"
+#include "structures\sm_closets.dm"
+// END_INCLUDE
+#endif
diff --git a/mods/content/supermatter/admin_setup_supermatter.dm b/mods/content/supermatter/admin_setup_supermatter.dm
new file mode 100644
index 00000000000..9664671e836
--- /dev/null
+++ b/mods/content/supermatter/admin_setup_supermatter.dm
@@ -0,0 +1,116 @@
+#define ENERGY_NITROGEN 115 // Roughly 8 emitter shots.
+#define ENERGY_CARBONDIOXIDE 150 // Roughly 10 emitter shots.
+#define ENERGY_HYDROGEN 300 // Roughly 20 emitter shots.
+
+/datum/admins/proc/setup_supermatter()
+ set category = "Debug"
+ set name = "Setup Supermatter"
+ set desc = "Allows you to start the Supermatter engine."
+
+ if (!istype(src,/datum/admins))
+ src = usr.client.holder
+ if (!istype(src,/datum/admins))
+ to_chat(usr, "Error: you are not an admin!")
+ return
+
+ var/response = input(usr, "Are you sure? This will start up the engine with selected gas as coolant.", "Engine setup") as null|anything in list("N2", "CO2", "H2", "Abort")
+ if(!response || response == "Abort")
+ return
+
+ var/errors = 0
+ var/warnings = 0
+ var/success = 0
+
+ log_and_message_admins("## SUPERMATTER SETUP - Setup initiated by [usr] using coolant type [response].")
+
+ // CONFIGURATION PHASE
+ // Coolant canisters, set types according to response.
+ for(var/obj/effect/engine_setup/coolant_canister/C in global.engine_setup_markers)
+ switch(response)
+ if("N2")
+ C.canister_type = /obj/machinery/portable_atmospherics/canister/nitrogen/engine_setup/
+ continue
+ if("CO2")
+ C.canister_type = /obj/machinery/portable_atmospherics/canister/carbon_dioxide/engine_setup/
+ continue
+ if("H2")
+ C.canister_type = /obj/machinery/portable_atmospherics/canister/hydrogen/engine_setup/
+ continue
+
+ for(var/obj/effect/engine_setup/core/C in global.engine_setup_markers)
+ switch(response)
+ if("N2")
+ C.energy_setting = ENERGY_NITROGEN
+ continue
+ if("CO2")
+ C.energy_setting = ENERGY_CARBONDIOXIDE
+ continue
+ if("H2")
+ C.energy_setting = ENERGY_HYDROGEN
+ continue
+
+ for(var/obj/effect/engine_setup/filter/F in global.engine_setup_markers)
+ F.coolant = response
+
+ var/list/delayed_objects = list()
+ // SETUP PHASE
+ for(var/obj/effect/engine_setup/S in global.engine_setup_markers)
+ var/result = S.activate(0)
+ switch(result)
+ if(ENGINE_SETUP_OK)
+ success++
+ continue
+ if(ENGINE_SETUP_WARNING)
+ warnings++
+ continue
+ if(ENGINE_SETUP_ERROR)
+ errors++
+ log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.")
+ break
+ if(ENGINE_SETUP_DELAYED)
+ delayed_objects.Add(S)
+ continue
+
+ if(!errors)
+ for(var/obj/effect/engine_setup/S in delayed_objects)
+ var/result = S.activate(1)
+ switch(result)
+ if(ENGINE_SETUP_OK)
+ success++
+ continue
+ if(ENGINE_SETUP_WARNING)
+ warnings++
+ continue
+ if(ENGINE_SETUP_ERROR)
+ errors++
+ log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.")
+ break
+
+ log_and_message_admins("## SUPERMATTER SETUP - Setup completed with [errors] errors, [warnings] warnings and [success] successful steps.")
+
+ return
+
+
+
+// Energises the supermatter. Errors when unable to locate supermatter.
+/obj/effect/engine_setup/core
+ name = "Supermatter Core Marker"
+ var/energy_setting = 0
+
+/obj/effect/engine_setup/core/activate(var/last = 0)
+ if(!last)
+ return ENGINE_SETUP_DELAYED
+ ..()
+ var/obj/machinery/power/supermatter/SM = locate() in get_turf(src)
+ if(!SM)
+ log_and_message_admins("## ERROR: Unable to locate supermatter core at [x] [y] [z]!")
+ return ENGINE_SETUP_ERROR
+ if(!energy_setting)
+ log_and_message_admins("## ERROR: Energy setting unset at [x] [y] [z]!")
+ return ENGINE_SETUP_ERROR
+ SM.power = energy_setting
+ return ENGINE_SETUP_OK
+
+#undef ENERGY_NITROGEN
+#undef ENERGY_CARBONDIOXIDE
+#undef ENERGY_HYDROGEN
diff --git a/mods/content/supermatter/datums/sm_codex.dm b/mods/content/supermatter/datums/sm_codex.dm
new file mode 100644
index 00000000000..c0d5c160fae
--- /dev/null
+++ b/mods/content/supermatter/datums/sm_codex.dm
@@ -0,0 +1,21 @@
+
+/datum/codex_entry/guide/supermatter
+ name = "Guide to Supermatter Engines"
+ available_to_map_tech_level = MAP_TECH_LEVEL_SPACE
+
+/datum/codex_entry/supermatter
+ associated_paths = list(/obj/machinery/power/supermatter)
+ mechanics_text = "When energized by a laser (or something hitting it), it emits radiation and heat. If the heat reaches above 7000 kelvin, it will send an alert and start taking damage. \
+ After integrity falls to zero percent, it will delaminate, causing a massive explosion, station-wide radiation spikes, and hallucinations. \
+ Supermatter reacts badly to oxygen in the atmosphere. It'll also heat up really quick if it is in vacuum. \
+ \
+ Supermatter cores are extremely dangerous to be close to, and requires protection to handle properly. The protection you will need is: \
+ Optical meson scanners on your eyes, to prevent hallucinations when looking at the supermatter. \
+ Radiation helmet and suit, as the supermatter is radioactive. \
+ \
+ Touching the supermatter will result in *instant death*, with no corpse left behind! You can drag the supermatter, but anything else will kill you. \
+ It is advised to obtain a genetic backup before trying to drag it."
+ antag_text = "Exposing the supermatter to oxygen or vaccum will cause it to start rapidly heating up. Sabotaging the supermatter and making it explode will \
+ cause a period of lag as the explosion is processed by the server, as well as irradiating the entire station and causing hallucinations to happen. \
+ Wearing radiation equipment will protect you from most of the delamination effects sans explosion."
+ available_to_map_tech_level = MAP_TECH_LEVEL_SPACE
\ No newline at end of file
diff --git a/mods/content/supermatter/datums/sm_follow.dm b/mods/content/supermatter/datums/sm_follow.dm
new file mode 100644
index 00000000000..5b221ad03d6
--- /dev/null
+++ b/mods/content/supermatter/datums/sm_follow.dm
@@ -0,0 +1,3 @@
+/datum/follow_holder/supermatter
+ sort_order = 10
+ followed_type = /obj/machinery/power/supermatter
\ No newline at end of file
diff --git a/mods/content/supermatter/datums/sm_grief_fix.dm b/mods/content/supermatter/datums/sm_grief_fix.dm
new file mode 100644
index 00000000000..70dd9469abc
--- /dev/null
+++ b/mods/content/supermatter/datums/sm_grief_fix.dm
@@ -0,0 +1,8 @@
+/decl/atmos_grief_fix_step/supermatter
+ name = "Supermatter depowered"
+ sort_order = 0
+
+/decl/atmos_grief_fix_step/supermatter/act()
+ // Depower the supermatter, as it would quickly blow up once we remove all gases from the pipes.
+ for(var/obj/machinery/power/supermatter/S in SSmachines.machinery)
+ S.power = 0
\ No newline at end of file
diff --git a/code/modules/supermatter/sm_looping_sound.dm b/mods/content/supermatter/datums/sm_looping_sound.dm
similarity index 100%
rename from code/modules/supermatter/sm_looping_sound.dm
rename to mods/content/supermatter/datums/sm_looping_sound.dm
diff --git a/mods/content/supermatter/datums/sm_supply_drop.dm b/mods/content/supermatter/datums/sm_supply_drop.dm
new file mode 100644
index 00000000000..1560d1118d2
--- /dev/null
+++ b/mods/content/supermatter/datums/sm_supply_drop.dm
@@ -0,0 +1,5 @@
+/datum/supply_drop_loot/supermatter
+ name = "Supermatter"
+/datum/supply_drop_loot/supermatter/New()
+ ..()
+ contents = list(/obj/machinery/power/supermatter)
diff --git a/mods/content/supermatter/datums/sm_supply_pack.dm b/mods/content/supermatter/datums/sm_supply_pack.dm
new file mode 100644
index 00000000000..5261f06a069
--- /dev/null
+++ b/mods/content/supermatter/datums/sm_supply_pack.dm
@@ -0,0 +1,6 @@
+/decl/hierarchy/supply_pack/engineering/smbig
+ name = "Power - Supermatter core"
+ contains = list(/obj/machinery/power/supermatter)
+ containertype = /obj/structure/closet/crate/secure/large/supermatter
+ containername = "\improper Supermatter crate (CAUTION)"
+ access = access_ce
\ No newline at end of file
diff --git a/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm b/mods/content/supermatter/datums/supermatter_monitor.dm
similarity index 91%
rename from code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm
rename to mods/content/supermatter/datums/supermatter_monitor.dm
index e139e3c4f28..518d84a7f18 100644
--- a/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm
+++ b/mods/content/supermatter/datums/supermatter_monitor.dm
@@ -5,7 +5,7 @@
/datum/computer_file/program/supermatter_monitor
filename = "supmon"
filedesc = "Supermatter Monitoring"
- nanomodule_path = /datum/nano_module/program/supermatter_monitor/
+ nanomodule_path = /datum/nano_module/program/supermatter_monitor
program_icon_state = "smmon_0"
program_key_state = "tech_key"
program_menu_icon = "notice"
@@ -215,3 +215,20 @@
if(S.uid == newuid)
active = S
return 1
+
+// Add this to the software list for borgs
+/obj/item/robot_module/engineering/grant_software()
+ software |= /datum/computer_file/program/supermatter_monitor
+ return ..()
+
+/obj/item/robot_module/flying/repair/grant_software()
+ software |= /datum/computer_file/program/supermatter_monitor
+ return ..()
+
+/obj/machinery/computer/modular/telescreen/preset/engineering/Initialize(mapload, d, populate_parts)
+ default_software |= /datum/computer_file/program/supermatter_monitor
+ return ..()
+
+/obj/machinery/computer/modular/preset/engineering/Initialize(mapload, d, populate_parts)
+ default_software |= /datum/computer_file/program/supermatter_monitor
+ return ..()
\ No newline at end of file
diff --git a/code/game/gamemodes/endgame/supermatter_cascade/cascade_blob.dm b/mods/content/supermatter/endgame_cascade/cascade_blob.dm
similarity index 98%
rename from code/game/gamemodes/endgame/supermatter_cascade/cascade_blob.dm
rename to mods/content/supermatter/endgame_cascade/cascade_blob.dm
index ef04b1069f7..6cd76d14233 100644
--- a/code/game/gamemodes/endgame/supermatter_cascade/cascade_blob.dm
+++ b/mods/content/supermatter/endgame_cascade/cascade_blob.dm
@@ -9,7 +9,7 @@
//luminosity = 5
//l_color="#0066ff"
plane = ABOVE_LIGHTING_PLANE
- layer = SUPERMATTER_WALL_LAYER
+ layer = SUBSPACE_WALL_LAYER
var/list/avail_dirs = list(NORTH,SOUTH,EAST,WEST,UP,DOWN)
diff --git a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm b/mods/content/supermatter/endgame_cascade/portal.dm
similarity index 100%
rename from code/game/gamemodes/endgame/supermatter_cascade/portal.dm
rename to mods/content/supermatter/endgame_cascade/portal.dm
diff --git a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm b/mods/content/supermatter/endgame_cascade/universe.dm
similarity index 96%
rename from code/game/gamemodes/endgame/supermatter_cascade/universe.dm
rename to mods/content/supermatter/endgame_cascade/universe.dm
index e9b2d2e40fd..ccca16707e4 100644
--- a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm
+++ b/mods/content/supermatter/endgame_cascade/universe.dm
@@ -1,6 +1,3 @@
-var/global/universe_has_ended = 0
-
-
/datum/universal_state/supermatter_cascade
name = "Supermatter Cascade"
desc = "Unknown harmonance affecting universal substructure, converting nearby matter to supermatter."
@@ -70,9 +67,10 @@ var/global/universe_has_ended = 0
if(!invalid_area)
A.update_icon()
+// TODO: Should this be changed to use the actual ambient lights system...?
/datum/universal_state/supermatter_cascade/OverlayAndAmbientSet()
spawn(0)
- for(var/datum/lighting_corner/L in world)
+ for(var/datum/lighting_corner/L in SSlighting.lighting_corners)
if(isAdminLevel(L.z))
L.update_lumcount(1,1,1)
else
diff --git a/mods/content/supermatter/items/sm_book.dm b/mods/content/supermatter/items/sm_book.dm
new file mode 100644
index 00000000000..8230625788a
--- /dev/null
+++ b/mods/content/supermatter/items/sm_book.dm
@@ -0,0 +1,6 @@
+/obj/item/book/manual/supermatter_engine
+ name = "supermatter engine reference manual"
+ icon = 'icons/obj/items/books/book_supermatter.dmi'
+ author = "Central Engineering Division"
+ title = "Supermatter Engine Operating Manual"
+ guide_decl = /datum/codex_entry/guide/supermatter
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/grenades/supermatter.dm b/mods/content/supermatter/items/sm_grenade.dm
similarity index 50%
rename from code/game/objects/items/weapons/grenades/supermatter.dm
rename to mods/content/supermatter/items/sm_grenade.dm
index 4f2758b53e3..b7f3186e666 100644
--- a/code/game/objects/items/weapons/grenades/supermatter.dm
+++ b/mods/content/supermatter/items/sm_grenade.dm
@@ -33,3 +33,25 @@
if(world.time > implode_at)
explosion(loc, 0, 1, 3, 4)
qdel(src)
+
+/obj/item/box/supermatters
+ name = "box of supermatter grenades"
+ desc = "A box containing 5 highly experimental supermatter grenades."
+ icon_state = "radbox"
+
+/obj/item/box/supermatters/WillContain()
+ return list(/obj/item/grenade/supermatter = 5)
+
+/datum/uplink_item/item/grenades/supermatter
+ name = "1x Supermatter Grenade"
+ desc = "This grenade contains a small supermatter shard which will delaminate upon activation and pull in nearby objects, irradiate lifeforms, and eventually explode."
+ item_cost = 15
+ antag_roles = list(/decl/special_role/mercenary)
+ path = /obj/item/grenade/supermatter
+
+/datum/uplink_item/item/grenades/supermatters
+ name = "5x Supermatter Grenades"
+ desc = "These grenades contains a small supermatter shard which will delaminate upon activation and pull in nearby objects, irradiate lifeforms, and eventually explode."
+ item_cost = 60
+ antag_roles = list(/decl/special_role/mercenary)
+ path = /obj/item/box/supermatters
diff --git a/mods/content/supermatter/machinery/sm_supply_beacon.dm b/mods/content/supermatter/machinery/sm_supply_beacon.dm
new file mode 100644
index 00000000000..e6a622480b6
--- /dev/null
+++ b/mods/content/supermatter/machinery/sm_supply_beacon.dm
@@ -0,0 +1,7 @@
+/obj/item/supply_beacon/supermatter
+ name = "inactive supermatter supply beacon"
+ deploy_path = /obj/structure/supply_beacon/supermatter
+
+/obj/structure/supply_beacon/supermatter
+ name = "supermatter supply beacon"
+ drop_type = "supermatter"
diff --git a/code/modules/supermatter/supermatter.dm b/mods/content/supermatter/machinery/supermatter.dm
similarity index 98%
rename from code/modules/supermatter/supermatter.dm
rename to mods/content/supermatter/machinery/supermatter.dm
index 676104bd863..b300501036c 100644
--- a/code/modules/supermatter/supermatter.dm
+++ b/mods/content/supermatter/machinery/supermatter.dm
@@ -99,7 +99,7 @@ var/global/list/supermatter_delam_accent_sounds = list(
SPAN_DANGER("As \the [source] slowly stops resonating, you find your skin covered in new radiation burns."), 1,\
SPAN_DANGER("The unearthly ringing subsides and you notice you have new radiation burns."), 2)
else
- M.show_message(SPAN_DANGER("You hear an uneartly ringing and notice your skin is covered in fresh radiation burns."), 2)
+ M.show_message(SPAN_DANGER("You hear an unearthly ringing and notice your skin is covered in fresh radiation burns."), 2)
var/rads = 500
SSradiation.radiate(source, rads)
@@ -113,9 +113,10 @@ var/global/list/supermatter_delam_accent_sounds = list(
light_range = 4
layer = ABOVE_HUMAN_LAYER
matter = list(
- /decl/material/solid/supermatter = MATTER_AMOUNT_PRIMARY,
+ /decl/material/solid/exotic_matter = MATTER_AMOUNT_PRIMARY,
/decl/material/solid/metal/steel = MATTER_AMOUNT_REINFORCEMENT
)
+ w_class = ITEM_SIZE_LARGE_STRUCTURE
var/nitrogen_retardation_factor = 0.15 // Higher == N2 slows reaction more
var/thermal_release_modifier = 10000 // Higher == more heat released during reaction
@@ -696,6 +697,7 @@ var/global/list/supermatter_delam_accent_sounds = list(
desc = "A strangely translucent and iridescent crystal that looks like it used to be part of a larger structure. You get headaches just from looking at it."
icon = 'icons/obj/supermatter_32.dmi'
icon_state = "supermatter_shard"
+ w_class = ITEM_SIZE_STRUCTURE
warning_point = 50
emergency_point = 400
@@ -708,6 +710,7 @@ var/global/list/supermatter_delam_accent_sounds = list(
/obj/machinery/power/supermatter/medium
icon = 'icons/obj/supermatter_32.dmi'
+ w_class = (ITEM_SIZE_STRUCTURE + ITEM_SIZE_LARGE_STRUCTURE) / 2 // halfway between a shard and a normal SM
/obj/machinery/power/supermatter/shard/announce_warning() //Shards don't get announcements
return
diff --git a/mods/content/supermatter/machinery/supermatter_core_console.dm b/mods/content/supermatter/machinery/supermatter_core_console.dm
new file mode 100644
index 00000000000..8b2bf0e175c
--- /dev/null
+++ b/mods/content/supermatter/machinery/supermatter_core_console.dm
@@ -0,0 +1,45 @@
+// Does this really need to be its own thing...?
+// Can it not just be a stock parts preset or something?
+/obj/machinery/computer/air_control/supermatter_core
+ frequency = 1438
+ out_pressure_mode = 1
+
+/datum/fabricator_recipe/imprinter/circuit/supermatter_control
+ path = /obj/item/stock_parts/circuitboard/air_management/supermatter_core
+
+/obj/item/stock_parts/circuitboard/air_management/supermatter_core
+ name = "circuitboard (core control)"
+ build_path = /obj/machinery/computer/air_control/supermatter_core
+ frequency = 1438
+ var/input_tag
+ var/output_tag
+
+ var/list/input_info = list()
+ var/list/output_info = list()
+
+ var/input_flow_setting = 700
+ var/pressure_setting = 100
+
+/obj/item/stock_parts/circuitboard/air_management/supermatter_core/construct(var/obj/machinery/computer/air_control/supermatter_core/SC)
+ if(..(SC))
+ SC.input_tag = input_tag
+ SC.output_tag = output_tag
+
+ SC.input_info = input_info.Copy()
+ SC.output_info = output_info.Copy()
+
+ SC.input_flow_setting = input_flow_setting
+ SC.pressure_setting = input_flow_setting
+ return 1
+
+/obj/item/stock_parts/circuitboard/air_management/supermatter_core/deconstruct(var/obj/machinery/computer/air_control/supermatter_core/SC)
+ if(..(SC))
+ input_tag = SC.input_tag
+ output_tag = SC.output_tag
+
+ input_info = SC.input_info.Copy()
+ output_info = SC.output_info.Copy()
+
+ input_flow_setting = SC.input_flow_setting
+ pressure_setting = SC.input_flow_setting
+ return 1
\ No newline at end of file
diff --git a/nano/templates/supermatter_crystal.tmpl b/mods/content/supermatter/nano_templates/supermatter_crystal.tmpl
similarity index 100%
rename from nano/templates/supermatter_crystal.tmpl
rename to mods/content/supermatter/nano_templates/supermatter_crystal.tmpl
diff --git a/nano/templates/supermatter_monitor.tmpl b/mods/content/supermatter/nano_templates/supermatter_monitor.tmpl
similarity index 100%
rename from nano/templates/supermatter_monitor.tmpl
rename to mods/content/supermatter/nano_templates/supermatter_monitor.tmpl
diff --git a/mods/content/supermatter/overrides/sm_fuel_compressor.dm b/mods/content/supermatter/overrides/sm_fuel_compressor.dm
new file mode 100644
index 00000000000..e259fa26625
--- /dev/null
+++ b/mods/content/supermatter/overrides/sm_fuel_compressor.dm
@@ -0,0 +1,13 @@
+/obj/machinery/fuel_compressor/add_material(obj/thing, mob/user)
+ . = ..()
+ if(.)
+ return TRUE
+ if(istype(thing, /obj/machinery/power/supermatter/shard))
+ var/exotic_matter_amount = thing?.matter?[/decl/material/solid/exotic_matter]
+ if(exotic_matter_amount <= 0)
+ return FALSE
+ stored_material[/decl/material/solid/exotic_matter] = exotic_matter_amount
+ to_chat(user, SPAN_NOTICE("You awkwardly cram \the [thing] into \the [src]'s material buffer."))
+ qdel(thing)
+ return TRUE
+ return FALSE
\ No newline at end of file
diff --git a/mods/content/supermatter/overrides/sm_meteor.dm b/mods/content/supermatter/overrides/sm_meteor.dm
new file mode 100644
index 00000000000..449ad80fbb9
--- /dev/null
+++ b/mods/content/supermatter/overrides/sm_meteor.dm
@@ -0,0 +1,5 @@
+/obj/effect/meteor/destroyer/supermatter
+ name = "supermatter shard"
+ desc = "Oh god, what will be next..?"
+ icon = 'icons/obj/supermatter_32.dmi'
+ icon_state = "supermatter"
diff --git a/mods/content/supermatter/overrides/sm_singularity.dm b/mods/content/supermatter/overrides/sm_singularity.dm
new file mode 100644
index 00000000000..b13506cd580
--- /dev/null
+++ b/mods/content/supermatter/overrides/sm_singularity.dm
@@ -0,0 +1,46 @@
+#define STAGE_SUPER 11
+
+/// A singularity that has the mass of a supermatter crystal.
+/decl/singularity_stage/stage_super
+ name = "super gravitational singularity"
+ desc = "A gravitational singularity with the properties of supermatter. It has the power to destroy worlds."
+ min_energy = 50000
+ max_energy = INFINITY
+ stage_size = STAGE_SUPER
+ footprint = 6
+ icon = 'icons/effects/352x352.dmi'
+ icon_state = "singularity_s11"//uh, whoever drew that, you know that black holes are supposed to look dark right? What's this, the clown's singulo?
+ pixel_x = -160
+ pixel_y = -160
+ grav_pull = 16
+ consume_range = 5
+ dissipates_over_time = 0 //It cant go smaller due to e loss
+ event_chance = 25 //Events will fire off more often.
+ forced_event = /decl/singularity_event/supermatter_wave
+ wander = TRUE
+ explosion_vulnerable = FALSE
+ em_heavy_range = 12
+ em_light_range = 16
+ mesmerize_text = "helpless"
+ the_goggles_do_nothing = TRUE
+ ignore_obstacles = TRUE
+
+/decl/singularity_stage/stage_super/grow_to(obj/effect/singularity/source)
+ source.visible_message(SPAN_SINISTER("You witness the creation of a destructive force that cannot possibly be stopped by human hands."))
+
+// why is this not shrink_from or something?
+/decl/singularity_stage/stage_five/shrink_to(obj/effect/singularity/source)
+ source.visible_message(SPAN_WARNING("\The [source] miraculously reduces in size and loses its supermatter properties."))
+
+// Singularity event
+/decl/singularity_event/supermatter_wave/handle_event(obj/effect/singularity/source)
+ for(var/mob/living/M in view(10, source.loc))
+ to_chat(M, SPAN_WARNING("You hear an unearthly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat."))
+ if(prob(67))
+ to_chat(M, SPAN_NOTICE("Miraculously, it fails to kill you."))
+ else
+ to_chat(M, SPAN_DANGER("You don't even have a moment to react as you are reduced to ashes by the intense radiation."))
+ M.dust()
+ SSradiation.radiate(source, rand(source.energy))
+
+#undef STAGE_SUPER
\ No newline at end of file
diff --git a/mods/content/supermatter/overrides/sm_strings.dm b/mods/content/supermatter/overrides/sm_strings.dm
new file mode 100644
index 00000000000..2d7427f03d3
--- /dev/null
+++ b/mods/content/supermatter/overrides/sm_strings.dm
@@ -0,0 +1,19 @@
+/decl/game_mode/possible_ert_disabled_reasons()
+ var/static/sm_injected = FALSE
+ if(sm_injected)
+ return ..()
+ sm_injected = TRUE
+ . = ..()
+ . += "supermatter dust"
+
+/obj/item/disk/secret_project/get_secret_project_nouns()
+ var/static/sm_injected = FALSE
+ if(sm_injected)
+ return ..()
+ sm_injected = TRUE
+ . = ..()
+ . += "a supermatter engine"
+ return .
+
+/decl/material/solid/exotic_matter
+ lore_text = "Hypercrystalline supermatter is a subset of non-baryonic 'exotic' matter. It is found mostly in the heart of large stars, and features heavily in all kinds of fringe physics-defying technology."
\ No newline at end of file
diff --git a/mods/content/supermatter/overrides/sm_trader.dm b/mods/content/supermatter/overrides/sm_trader.dm
new file mode 100644
index 00000000000..ded45374bd9
--- /dev/null
+++ b/mods/content/supermatter/overrides/sm_trader.dm
@@ -0,0 +1,3 @@
+/datum/trader/ship/unique/rock/New()
+ ..()
+ possible_trading_items[/obj/machinery/power/supermatter] = TRADER_ALL
\ No newline at end of file
diff --git a/mods/content/supermatter/overrides/sm_unit_tests.dm b/mods/content/supermatter/overrides/sm_unit_tests.dm
new file mode 100644
index 00000000000..18351659e4c
--- /dev/null
+++ b/mods/content/supermatter/overrides/sm_unit_tests.dm
@@ -0,0 +1,3 @@
+/datum/unit_test/turf_floor_icons_shall_be_valid/New()
+ ..()
+ excepted_types |= /turf/unsimulated/wall/cascade
\ No newline at end of file
diff --git a/mods/content/supermatter/overrides/sm_xenoarchaeology.dm b/mods/content/supermatter/overrides/sm_xenoarchaeology.dm
new file mode 100644
index 00000000000..537de7a311c
--- /dev/null
+++ b/mods/content/supermatter/overrides/sm_xenoarchaeology.dm
@@ -0,0 +1,7 @@
+/datum/artifact_find/New()
+ var/static/supermatter_injected = FALSE
+ if(!supermatter_injected)
+ potential_finds[/obj/machinery/power/supermatter] = 5
+ potential_finds[/obj/machinery/power/supermatter/shard] = 25
+ supermatter_injected = TRUE
+ ..()
diff --git a/mods/content/supermatter/structures/sm_closets.dm b/mods/content/supermatter/structures/sm_closets.dm
new file mode 100644
index 00000000000..a1e58097f93
--- /dev/null
+++ b/mods/content/supermatter/structures/sm_closets.dm
@@ -0,0 +1,2 @@
+/obj/structure/closet/crate/secure/large/supermatter
+ closet_appearance = /decl/closet_appearance/large_crate/secure/hazard
\ No newline at end of file
diff --git a/mods/content/tabloids/_tabloids.dm b/mods/content/tabloids/_tabloids.dm
new file mode 100644
index 00000000000..7d6188ff28f
--- /dev/null
+++ b/mods/content/tabloids/_tabloids.dm
@@ -0,0 +1,58 @@
+/decl/modpack/tabloids
+ name = "Tabloids"
+ tabloid_publishers = list(
+ "\improper Solar Enquirer",
+ "\improper Stellar Examiner",
+ "\improper Antares Daily",
+ "\improper Weekly Galactic News",
+ "\improper Spiral"
+ )
+ tabloid_headlines = list(
+ "NARCOALGORITHMS: ARE YOUR CHILDREN SAFE?",
+ "ARE GMO HUMANS POISONOUS IN BED?",
+ "TOP 10 REASONS WHY OTHER SPECIES ARE A HOAX",
+ "CENTENNIAL POSITRONIC EXTENDS LIFESPAN WITH 1 SIMPLE TRICK",
+ "TOP 10 DANGEROUS FOODS WITH CHEMICALS",
+ "NEW TERRIFYING TEEN TREND: SUN-DIVING",
+ "HAS YOUR SPOUSE BEEN REPLACED BY AN ALIEN IMPOSTER? STUDIES SUGGEST YES!",
+ "SPACE CAUSES CANCER: DOCTORS CONFIRM",
+ "ARE BODY SCANNERS TOO INVASIVE? FIND OUT INSIDE!",
+ "HAS SCIENCE GONE TOO FAR? LOCAL SCIENTIST DEBUNKS ALIEN THEORY, DECRIES THEM AS TUBE EXPERIMENTS GONE WRONG",
+ "100 DELICIOUS RECIPES LETHAL TO CARBON-BASED LIFE",
+ "TOP FIVE SPECIES WE DROVE TO EXTINCTION; NUMBER TWO WILL SHOCK YOU",
+ "RELIGION WAS RIGHT? SHOCK FINDINGS SHOW ALIEN SIMILARITY TO ANIMALS, EXISTENCE OF BOATS",
+ "TOP TEN REASONS WHY ONLY HUMANS ARE SENTIENT",
+ "WHICH PLANET HAS THE BEST LOVERS? THIS AND MORE INSIDE!",
+ "SHE SAID WE SHOULD SEE OTHER PEOPLE, SO I MARRIED A NEO-AVIAN PACK: FULL STORY INSIDE",
+ "LOSE WEIGHT THREE TIMES FASTER WITH THESE LOW-G MANEUVERS!",
+ "MY DAUGHTER JOINED A NEURAL COLLECTIVE AND NOW SHE CAN TASTE SPACETIME: FULL STORY INSIDE",
+ "WERE THE NAZIS PSYCHIC? ONE HISTORIAN TELLS ALL",
+ "IS THE SOLAR GOVERNMENT CREATING AN AI SUPERINTELLIGENCE NEAR MERCURY? ONE EXPERT REVEALS SHOCKING INSIDER DETAILS!",
+ "TOP TEN HISTORICAL FIGURES THAT WERE TWO PROMETHEANS IN A TRENCHCOAT",
+ "TOP 10 SECRET AUGMENTS THE GOVERNMENT DOESN'T WANT YOU TO GET",
+ "ENLARGE YOUR MENTAL FACULTIES WITH THIS 1 WEIRD HAT",
+ "'HELP, MY SON THINKS HE'S A 20TH CENTURY VID CHARACTER CALLED SPOCK' AND MORE SHOCKING TALES INSIDE",
+ "18 RADICAL HIP IMPLANTS ALL THE KIDS ARE GETTING!",
+ "PRESERVED HEAD OF 21ST CENTURY CAPITALIST INSISTS THAT 'DYSON WALL' ONLY SANE SOLUTION TO RIMWARD MALCONTENTS",
+ "50 SHADES OF GREEN; BESTSELLING MULTISPECIES ROMANCE COMING TO CINEMAS",
+ "PLUTO: DWARF PLANET, OR SECRET RAMPANT AI FACILITY HELL-BENT ON CORRUPTING YOUR CHILDREN?",
+ "TOP TEN ANIME ALIENS. NUMBER 3 WILL SICKEN YOU",
+ "OCTUBER X'RALLBRE EXPOSED; NUDE PHOTOSHOOT LEAKS",
+ "WAR ON MARS AFTER NAKED MAN WAS FOUND; WERE THE ROMANS RIGHT?",
+ "REAL ALIENS ARGUE EARTH MOVIES RACIST!",
+ "HELP! I MARRIED A HEGEMONOUS SWARM INTELLIGENCE AND MY SON THINKS HE'S A ROUTER!",
+ "POSITRONICS: HUMAN INGENUITY AND GENEROSITY, OR A HORRIBLE MISTAKE? FIND OUT INSIDE!",
+ "THE FREE TRADER UNION: NEITHER FREE NOR A UNION. SHOCKING EXPOSE!",
+ "HAS THE FREE MARKET GONE TOO FAR? LUNA GLITTERPOP STAR AUCTIONS THIRD TESTICLE FOR TRANS-ORBITAL SHIPPING BONDS",
+ "THEY SAID IT WAS CANCER, BUT I KNEW IT WAS A TINY, SELF-REPLICATING CLONE OF RAY KURZWEIL: FULL STORY INSIDE",
+ "WHAT HAS TECHNOLOGY DONE? INDUSTRY BILLIONAIRE MARRIES OWN INFORMORPH MIND-COPY",
+ "REPTILLIAN ICE WARRIORS FROM ANOTHER WORLD LIVE INSIDE YOUR AIR DUCTS: HERE'S HOW TO GET RID OF THEM",
+ "10 CRITICAL THINGS YOU NEED TO KNOW ABOUT 'DRONEGATE'",
+ "THEY CALL THEM JUMPGATES BUT I'VE NEVER SEEN THEM JUMP: AN INDUSTRY INSIDER SPEAKS FOR THE FIRST TIME",
+ "EMERGENT INTELLIGENCES ARE STEALING YOUR BANK DETAILS, FETISHES: FOIL HAT RECIPE INSIDE",
+ "TIME TRAVELLERS ARE STEALING YOUR WIFI: 5 TIPS FOR DEFEATING HACKERS FROM THE FUTURE",
+ "'My mother was an alien spy': THIS CELEBRITY REVEAL WILL SHOCK AND AMAZE YOU",
+ "LUMINARY SCIENTIST SPEAKS: DIABETES IS A HYPERCORP RETROVIRUS!",
+ "'I REROUTED MY NEURAL CIRCUITRY SO THAT PAIN TASTES OF STRAWBERRIES' AND FIFTEEN OTHER CRAZY ALMACH STORIES",
+ "JOINING THE NAVY? HERE'S 15 EXPERT TIPS FOR AVOIDING BRAIN PARASITES"
+ )
\ No newline at end of file
diff --git a/mods/content/tabloids/_tabloids.dme b/mods/content/tabloids/_tabloids.dme
new file mode 100644
index 00000000000..0c6e6e35b01
--- /dev/null
+++ b/mods/content/tabloids/_tabloids.dme
@@ -0,0 +1,8 @@
+#ifndef CONTENT_PACK_TABLOIDS
+#define CONTENT_PACK_TABLOIDS
+// BEGIN_INCLUDE
+#include "_tabloids.dm"
+#include "tabloid.dm"
+#include "tabloid_helpers.dm"
+// END_INCLUDE
+#endif
\ No newline at end of file
diff --git a/mods/content/tabloids/icons/magazine.dmi b/mods/content/tabloids/icons/magazine.dmi
new file mode 100644
index 00000000000..62b385510c8
Binary files /dev/null and b/mods/content/tabloids/icons/magazine.dmi differ
diff --git a/mods/content/tabloids/tabloid.dm b/mods/content/tabloids/tabloid.dm
new file mode 100644
index 00000000000..6fc781a7ee6
--- /dev/null
+++ b/mods/content/tabloids/tabloid.dm
@@ -0,0 +1,36 @@
+/obj/item/tabloid
+ name = "tabloid magazine"
+ desc = "It's one of those trashy tabloid magazines. It looks pretty out of date."
+ icon = 'mods/content/tabloids/icons/magazine.dmi'
+ icon_state = "magazine"
+ randpixel = 6
+ material = /decl/material/solid/organic/paper
+ matter = list(/decl/material/solid/organic/plastic = MATTER_AMOUNT_REINFORCEMENT)
+ var/headline
+ var/article_body
+
+/obj/item/tabloid/Initialize()
+ . = ..()
+ var/list/tabloid_headlines = get_tabloid_headlines()
+ name = SAFEPICK(get_tabloid_publishers()) || initial(name)
+ icon_state = SAFEPICK(get_tabloid_states()) || initial(icon_state)
+ headline = SAFEPICK(tabloid_headlines)
+ if(length(tabloid_headlines) && tabloid_headlines[headline])
+ article_body = tabloid_headlines[headline]
+
+/obj/item/tabloid/examine(mob/user, distance, infix, suffix)
+ . = ..()
+ if(headline)
+ to_chat(user, "The headline screams, \"[headline]\"")
+
+/obj/item/tabloid/attack_self(mob/user)
+ . = ..()
+ if(!.)
+ user.visible_message(SPAN_NOTICE("\The [user] leafs idly through \the [src]."))
+ if(headline)
+ to_chat(user, "Most of it is the usual tabloid garbage, but the headline story, \"[headline]\", holds your attention for awhile.")
+ if(article_body)
+ to_chat(user, article_body)
+ else
+ to_chat(user, "It's the usual tabloid garbage. You find nothing of interest.")
+ return TRUE
diff --git a/mods/content/tabloids/tabloid_helpers.dm b/mods/content/tabloids/tabloid_helpers.dm
new file mode 100644
index 00000000000..966556dafbe
--- /dev/null
+++ b/mods/content/tabloids/tabloid_helpers.dm
@@ -0,0 +1,24 @@
+// Minor fluff item for mapping in waiting rooms etc.
+/proc/get_tabloid_publishers()
+ var/static/list/tabloid_publishers
+ if(!tabloid_publishers)
+ tabloid_publishers = list()
+ for(var/modpack_name in SSmodpacks.loaded_modpacks)
+ var/decl/modpack/modpack = SSmodpacks.loaded_modpacks[modpack_name]
+ if(length(modpack.tabloid_publishers))
+ tabloid_publishers |= modpack.tabloid_publishers
+ return tabloid_publishers
+
+/proc/get_tabloid_headlines()
+ var/static/list/tabloid_headlines
+ if(!tabloid_headlines)
+ tabloid_headlines = list()
+ for(var/modpack_name in SSmodpacks.loaded_modpacks)
+ var/decl/modpack/modpack = SSmodpacks.loaded_modpacks[modpack_name]
+ if(length(modpack.tabloid_headlines))
+ tabloid_headlines |= modpack.tabloid_headlines
+ return tabloid_headlines
+
+/proc/get_tabloid_states()
+ var/static/list/tabloid_states = icon_states('mods/content/tabloids/icons/magazine.dmi')
+ return tabloid_states
diff --git a/mods/content/xenobiology/_xenobiology.dme b/mods/content/xenobiology/_xenobiology.dme
index 11a5f3972c6..1591ea3f458 100644
--- a/mods/content/xenobiology/_xenobiology.dme
+++ b/mods/content/xenobiology/_xenobiology.dme
@@ -50,7 +50,6 @@
#include "slime\slime_commands.dm"
#include "slime\slime_comments.dm"
#include "slime\slime_follow.dm"
-#include "slime\slime_hud.dm"
#include "slime\slime_reagents.dm"
#include "slime\slime_surgery.dm"
#include "slime\slime_update_icon.dm"
diff --git a/mods/content/xenobiology/slime/_slime.dm b/mods/content/xenobiology/slime/_slime.dm
index a5b342022c2..60c12cb89e3 100644
--- a/mods/content/xenobiology/slime/_slime.dm
+++ b/mods/content/xenobiology/slime/_slime.dm
@@ -18,7 +18,7 @@
status_flags = CANPARALYSE|CANPUSH
butchery_data = null
ai = /datum/mob_controller/slime
- hud_used = /datum/hud/slime
+ hud_used = /datum/hud/animal
nutrition = 800
var/is_adult = FALSE
@@ -33,7 +33,6 @@
var/slime_type = /decl/slime_colour/grey
var/cores = 1 // the number of /obj/item/slime_extract's the slime has left inside
var/core_removal_stage = 0 //For removing cores.
- var/datum/reagents/metabolism/ingested
/mob/living/slime/Destroy()
set_feeding_on()
@@ -65,8 +64,7 @@
. = ..(mapload)
- ingested = new /datum/reagents/metabolism(240, src, CHEM_TOUCH)
- reagents = ingested
+ reagents = new /datum/reagents/metabolism(240, src, CHEM_TOUCH)
render_target = "slime_\ref[src]"
verbs += /mob/living/proc/ventcrawl
@@ -272,7 +270,7 @@
return ..()
/mob/living/slime/attackby(var/obj/item/W, var/mob/user)
- var/force = W.get_attack_force(user)
+ var/force = W.expend_attack_force(user)
if(force > 0)
var/datum/mob_controller/slime/slime_ai = ai
if(istype(slime_ai))
diff --git a/mods/content/xenobiology/slime/life.dm b/mods/content/xenobiology/slime/life.dm
index 55b0e665ec1..d71a1d3edd4 100644
--- a/mods/content/xenobiology/slime/life.dm
+++ b/mods/content/xenobiology/slime/life.dm
@@ -46,6 +46,7 @@
. = ..()
if(feeding_on)
slime_feed()
+ var/datum/reagents/metabolism/ingested = reagents
ingested.metabolize()
/mob/living/slime/fluid_act(datum/reagents/fluids)
@@ -86,6 +87,7 @@
. = ..()
if(feeding_on)
slime_feed()
+ var/datum/reagents/metabolism/ingested = reagents
ingested.metabolize()
// Digest whatever we've got floating around in our goop.
diff --git a/mods/content/xenobiology/slime/slime_AI.dm b/mods/content/xenobiology/slime/slime_AI.dm
index 7260e124070..bf28ef6cd6b 100644
--- a/mods/content/xenobiology/slime/slime_AI.dm
+++ b/mods/content/xenobiology/slime/slime_AI.dm
@@ -2,8 +2,8 @@
expected_type = /mob/living/slime
var/mood
var/chase_target = 0
- var/mob/living/leader
- var/mob/living/current_target // Currently attacking this mob (separate from feeding)
+ var/weakref/leader
+ var/weakref/current_target // Currently attacking this mob (separate from feeding)
var/attacked = 0 // Determines if it's been attacked recently. Can be any number, is a cooloff-ish variable
var/rabid = 0 // If set to 1, the slime will attack and eat anything it comes in contact with
var/list/observed_friends // A list of refs to friends; they are not considered targets for feeding; passed down after splitting.
@@ -20,6 +20,7 @@
/datum/mob_controller/slime/Destroy()
observed_friends = null
friendship_cooldown = null
+ leader = null
current_target = null
speech_buffer = null
slime = null
@@ -44,7 +45,7 @@
else if(rabid || attacked)
new_mood = "angry"
body.set_intent(I_FLAG_HARM)
- else if(current_target)
+ else if(current_target?.resolve())
new_mood = "mischevous"
if(!new_mood)
@@ -97,22 +98,27 @@
current_target = null
return
- if(current_target)
+ var/mob/actual_target = current_target?.resolve()
+ if(actual_target)
chase_target--
if(chase_target <= 0 || attacked || rabid) // Tired of chasing or attacking everything nearby
chase_target = 0
current_target = null
+ else
+ current_target = null
var/hunger = slime.get_hunger_state()
- if(!current_target)
+ var/mob/leader_mob = leader?.resolve()
+ actual_target = current_target?.resolve()
+ if(!actual_target)
var/feral = (attacked || rabid || hunger >= 2)
- if(feral || (!leader && !holding_still) || (hunger && prob(10)))
+ if(feral || (!leader_mob && !holding_still) || (hunger && prob(10)))
var/list/targets
for(var/mob/living/prey in view(7, body))
if(assess_target(prey))
LAZYADD(targets, prey)
if(length(targets))
- current_target = get_best_target(targets)
+ current_target = weakref(get_best_target(targets))
chase_target = rand(5,7)
if(slime.is_adult)
chase_target += 3
@@ -120,8 +126,8 @@
if(holding_still)
holding_still = max(holding_still - 1 - hunger, 0)
else if(isturf(body?.loc))
- if(leader)
- step_to(body, get_dir(body, leader))
+ if(leader_mob)
+ step_to(body, get_dir(body, leader_mob))
else if(prob(hunger ? 50 : 33))
body.SelfMove(pick(global.cardinal))
@@ -131,42 +137,42 @@
return
var/added_delay = 0
- if(slime.amount_grown >= SLIME_EVOLUTION_THRESHOLD && !current_target)
+ var/mob/actual_target = current_target?.resolve()
+ if(slime.amount_grown >= SLIME_EVOLUTION_THRESHOLD && !actual_target)
if(slime.is_adult)
slime.slime_split()
else
slime.slime_mature()
added_delay = 10
else
-
- if(!assess_target(current_target) || current_target == slime.feeding_on || !(current_target in view(7, body)))
+ if(!assess_target(actual_target) || actual_target == slime.feeding_on || !(actual_target in view(7, body)))
current_target = null
- if(!current_target)
+ if(!actual_target)
if(prob(1))
for(var/mob/living/slime/frenemy in range(1, body))
if(frenemy != body && body.Adjacent(frenemy))
body.set_intent((frenemy.slime_type == slime.slime_type) ? I_FLAG_HELP : I_FLAG_HARM)
body.UnarmedAttack(frenemy, TRUE)
added_delay = 10
- else if(slime.Adjacent(current_target))
+ else if(slime.Adjacent(actual_target))
var/do_attack = FALSE
- if(issilicon(current_target))
+ if(issilicon(actual_target))
body.set_intent(I_FLAG_HARM)
do_attack = TRUE
- else if(current_target.client && !current_target.current_posture.prone && prob(60 + slime.powerlevel * 4))
+ else if(actual_target.client && !actual_target.current_posture.prone && prob(60 + slime.powerlevel * 4))
body.set_intent(I_FLAG_DISARM)
do_attack = TRUE
- else if(slime.check_valid_feed_target(current_target) == FEED_RESULT_VALID)
+ else if(slime.check_valid_feed_target(actual_target) == FEED_RESULT_VALID)
body.set_intent(I_FLAG_GRAB)
do_attack = TRUE
if(do_attack)
- body.UnarmedAttack(current_target, TRUE)
+ body.UnarmedAttack(actual_target, TRUE)
added_delay = 10
else
current_target = null
else
- step_to(body, current_target)
+ step_to(body, actual_target)
next_core_logic_run = world.time + max(body?.get_movement_delay(), 5) + added_delay
@@ -208,13 +214,13 @@
/datum/mob_controller/slime/proc/adjust_friendship(var/atom/user, var/amount)
if(ismob(user))
- if(QDELETED(user))
+ if(QDELING(user))
return FALSE
user = weakref(user)
else if(istype(user, /weakref)) // verify the ref is still valid
var/weakref/user_ref = user
- user = user_ref.resolve()
- if(!ismob(user) || QDELETED(user))
+ var/mob/resolved_user = user_ref.resolve()
+ if(!ismob(resolved_user) || QDELING(resolved_user))
return FALSE
else
return FALSE
diff --git a/mods/content/xenobiology/slime/slime_commands.dm b/mods/content/xenobiology/slime/slime_commands.dm
index 4290f05accf..3be381f2a01 100644
--- a/mods/content/xenobiology/slime/slime_commands.dm
+++ b/mods/content/xenobiology/slime/slime_commands.dm
@@ -20,15 +20,16 @@
triggers = list("follow")
/decl/slime_command/follow/get_response(var/speaker, var/spoken, var/datum/mob_controller/slime/holder)
- if(holder.leader)
- if(holder.leader == speaker)
+ var/mob/leader_mob = holder.leader?.resolve()
+ if(leader_mob)
+ if(leader_mob == speaker)
return pick("Yes...", "Lead...", "Following...")
- if(LAZYACCESS(holder.observed_friends, weakref(speaker)) > LAZYACCESS(holder.observed_friends, weakref(holder.leader)))
- holder.leader = speaker
+ if(LAZYACCESS(holder.observed_friends, weakref(speaker)) > LAZYACCESS(holder.observed_friends, holder.leader))
+ holder.leader = weakref(speaker)
return "Yes... I follow [speaker]..."
- return "No... I follow [holder.leader]..."
+ return "No... I follow [leader_mob]..."
if(LAZYACCESS(holder.observed_friends, weakref(speaker)) > 2)
- holder.leader = speaker
+ holder.leader = weakref(speaker)
return "I follow..."
return pick("No...", "I won't follow...")
@@ -45,18 +46,20 @@
holder.adjust_friendship(speaker, -1)
return "Grrr..."
return "Fine..."
- if(holder.current_target)
+ var/mob/actual_target = holder.current_target?.resolve()
+ if(actual_target)
if(friendship > 3)
holder.current_target = null
if(friendship < 6)
holder.adjust_friendship(speaker, -1)
return "Grrr..."
return "Fine..."
- if(holder.leader)
- if(holder.leader == speaker)
+ var/mob/leader_mob = holder.leader?.resolve()
+ if(leader_mob)
+ if(leader_mob == speaker)
holder.leader = null
return "Yes... I'll stop..."
- if(friendship > LAZYACCESS(holder.observed_friends, weakref(holder.leader)))
+ if(friendship > LAZYACCESS(holder.observed_friends, holder.leader))
holder.leader = null
return "Yes... I'll stop..."
return "No... I'll keep following..."
@@ -66,11 +69,12 @@
/decl/slime_command/stay/get_response(var/speaker, var/spoken, var/datum/mob_controller/slime/holder)
var/friendship = LAZYACCESS(holder.observed_friends, weakref(speaker))
- if(holder.leader)
- if(holder.leader == speaker)
+ var/mob/leader_mob = holder.leader?.resolve()
+ if(leader_mob)
+ if(leader_mob == speaker)
holder.holding_still = friendship * 10
return "Yes... Staying..."
- var/leader_friendship = LAZYACCESS(holder.observed_friends, weakref(holder.leader))
+ var/leader_friendship = LAZYACCESS(holder.observed_friends, holder.leader)
if(friendship > leader_friendship)
holder.holding_still = (friendship - leader_friendship) * 10
return "Yes... Staying..."
diff --git a/mods/content/xenobiology/slime/slime_comments.dm b/mods/content/xenobiology/slime/slime_comments.dm
index bd8ad9f1146..f009e313123 100644
--- a/mods/content/xenobiology/slime/slime_comments.dm
+++ b/mods/content/xenobiology/slime/slime_comments.dm
@@ -29,8 +29,9 @@
if(holder.slime.nutrition < holder.slime.get_starve_nutrition())
. += list("So... hungry...", "Very... hungry...", "Need... food...", "Must... eat...")
tension += 10
- if(holder.current_target)
- . += "\The [holder.current_target]... looks tasty..."
+ var/mob/actual_target = holder.current_target?.resolve()
+ if(actual_target)
+ . += "\The [actual_target]... looks tasty..."
if(length(.) && prob(tension))
return pick(.)
diff --git a/mods/content/xenobiology/slime/slime_hud.dm b/mods/content/xenobiology/slime/slime_hud.dm
deleted file mode 100644
index 2cdd315d671..00000000000
--- a/mods/content/xenobiology/slime/slime_hud.dm
+++ /dev/null
@@ -1,4 +0,0 @@
-/datum/hud/slime/FinalizeInstantiation()
- action_intent = new(null, mymob)
- adding = list(action_intent)
- ..()
diff --git a/mods/content/xenobiology/slime/slime_reagents.dm b/mods/content/xenobiology/slime/slime_reagents.dm
index bff84fd00ee..882797de759 100644
--- a/mods/content/xenobiology/slime/slime_reagents.dm
+++ b/mods/content/xenobiology/slime/slime_reagents.dm
@@ -14,22 +14,23 @@
metabolism = REM * 0.25
exoplanet_rarity_gas = MAT_RARITY_EXOTIC
-/decl/material/liquid/water/affect_touch(var/mob/living/M, var/removed, var/datum/reagents/holder)
+/decl/material/liquid/water/affect_touch(var/mob/living/victim, var/removed, var/datum/reagents/holder)
. = ..()
- if(isslime(M))
- M.take_damage(10 * removed, TOX)
- var/mob/living/slime/S = M
- if(istype(S) && istype(S.ai, /datum/mob_controller/slime))
- var/datum/mob_controller/slime/slime_ai = S.ai
- if(slime_ai.current_target)
+ if(isslime(victim))
+ victim.take_damage(10 * removed, TOX)
+ var/mob/living/slime/slime_victim = victim
+ if(istype(slime_victim) && istype(slime_victim.ai, /datum/mob_controller/slime))
+ var/datum/mob_controller/slime/slime_ai = slime_victim.ai
+ if(slime_ai.current_target) // don't bother resolving it, we're just clearing it
slime_ai.current_target = null
- S.set_feeding_on()
- if(LAZYACCESS(M.chem_doses, type) == removed)
- M.visible_message( \
- SPAN_DANGER("\The [S]'s flesh sizzles where \the [name] touches it!"), \
- SPAN_DANGER("Your flesh is burned by \the [name]!"))
- SET_STATUS_MAX(M, STAT_CONFUSE, 2)
- var/datum/mob_controller/slime/slime_ai = M.ai
+ slime_victim.set_feeding_on()
+ if(LAZYACCESS(victim.chem_doses, type) == removed)
+ var/reagent_name = get_reagent_name(holder) // mostly to check masked name, but handles phase too
+ victim.visible_message( \
+ SPAN_DANGER("\The [slime_victim]'s flesh sizzles where \the [reagent_name] touches it!"), \
+ SPAN_DANGER("Your flesh is burned by \the [reagent_name]!"))
+ SET_STATUS_MAX(victim, STAT_CONFUSE, 2)
+ var/datum/mob_controller/slime/slime_ai = victim.ai
if(istype(slime_ai))
slime_ai.attacked = max(slime_ai.attacked, rand(7,10)) // angery
diff --git a/mods/gamemodes/cult/_cult.dme b/mods/gamemodes/cult/_cult.dme
index 82d4e19aed5..02138255d74 100644
--- a/mods/gamemodes/cult/_cult.dme
+++ b/mods/gamemodes/cult/_cult.dme
@@ -21,7 +21,11 @@
#include "special_role.dm"
#include "structures.dm"
#include "talisman.dm"
-#include "cultify\de-cultify.dm"
+#include "abilities\_handler.dm"
+#include "abilities\construct.dm"
+#include "abilities\harvest.dm"
+#include "abilities\shade.dm"
+#include "cultify\de-cultify.dm"
#include "cultify\defile.dm"
#include "cultify\mob.dm"
#include "cultify\turf.dm"
@@ -29,7 +33,12 @@
#include "mobs\shade.dm"
#include "mobs\constructs\constructs.dm"
#include "mobs\constructs\soulstone.dm"
-#include "spells\construct.dm"
-#include "spells\harvest.dm"
// END_INCLUDE
-#endif
\ No newline at end of file
+#endif
+// BEGIN_INTERNALS
+// END_INTERNALS
+// BEGIN_FILE_DIR
+#define FILE_DIR .
+// END_FILE_DIR
+// BEGIN_PREFERENCES
+// END_PREFERENCES
diff --git a/mods/gamemodes/cult/abilities/_handler.dm b/mods/gamemodes/cult/abilities/_handler.dm
new file mode 100644
index 00000000000..f346bb73fb4
--- /dev/null
+++ b/mods/gamemodes/cult/abilities/_handler.dm
@@ -0,0 +1,21 @@
+/obj/screen/ability/category/cult
+ name = "Toggle Construct Abilities"
+ icon = 'mods/gamemodes/cult/icons/abilities.dmi'
+
+/obj/screen/ability/button/cult
+ icon = 'mods/gamemodes/cult/icons/abilities.dmi'
+
+/datum/ability_handler/cult
+ category_toggle_type = /obj/screen/ability/category/cult
+
+/decl/ability/cult
+ abstract_type = /decl/ability/cult
+ ability_icon = 'mods/gamemodes/cult/icons/abilities.dmi'
+ ability_icon_state = "artificer"
+ associated_handler_type = /datum/ability_handler/cult
+ ui_element_type = /obj/screen/ability/button/cult
+ ability_cooldown_time = 60 SECONDS
+
+/obj/item/ability/cult
+ icon = 'mods/gamemodes/cult/icons/ability_item.dmi'
+ color = COLOR_RED
diff --git a/mods/gamemodes/cult/abilities/construct.dm b/mods/gamemodes/cult/abilities/construct.dm
new file mode 100644
index 00000000000..60138eaba35
--- /dev/null
+++ b/mods/gamemodes/cult/abilities/construct.dm
@@ -0,0 +1,131 @@
+//////////////////////////////Construct Spells/////////////////////////
+/decl/ability/cult/construct
+ name = "Artificer"
+ desc = "This spell conjures a construct which may be controlled by shades."
+ target_selector = /decl/ability_targeting/clear_turf
+ overlay_icon = 'mods/gamemodes/cult/icons/effects.dmi'
+ overlay_icon_state = "sparkles"
+ target_selector = /decl/ability_targeting/clear_turf/construct
+ var/summon_type = /obj/structure/constructshell
+
+/decl/ability_targeting/clear_turf/construct/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability)
+ var/decl/ability/cult/construct/cult_ability = ability
+ if(!istype(cult_ability))
+ return FALSE
+ return ..() && !istype(target, cult_ability.summon_type) && !(locate(cult_ability.summon_type) in target)
+
+/decl/ability/cult/construct/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile)
+ . = ..()
+ var/turf/target_turf = get_turf(hit_target)
+ if(istype(target_turf))
+ if(ispath(summon_type, /turf))
+ target_turf = target_turf.ChangeTurf(summon_type, TRUE, FALSE, TRUE, TRUE, FALSE)
+ if(target_turf) // We reapply effects as target no longer exists.
+ apply_effect_to(user, target_turf, metadata)
+ else if(ispath(summon_type, /atom))
+ new summon_type(target_turf)
+
+/decl/ability/cult/construct/lesser
+ ability_cooldown_time = 2 MINUTES
+ summon_type = /obj/structure/constructshell/cult
+ ability_icon_state = "const_shell"
+
+/decl/ability/cult/construct/floor
+ name = "Floor Construction"
+ desc = "This spell constructs a cult floor"
+ ability_cooldown_time = 2 SECONDS
+ summon_type = /turf/floor/cult
+ ability_icon_state = "const_floor"
+ overlay_icon_state = "cultfloor"
+
+/decl/ability/cult/construct/wall
+ name = "Lesser Construction"
+ desc = "This spell constructs a cult wall"
+ ability_cooldown_time = 10 SECONDS
+ summon_type = /turf/wall/cult
+ ability_icon_state = "const_wall"
+ overlay_icon_state = "cultwall"
+
+/decl/ability/cult/construct/wall/reinforced
+ name = "Greater Construction"
+ desc = "This spell constructs a reinforced metal wall"
+ ability_cooldown_time = 30 SECONDS
+ summon_type = /turf/wall/r_wall
+
+/decl/ability/cult/construct/soulstone
+ name = "Summon Soulstone"
+ desc = "This spell reaches into Nar-Sie's realm, summoning one of the legendary fragments across time and space."
+ ability_cooldown_time = 5 MINUTES
+ summon_type = /obj/item/soulstone
+ ability_icon_state = "const_stone"
+
+/decl/ability/cult/construct/pylon
+ name = "Red Pylon"
+ desc = "This spell conjures a fragile crystal from Nar-Sie's realm. Makes for a convenient light source."
+ ability_cooldown_time = 20 SECONDS
+ summon_type = /obj/structure/cult/pylon
+ ability_icon_state = "const_pylon"
+ target_selector = /decl/ability_targeting/pylon
+ is_melee_invocation = TRUE
+ prep_cast = TRUE
+
+/decl/ability_targeting/pylon/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability)
+ . = ..()
+ if(!.)
+ return
+ if(istype(target, /obj/structure/cult/pylon))
+ return TRUE
+ if(isturf(target))
+ var/turf/target_turf = target
+ // We can repair pylons, so let us target turfs containing broken pylons.
+ if(target_turf.contains_dense_objects(user))
+ for(var/obj/structure/cult/pylon/pylon in target_turf)
+ if(pylon.isbroken)
+ return TRUE
+ return FALSE
+ // We can summon pylons in empty turfs.
+ return TRUE
+ return FALSE
+
+/decl/ability/cult/construct/pylon/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile)
+ for(var/obj/structure/cult/pylon/P in get_turf(hit_target))
+ if(P.isbroken)
+ P.repair(user)
+ return TRUE
+ . = ..()
+
+/decl/ability/cult/construct/forcewall/lesser
+ name = "Force Shield"
+ desc = "Allows you to pull up a shield to protect yourself and allies from incoming threats"
+ summon_type = /obj/effect/cult_force_wall
+ ability_cooldown_time = 30 SECONDS
+ ability_use_channel = 20 SECONDS
+ ability_icon_state = "const_juggwall"
+ prepare_message_3p_str = "$USER$ begins to twist and warp space around $TARGET$, building a wall of force."
+ prepare_message_1p_str = "You begin the lengthy process of warping local space to form a wall of force."
+ cast_message_3p_str = "$USER$ completes a wall of force!"
+ cast_message_1p_str = "You complete a wall of force!"
+ fail_cast_1p_str = "The screaming fabric of spacetime escapes your grip, and the wall of force vanishes."
+
+//Code for the Juggernaut construct's forcefield, that seemed like a good place to put it.
+/obj/effect/cult_force_wall
+ desc = "This eerie-looking obstacle seems to have been pulled from another dimension through sheer force."
+ name = "wall of force"
+ icon = 'mods/gamemodes/cult/icons/effects.dmi'
+ icon_state = "m_shield_cult"
+ light_color = "#b40000"
+ light_range = 2
+ anchored = TRUE
+ opacity = FALSE
+ density = TRUE
+
+/obj/effect/cult_force_wall/Initialize(mapload)
+ . = ..()
+ addtimer(CALLBACK(src, PROC_REF(vanish)), 30 SECONDS)
+
+/obj/effect/cult_force_wall/proc/vanish()
+ density = FALSE
+ icon_state = "m_shield_cult_vanish"
+ sleep(12)
+ if(!QDELETED(src))
+ qdel(src)
diff --git a/mods/gamemodes/cult/abilities/harvest.dm b/mods/gamemodes/cult/abilities/harvest.dm
new file mode 100644
index 00000000000..49569d6a25e
--- /dev/null
+++ b/mods/gamemodes/cult/abilities/harvest.dm
@@ -0,0 +1,41 @@
+/decl/ability/cult/construct/harvest
+ name = "Harvest"
+ desc = "Back to where I come from, and you're coming with me."
+ ability_cooldown_time = 20 SECONDS
+ ability_use_channel = 10 SECONDS
+ overlay_icon_state = "rune_teleport"
+ overlay_lifespan = 0
+ ability_icon_state = "const_harvest"
+ prepare_message_3p_str = "Space around $USER$ begins to bubble and decay as a terrible vista begins to intrude..."
+ prepare_message_1p_str = "You bore through space and time, seeking the essence of the Geometer of Blood."
+ fail_cast_1p_str = "Reality reasserts itself, preventing your return to Nar-Sie."
+ target_selector = /decl/ability_targeting/living_mob
+
+/decl/ability/cult/construct/harvest/can_use_ability(mob/user, list/metadata, silent)
+ . = ..()
+ if(.)
+ var/destination
+ for(var/obj/effect/narsie/N in global.narsie_list)
+ destination = N.loc
+ break
+ if(!destination)
+ to_chat(user, SPAN_DANGER("You cannot sense the Geometer of Blood!"))
+ return FALSE
+
+/decl/ability/cult/construct/harvest/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile)
+ ..()
+ var/destination = null
+ for(var/obj/effect/narsie/N in global.narsie_list)
+ destination = N.loc
+ break
+ if(!destination)
+ to_chat(user, SPAN_DANGER("You cannot sense the Geometer of Blood!"))
+ return
+ if(ismob(hit_target) && hit_target != user)
+ var/mob/living/victim = hit_target
+ to_chat(user, SPAN_SINISTER("You warp back to Nar-Sie along with your prey."))
+ to_chat(victim, SPAN_SINISTER("You are wrenched through time and space and thrown into chaos!"))
+ victim.dropInto(destination)
+ else
+ to_chat(user, SPAN_SINISTER("You warp back to Nar-Sie."))
+ user.dropInto(destination)
diff --git a/mods/gamemodes/cult/abilities/shade.dm b/mods/gamemodes/cult/abilities/shade.dm
new file mode 100644
index 00000000000..5fab626d14d
--- /dev/null
+++ b/mods/gamemodes/cult/abilities/shade.dm
@@ -0,0 +1 @@
+/decl/ability/cult/construct/shift
\ No newline at end of file
diff --git a/mods/gamemodes/cult/flooring.dm b/mods/gamemodes/cult/flooring.dm
index a92973b1077..71aff2a3ff3 100644
--- a/mods/gamemodes/cult/flooring.dm
+++ b/mods/gamemodes/cult/flooring.dm
@@ -7,6 +7,6 @@
turf_flags = TURF_ACID_IMMUNE | TURF_REMOVE_WRENCH
can_paint = null
-/decl/flooring/reinforced/cult/on_remove()
+/decl/flooring/reinforced/cult/on_flooring_remove(turf/removing_from)
var/decl/special_role/cultist/cult = GET_DECL(/decl/special_role/cultist)
cult.remove_cultiness(CULTINESS_PER_TURF)
diff --git a/mods/gamemodes/cult/hell_universe.dm b/mods/gamemodes/cult/hell_universe.dm
index c5e5ad0adf0..5133b72ba09 100644
--- a/mods/gamemodes/cult/hell_universe.dm
+++ b/mods/gamemodes/cult/hell_universe.dm
@@ -40,9 +40,3 @@ In short:
for(var/mob/living/simple_animal/M in SSmobs.mob_list)
if(M && !M.client)
M.set_stat(DEAD)
-
-// Disable Narsie when we enter other (non-hell) universe states
-/datum/universal_state/supermatter_cascade/OnEnter()
- // Disable Nar-Sie.
- var/decl/special_role/cultist/cult = GET_DECL(/decl/special_role/cultist)
- cult.allow_narsie = 0
\ No newline at end of file
diff --git a/mods/gamemodes/cult/icons/abilities.dmi b/mods/gamemodes/cult/icons/abilities.dmi
new file mode 100644
index 00000000000..f1d5d8bc121
Binary files /dev/null and b/mods/gamemodes/cult/icons/abilities.dmi differ
diff --git a/mods/gamemodes/cult/icons/ability_item.dmi b/mods/gamemodes/cult/icons/ability_item.dmi
new file mode 100644
index 00000000000..e22793f4f6b
Binary files /dev/null and b/mods/gamemodes/cult/icons/ability_item.dmi differ
diff --git a/mods/gamemodes/cult/icons/effects.dmi b/mods/gamemodes/cult/icons/effects.dmi
new file mode 100644
index 00000000000..9e238941454
Binary files /dev/null and b/mods/gamemodes/cult/icons/effects.dmi differ
diff --git a/mods/gamemodes/cult/icons/forcewall.dmi b/mods/gamemodes/cult/icons/forcewall.dmi
new file mode 100644
index 00000000000..04b8560cdac
Binary files /dev/null and b/mods/gamemodes/cult/icons/forcewall.dmi differ
diff --git a/icons/effects/uristrunes.dmi b/mods/gamemodes/cult/icons/runes.dmi
similarity index 100%
rename from icons/effects/uristrunes.dmi
rename to mods/gamemodes/cult/icons/runes.dmi
diff --git a/mods/gamemodes/cult/items.dm b/mods/gamemodes/cult/items.dm
index 2b2e826617c..e4faf111e49 100644
--- a/mods/gamemodes/cult/items.dm
+++ b/mods/gamemodes/cult/items.dm
@@ -26,7 +26,7 @@
to_chat(user, SPAN_DANGER("An unexplicable force rips through you, tearing the sword from your grasp!"))
//random amount of damage between half of the blade's force and the full force of the blade.
- var/force = get_attack_force(user)
+ var/force = expend_attack_force(user)
user.apply_damage(rand(force/2, force), BRUTE, zone, (DAM_SHARP|DAM_EDGE), armor_pen = 100)
SET_STATUS_MAX(user, STAT_WEAK, 5)
diff --git a/mods/gamemodes/cult/mobs/constructs/constructs.dm b/mods/gamemodes/cult/mobs/constructs/constructs.dm
index 1f10369a694..1eb37f6980b 100644
--- a/mods/gamemodes/cult/mobs/constructs/constructs.dm
+++ b/mods/gamemodes/cult/mobs/constructs/constructs.dm
@@ -5,7 +5,6 @@
speak_emote = list("hisses")
base_animal_type = /mob/living/simple_animal/construct
base_movement_delay = -1
-
response_help_1p = "You think better of touching $TARGET$."
response_help_3p = "$USER$ thinks better of touching $TARGET$."
response_disarm = "flails at"
@@ -31,7 +30,7 @@
z_flags = ZMM_MANGLE_PLANES
glowing_eyes = TRUE
ai = /datum/mob_controller/aggressive/construct
- var/list/construct_spells = list()
+ var/list/construct_spells
/datum/mob_controller/aggressive/construct
emote_speech = list("Hsssssssszsht.", "Hsssssssss...", "Tcshsssssssszht!")
@@ -54,7 +53,7 @@
add_language(/decl/language/cultcommon)
add_language(/decl/language/cult)
for(var/spell in construct_spells)
- src.add_spell(new spell, "const_spell_ready")
+ add_ability(spell)
set_light(1.5, -2, COLOR_WHITE)
update_icon()
@@ -107,7 +106,9 @@
environment_smash = 2
status_flags = 0
resistance = 10
- construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser)
+ construct_spells = list(
+ /decl/ability/cult/construct/forcewall/lesser
+ )
hud_used = /datum/hud/construct/juggernaut
base_movement_delay = 2
ai = /datum/mob_controller/aggressive/construct_armoured
@@ -163,7 +164,9 @@
natural_weapon = /obj/item/natural_weapon/wraith
environment_smash = 1
see_in_dark = 7
- construct_spells = list(/spell/targeted/ethereal_jaunt/shift)
+ construct_spells = list(
+ /decl/ability/cult/construct/shift
+ )
hud_used = /datum/hud/construct/wraith
/obj/item/natural_weapon/wraith
@@ -194,11 +197,11 @@
natural_weapon = /obj/item/natural_weapon/cult_builder
environment_smash = 1
construct_spells = list(
- /spell/aoe_turf/conjure/construct/lesser,
- /spell/aoe_turf/conjure/wall,
- /spell/aoe_turf/conjure/floor,
- /spell/aoe_turf/conjure/soulstone,
- /spell/aoe_turf/conjure/pylon
+ /decl/ability/cult/construct/lesser,
+ /decl/ability/cult/construct/wall,
+ /decl/ability/cult/construct/floor,
+ /decl/ability/cult/construct/soulstone,
+ /decl/ability/cult/construct/pylon
)
hud_used = /datum/hud/construct/artificer
base_movement_delay = 0
@@ -228,7 +231,9 @@
natural_weapon = /obj/item/natural_weapon/juggernaut/behemoth
environment_smash = 2
resistance = 10
- construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser)
+ construct_spells = list(
+ /decl/ability/cult/construct/lesser
+ )
hud_used = /datum/hud/construct/juggernaut
base_movement_delay = 2
ai = /datum/mob_controller/aggressive/construct_armoured
@@ -249,7 +254,7 @@
see_in_dark = 7
hud_used = /datum/hud/construct/harvester
construct_spells = list(
- /spell/targeted/harvest
+ /decl/ability/cult/construct/harvest
)
/obj/item/natural_weapon/harvester
@@ -264,14 +269,14 @@
/mob/living/simple_animal/construct/handle_regular_status_updates()
. = ..()
if(.)
- silence_spells(purge)
+ disable_abilities(purge)
/mob/living/simple_animal/construct/handle_regular_hud_updates()
. = ..()
if(.)
if(fire)
fire.icon_state = "fire[!!GET_HUD_ALERT(src, /decl/hud_element/condition/fire)]"
- silence_spells(purge)
+ disable_abilities(purge)
if(healths)
switch(current_health)
if(250 to INFINITY) healths.icon_state = "health0"
diff --git a/mods/gamemodes/cult/mobs/constructs/soulstone.dm b/mods/gamemodes/cult/mobs/constructs/soulstone.dm
index a6e8d693c3b..69e5d0ef21e 100644
--- a/mods/gamemodes/cult/mobs/constructs/soulstone.dm
+++ b/mods/gamemodes/cult/mobs/constructs/soulstone.dm
@@ -51,7 +51,7 @@
to_chat(user, SPAN_NOTICE("You cleanse \the [src] of taint, purging its shackles to its creator."))
is_evil = FALSE
return TRUE
- else if(I.get_attack_force(user) >= 5)
+ else if(I.expend_attack_force(user) >= 5)
if(full != SOULSTONE_CRACKED)
user.visible_message(
SPAN_WARNING("\The [user] hits \the [src] with \the [I], and it breaks.[shade.client ? " You hear a terrible scream!" : ""]"),
@@ -107,6 +107,33 @@
full = f
update_icon()
+// Soulstone synthesis recipe.
+/decl/chemical_reaction/synthesis/soulstone
+ name = "Soulstone"
+ result = null
+ required_reagents = list(/decl/material/liquid/blood = 15, /decl/material/liquid/crystal_agent = 1)
+ result_amount = 1
+ hidden_from_codex = TRUE // This shouldn't show up in search. Maybe it should be linked in a 'guide to cult' or something?
+
+/decl/chemical_reaction/synthesis/soulstone/send_data(datum/reagents/holder, reaction_limit)
+ return REAGENT_DATA(holder, /decl/material/liquid/blood) // allow on_reaction to get donor data
+
+/// Whether or not the reaction should produce a soulstone or a normal crystal.
+/// The donor mob parameter may either be /mob/living or null.
+/decl/chemical_reaction/synthesis/soulstone/proc/donor_is_magic(mob/living/donor)
+ return FALSE // By default, no one is magic! This is for modpacks to override.
+
+/decl/chemical_reaction/synthesis/soulstone/on_reaction(datum/reagents/holder, created_volume, list/reaction_data)
+ var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags))
+ var/weakref/donor_ref = LAZYACCESS(reaction_data, DATA_BLOOD_DONOR)
+ if(donor_is_magic(donor_ref?.resolve()))
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/soulstone(location)
+ else // waste it and produce useless crystal shards
+ for(var/i = 1, i <= created_volume*2, i++)
+ new /obj/item/shard(location, /decl/material/solid/gemstone/crystal)
+
+// Construct shells. These accept soulstones.
/obj/structure/constructshell
name = "empty shell"
icon = 'icons/obj/structures/construct.dmi'
diff --git a/mods/gamemodes/cult/overrides.dm b/mods/gamemodes/cult/overrides.dm
index 2077c9f0b1e..2d822d252c7 100644
--- a/mods/gamemodes/cult/overrides.dm
+++ b/mods/gamemodes/cult/overrides.dm
@@ -15,6 +15,7 @@
playsound(src, 'sound/effects/ghost2.ogg', 10, 5)
/datum/trader/ship/clothingshop/hatglovesaccessories/New()
+ ..()
possible_trading_items[/obj/item/clothing/head/culthood] = TRADER_BLACKLIST_ALL
/mob/living/silicon/ai
@@ -47,9 +48,9 @@
/mob/living/simple_animal/hostile/revenant/cult/on_defilement()
return
-/obj/item/mop/Initialize()
+/obj/item/mop/populate_moppable_types()
. = ..()
- moppable_types += /obj/effect/rune
+ moppable_types |= /obj/effect/rune
/obj/effect/gateway/active/can_transform(mob/victim)
if(iscultist(victim))
diff --git a/mods/gamemodes/cult/runes.dm b/mods/gamemodes/cult/runes.dm
index 161d225a648..c54cb016914 100644
--- a/mods/gamemodes/cult/runes.dm
+++ b/mods/gamemodes/cult/runes.dm
@@ -2,7 +2,7 @@
name = "rune"
desc = "A strange collection of symbols drawn in blood."
anchored = TRUE
- icon = 'icons/effects/uristrunes.dmi'
+ icon = 'mods/gamemodes/cult/icons/runes.dmi'
icon_state = "blank"
layer = RUNE_LAYER
@@ -24,7 +24,7 @@
if(cult.rune_strokes[type])
var/list/f = cult.rune_strokes[type]
for(var/i in f)
- var/image/t = image('icons/effects/uristrunes.dmi', "rune-[i]")
+ var/image/t = image(icon, "rune-[i]")
overlays += t
else
var/list/q = list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
@@ -33,7 +33,7 @@
var/j = pick(q)
f += j
q -= f
- var/image/t = image('icons/effects/uristrunes.dmi', "rune-[j]")
+ var/image/t = image(icon, "rune-[j]")
overlays += t
cult.rune_strokes[type] = f.Copy()
color = bcolor
@@ -322,7 +322,7 @@
user.visible_message(SPAN_NOTICE("\The [user] touches \the [src] with \the [I], and it disappears."), SPAN_NOTICE("You disrupt the vile magic with the deadening field of \the [I]."))
qdel(src)
return TRUE
- var/force = I.get_attack_force(user)
+ var/force = I.expend_attack_force(user)
if(force)
user.visible_message(SPAN_NOTICE("\The [user] hits \the [src] with \the [I]."), SPAN_NOTICE("You hit \the [src] with \the [I]."))
take_damage(force, I.atom_damage_type)
@@ -480,7 +480,6 @@
var/list/mob/living/casters = get_cultists()
if(casters.len < 3)
break
- //T.turf_animation('icons/effects/effects.dmi', "rune_sac")
victim.set_fire_intensity(max(2, victim.get_fire_intensity()))
victim.ignite_fire()
var/dam_amt = 2 + length(casters)
diff --git a/mods/gamemodes/cult/spells/construct.dm b/mods/gamemodes/cult/spells/construct.dm
deleted file mode 100644
index 05c35c46785..00000000000
--- a/mods/gamemodes/cult/spells/construct.dm
+++ /dev/null
@@ -1,122 +0,0 @@
-//////////////////////////////Construct Spells/////////////////////////
-
-/spell/aoe_turf/conjure/construct
- name = "Artificer"
- desc = "This spell conjures a construct which may be controlled by Shades."
-
- school = "conjuration"
- charge_max = 600
- spell_flags = 0
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
-
- summon_type = list(/obj/structure/constructshell)
-
- hud_state = "artificer"
-
-/spell/aoe_turf/conjure/construct/lesser
- charge_max = 1800
- summon_type = list(/obj/structure/constructshell/cult)
- hud_state = "const_shell"
- override_base = "const"
-
-/spell/aoe_turf/conjure/floor
- name = "Floor Construction"
- desc = "This spell constructs a cult floor"
-
- charge_max = 20
- spell_flags = Z2NOCAST | CONSTRUCT_CHECK
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
- summon_type = list(/turf/floor/cult)
-
- hud_state = "const_floor"
-
-/spell/aoe_turf/conjure/wall
- name = "Lesser Construction"
- desc = "This spell constructs a cult wall"
-
- charge_max = 100
- spell_flags = Z2NOCAST | CONSTRUCT_CHECK
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
- summon_type = list(/turf/wall/cult)
-
- hud_state = "const_wall"
-
-/spell/aoe_turf/conjure/wall/reinforced
- name = "Greater Construction"
- desc = "This spell constructs a reinforced metal wall"
-
- charge_max = 300
- spell_flags = Z2NOCAST
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
- cast_delay = 50
-
- summon_type = list(/turf/wall/r_wall)
-
-/spell/aoe_turf/conjure/soulstone
- name = "Summon Soulstone"
- desc = "This spell reaches into Nar-Sie's realm, summoning one of the legendary fragments across time and space"
-
- charge_max = 3000
- spell_flags = 0
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
-
- summon_type = list(/obj/item/soulstone)
-
- hud_state = "const_stone"
- override_base = "const"
-
-/spell/aoe_turf/conjure/pylon
- name = "Red Pylon"
- desc = "This spell conjures a fragile crystal from Nar-Sie's realm. Makes for a convenient light source."
-
- charge_max = 200
- spell_flags = CONSTRUCT_CHECK
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
-
- summon_type = list(/obj/structure/cult/pylon)
-
- hud_state = "const_pylon"
-
-/spell/aoe_turf/conjure/pylon/cast(list/targets, mob/user)
- ..()
- var/turf/spawn_place = pick(targets)
- for(var/obj/structure/cult/pylon/P in spawn_place.contents)
- if(P.isbroken)
- P.repair(user)
- continue
- return
-
-/spell/aoe_turf/conjure/forcewall/lesser
- name = "Force Shield"
- desc = "Allows you to pull up a shield to protect yourself and allies from incoming threats"
-
- charge_max = 300
- spell_flags = 0
- invocation = "none"
- invocation_type = SpI_NONE
- range = 0
- summon_type = list(/obj/effect/forcefield/cult)
- duration = 200
-
- hud_state = "const_juggwall"
-
-//Code for the Juggernaut construct's forcefield, that seemed like a good place to put it.
-/obj/effect/forcefield/cult
- desc = "That eerie looking obstacle seems to have been pulled from another dimension through sheer force."
- name = "Juggerwall"
- icon = 'icons/effects/effects.dmi'
- icon_state = "m_shield_cult"
- light_color = "#b40000"
- light_range = 2
\ No newline at end of file
diff --git a/mods/gamemodes/cult/spells/harvest.dm b/mods/gamemodes/cult/spells/harvest.dm
deleted file mode 100644
index 41854b772bc..00000000000
--- a/mods/gamemodes/cult/spells/harvest.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-/spell/targeted/harvest
- name = "Harvest"
- desc = "Back to where I come from, and you're coming with me."
-
- school = "transmutation"
- charge_max = 200
- spell_flags = Z2NOCAST | CONSTRUCT_CHECK | INCLUDEUSER
- invocation = ""
- invocation_type = SpI_NONE
- range = 0
- max_targets = 0
-
- overlay = 1
- overlay_icon = 'icons/effects/effects.dmi'
- overlay_icon_state = "rune_teleport"
- overlay_lifespan = 0
-
- hud_state = "const_harvest"
-
-/spell/targeted/harvest/cast(list/targets, mob/user)//because harvest is already a proc
- ..()
-
- var/destination = null
- for(var/obj/effect/narsie/N in global.narsie_list)
- destination = N.loc
- break
- if(destination)
- var/prey = 0
- for(var/mob/living/M in targets)
- if(!findNullRod(M))
- M.forceMove(destination)
- if(M != user)
- prey = 1
- to_chat(user, "You warp back to Nar-Sie[prey ? " along with your prey":""].")
- else
- to_chat(user, "...something's wrong!")//There shouldn't be an instance of Harvesters when Nar-Sie isn't in the world.
-
diff --git a/mods/gamemodes/cult/structures.dm b/mods/gamemodes/cult/structures.dm
index 51db7add603..9f39d61522d 100644
--- a/mods/gamemodes/cult/structures.dm
+++ b/mods/gamemodes/cult/structures.dm
@@ -13,10 +13,10 @@
desc = "A floating crystal that hums with an unearthly energy."
icon = 'icons/obj/structures/pylon.dmi'
icon_state = "pylon"
- var/isbroken = 0
light_power = 0.5
light_range = 13
light_color = "#3e0000"
+ var/isbroken = FALSE
/obj/structure/cult/pylon/attack_hand(mob/M)
SHOULD_CALL_PARENT(FALSE)
@@ -28,7 +28,7 @@
return TRUE
/obj/structure/cult/pylon/attackby(obj/item/W, mob/user)
- attackpylon(user, W.get_attack_force(user))
+ attackpylon(user, W.expend_attack_force(user))
return TRUE
/obj/structure/cult/pylon/proc/attackpylon(mob/user, var/damage)
@@ -42,7 +42,7 @@
)
user.do_attack_animation(src)
playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1)
- isbroken = 1
+ isbroken = TRUE
set_density(0)
icon_state = "pylon-broken"
set_light(0)
@@ -61,10 +61,12 @@
/obj/structure/cult/pylon/proc/repair(mob/user)
if(isbroken)
to_chat(user, "You repair the pylon.")
- isbroken = 0
+ isbroken = FALSE
set_density(1)
icon_state = "pylon"
set_light(13, 0.5)
+ return TRUE
+ return FALSE
/obj/structure/cult/pylon/get_artifact_scan_data()
return "Tribal pylon - subject resembles statues/emblems built by cargo cult civilisations to honour energy systems from post-warp civilisations."
diff --git a/mods/gamemodes/heist/_heist.dme b/mods/gamemodes/heist/_heist.dme
index 57bf5c58b42..de2a67d69d3 100644
--- a/mods/gamemodes/heist/_heist.dme
+++ b/mods/gamemodes/heist/_heist.dme
@@ -1,13 +1,5 @@
#ifndef GAMEMODE_PACK_HEIST
#define GAMEMODE_PACK_HEIST
-
-#ifdef MODPACK_VOX
-#warn Vox modpack loaded before Heist modpack, compatibility features will be missing.
-#endif
-#ifdef GAMEMODE_PACK_MIXED
-#warn Mixed gamemodes modpack loaded before Heist modpack, Heist combination modes will be missing.
-#endif
-
// BEGIN_INCLUDE
#include "_heist.dm"
#include "areas.dm"
diff --git a/mods/gamemodes/meteor/gamemode.dm b/mods/gamemodes/meteor/gamemode.dm
index 10212d20aa9..5836f1ad154 100644
--- a/mods/gamemodes/meteor/gamemode.dm
+++ b/mods/gamemodes/meteor/gamemode.dm
@@ -93,8 +93,7 @@
/obj/effect/meteor/irradiated=10,
/obj/effect/meteor/golden=10,
/obj/effect/meteor/silver=10,
- /obj/effect/meteor/flaming=10,
- /obj/effect/meteor/supermatter=1
+ /obj/effect/meteor/flaming=10
)
// As a bonus, more frequent events.
diff --git a/mods/gamemodes/mixed.dm b/mods/gamemodes/mixed.dm
new file mode 100644
index 00000000000..f89baef2aa8
--- /dev/null
+++ b/mods/gamemodes/mixed.dm
@@ -0,0 +1,7 @@
+#ifndef GAMEMODE_PACK_MIXED
+#define GAMEMODE_PACK_MIXED
+#endif
+
+// This modpack doesn't actually have anything here, and instead it uses the compatibility patch system to make load order not matter.
+/decl/modpack/mixed_modes
+ name = "Mixed Gamemodes"
\ No newline at end of file
diff --git a/mods/gamemodes/mixed/_mixed.dm b/mods/gamemodes/mixed/_mixed.dm
deleted file mode 100644
index c1c9167d414..00000000000
--- a/mods/gamemodes/mixed/_mixed.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/decl/modpack/mixed_modes
- name = "Mixed Gamemodes"
\ No newline at end of file
diff --git a/mods/gamemodes/mixed/_mixed.dme b/mods/gamemodes/mixed/_mixed.dme
deleted file mode 100644
index 6db33d07706..00000000000
--- a/mods/gamemodes/mixed/_mixed.dme
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef GAMEMODE_PACK_MIXED
-#define GAMEMODE_PACK_MIXED
-// BEGIN_INCLUDE
-#include "_mixed.dm"
-#if defined(GAMEMODE_PACK_HEIST) // TODO: && defined(GAMEMODE_PACK_MERCENARY)
-#include "crossfire.dm"
-#endif
-#if defined(GAMEMODE_PACK_REVOLUTIONARY)
-#include "siege.dm"
-#endif
-#if defined(GAMEMODE_PACK_REVOLUTIONARY) && defined(GAMEMODE_PACK_CULT)
-#include "uprising.dm"
-#endif
-// END_INCLUDE
-#endif
\ No newline at end of file
diff --git a/mods/mobs/borers/_borers.dme b/mods/mobs/borers/_borers.dme
index 380c95f4e87..7f230fc9536 100644
--- a/mods/mobs/borers/_borers.dme
+++ b/mods/mobs/borers/_borers.dme
@@ -1,10 +1,5 @@
#ifndef CONTENT_PACK_BORERS
#define CONTENT_PACK_BORERS
-
-#ifdef MODPACK_PSIONICS
-#warn Psionics modpack loaded before Borers modpack, compatibility features will be missing.
-#endif
-
// BEGIN_INCLUDE
#include "borer.dm"
#include "datum\antagonist.dm"
diff --git a/mods/mobs/borers/datum/antagonist.dm b/mods/mobs/borers/datum/antagonist.dm
index c714ef8e1a1..423297f09f8 100644
--- a/mods/mobs/borers/datum/antagonist.dm
+++ b/mods/mobs/borers/datum/antagonist.dm
@@ -7,12 +7,12 @@
welcome_text = "Click a target while on GRAB intent to crawl into their ear and infiltrate their brain. You can only take control temporarily, and at risk of hurting your host, so be clever and careful; your host is encouraged to help you however they can. Talk to your host with Say, and your fellow borers with ,z."
antag_indicator = "hudborer"
antaghud_indicator = "hudborer"
+ antag_hud_icon = 'mods/mobs/borers/icons/hud.dmi'
faction_name = "Borer Host"
faction_descriptor = "Unity"
faction_welcome = "You are now host to a cortical borer. Please listen to what they have to say; they're in your head."
faction = "borer"
- faction_indicator = "hudalien"
hard_cap = 5
hard_cap_round = 8
diff --git a/mods/mobs/borers/datum/symbiote.dm b/mods/mobs/borers/datum/symbiote.dm
index f6954fa2bf3..bf2f17e93c4 100644
--- a/mods/mobs/borers/datum/symbiote.dm
+++ b/mods/mobs/borers/datum/symbiote.dm
@@ -21,7 +21,8 @@ var/global/list/symbiote_starting_points = list()
minimal_player_age = 14
economic_power = 0
defer_roundstart_spawn = TRUE
- hud_icon = "hudblank"
+ hud_icon_state = "hudblank"
+ hud_icon = null
outfit_type = /decl/outfit/job/symbiote_host
create_record = FALSE
var/check_whitelist // = "Symbiote"
diff --git a/mods/mobs/borers/icons/hud.dmi b/mods/mobs/borers/icons/hud.dmi
new file mode 100644
index 00000000000..8e01986fd47
Binary files /dev/null and b/mods/mobs/borers/icons/hud.dmi differ
diff --git a/mods/mobs/borers/mob/borer/borer.dm b/mods/mobs/borers/mob/borer/borer.dm
index 83dc85cd003..f9dbbe2f6e1 100644
--- a/mods/mobs/borers/mob/borer/borer.dm
+++ b/mods/mobs/borers/mob/borer/borer.dm
@@ -18,6 +18,22 @@
bleed_colour = "#816e12"
ai = /datum/mob_controller/borer
+ // Defined here to remove relaymove handlers as being
+ // directly in mob contents breaks relaymove spectacularly.
+ movement_handlers = list(
+ /datum/movement_handler/mob/death,
+ /datum/movement_handler/mob/borer_in_host,
+ /datum/movement_handler/mob/conscious,
+ /datum/movement_handler/mob/eye,
+ /datum/movement_handler/mob/delay,
+ /datum/movement_handler/mob/stop_effect,
+ /datum/movement_handler/mob/physically_capable,
+ /datum/movement_handler/mob/physically_restrained,
+ /datum/movement_handler/mob/space,
+ /datum/movement_handler/mob/multiz,
+ /datum/movement_handler/mob/movement
+ )
+
var/static/list/chemical_types = list(
"anti-trauma" = /decl/material/liquid/brute_meds,
"amphetamines" = /decl/material/liquid/amphetamines,
@@ -40,6 +56,9 @@
var/mob/living/human/host // Human host for the brain worm.
var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth.
+/datum/movement_handler/mob/borer_in_host/MayMove(mob/mover, is_external)
+ return ismob(mob.loc) ? MOVEMENT_STOP : MOVEMENT_PROCEED
+
/datum/mob_controller/borer
emote_hear = list("chirrups")
do_wander = FALSE
diff --git a/mods/mobs/borers/mob/borer/borer_attacks.dm b/mods/mobs/borers/mob/borer/borer_attacks.dm
index 5463f67d718..6c5919ed2b5 100644
--- a/mods/mobs/borers/mob/borer/borer_attacks.dm
+++ b/mods/mobs/borers/mob/borer/borer_attacks.dm
@@ -1,50 +1,44 @@
/mob/living/simple_animal/borer/UnarmedAttack(atom/A, proximity)
- . = ..()
- if(.)
- return
+ if(host)
+ return TRUE // We cannot click things outside of our host.
- if(!isliving(A) || !check_intent(I_FLAG_GRAB))
- return FALSE
+ if(!isliving(A) || !check_intent(I_FLAG_GRAB) || stat || !proximity)
+ return ..()
- if(host || !can_use_borer_ability(requires_host_value = FALSE, check_last_special = FALSE))
- return FALSE
+ if(!can_use_borer_ability(requires_host_value = FALSE, check_last_special = FALSE))
+ return TRUE
- var/mob/living/M = A
- if(M.has_brain_worms())
+ var/mob/living/victim = A
+ if(victim.has_brain_worms())
to_chat(src, SPAN_WARNING("You cannot take a host who already has a passenger!"))
return TRUE
-
- //TODO generalize borers to enter any mob. Until then, return early.
- if(!ishuman(M))
- to_chat(src, SPAN_WARNING("This creature is not sufficiently intelligent to host you."))
+ var/obj/item/organ/external/limb = GET_EXTERNAL_ORGAN(victim, BP_HEAD)
+ if(!limb)
+ to_chat(src, SPAN_WARNING("\The [victim] does not have anatomy compatible with your lifecycle!"))
return TRUE
- // end TODO
-
- var/mob/living/human/H = M
- var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(H, BP_HEAD)
- if(!E)
- to_chat(src, SPAN_WARNING("\The [H] does not have a head!"))
+ if(BP_IS_PROSTHETIC(limb))
+ to_chat(src, SPAN_WARNING("\The [victim]'s head is prosthetic and cannot support your lifecycle!"))
return TRUE
- if(!H.should_have_organ(BP_BRAIN))
- to_chat(src, SPAN_WARNING("\The [H] does not seem to have a brain cavity to enter."))
+ if(!victim.should_have_organ(BP_BRAIN))
+ to_chat(src, SPAN_WARNING("\The [victim] does not seem to have a brain cavity to enter."))
return TRUE
- if(H.check_head_coverage())
+ if(victim.check_head_coverage())
to_chat(src, SPAN_WARNING("You cannot get through that host's protective gear."))
return TRUE
- to_chat(M, SPAN_WARNING("Something slimy begins probing at the opening of your ear canal..."))
- to_chat(src, SPAN_NOTICE("You slither up [M] and begin probing at their ear canal..."))
+ to_chat(victim, SPAN_WARNING("Something slimy begins probing at the opening of your ear canal..."))
+ to_chat(src, SPAN_NOTICE("You slither up [victim] and begin probing at their ear canal..."))
set_ability_cooldown(5 SECONDS)
- if(!do_after(src, 3 SECONDS, M))
+ if(!do_after(src, 3 SECONDS, victim) || host || GET_EXTERNAL_ORGAN(victim, BP_HEAD) != limb || BP_IS_PROSTHETIC(limb) || victim.check_head_coverage())
return TRUE
- to_chat(src, SPAN_NOTICE("You wiggle into \the [M]'s ear."))
- if(M.stat == CONSCIOUS)
- to_chat(M, SPAN_DANGER("Something wet, cold and slimy wiggles into your ear!"))
+ to_chat(src, SPAN_NOTICE("You wiggle into \the [victim]'s ear."))
+ if(victim.stat == CONSCIOUS)
+ to_chat(victim, SPAN_DANGER("Something wet, cold and slimy wiggles into your ear!"))
- host = M
+ host = victim
host.status_flags |= PASSEMOTES
forceMove(host)
@@ -60,9 +54,9 @@
borers.add_antagonist_mind(host.mind, 1, borers.faction_name, borers.faction_welcome)
if(ishuman(host))
- var/obj/item/organ/internal/I = GET_INTERNAL_ORGAN(H, BP_BRAIN)
+ var/obj/item/organ/internal/I = GET_INTERNAL_ORGAN(victim, BP_BRAIN)
if(!I) // No brain organ, so the borer moves in and replaces it permanently.
replace_brain()
- else if(E) // If they're in normally, implant removal can get them out.
- LAZYDISTINCTADD(E.implants, src)
+ else if(limb) // If they're in normally, implant removal can get them out.
+ LAZYDISTINCTADD(limb.implants, src)
return TRUE
diff --git a/mods/mobs/borers/mob/borer/borer_hud.dm b/mods/mobs/borers/mob/borer/borer_hud.dm
index 8ec7b333971..79235e827d5 100644
--- a/mods/mobs/borers/mob/borer/borer_hud.dm
+++ b/mods/mobs/borers/mob/borer/borer_hud.dm
@@ -50,6 +50,7 @@
icon = 'mods/mobs/borers/icons/borer_ui.dmi'
alpha = 0
invisibility = INVISIBILITY_MAXIMUM
+ requires_ui_style = FALSE
/obj/screen/borer/handle_click(mob/user, params)
if(!isborer(user))
diff --git a/mods/mobs/borers/mob/organ.dm b/mods/mobs/borers/mob/organ.dm
index c1f686ade98..80c12e77c94 100644
--- a/mods/mobs/borers/mob/organ.dm
+++ b/mods/mobs/borers/mob/organ.dm
@@ -38,5 +38,4 @@
B.leave_host()
B.ckey = last_owner.ckey
- spawn(0)
- qdel(src)
+ qdel(src)
diff --git a/mods/mobs/borers/mob/overrides.dm b/mods/mobs/borers/mob/overrides.dm
index 77c9a2c158e..26b83686f8e 100644
--- a/mods/mobs/borers/mob/overrides.dm
+++ b/mods/mobs/borers/mob/overrides.dm
@@ -22,8 +22,10 @@
var/mob/living/simple_animal/borer/B = HAS_BRAIN_WORMS(src)
if(B.controlling)
var/image/holder = hud_list[STATUS_HUD]
+ holder.icon = 'mods/mobs/borers/icons/hud.dmi'
holder.icon_state = "hudbrainworm"
var/image/holder2 = hud_list[STATUS_HUD_OOC]
+ holder2.icon = 'mods/mobs/borers/icons/hud.dmi'
holder2.icon_state = "hudbrainworm"
/mob/living/human/say_understands(mob/speaker, decl/language/speaking)
diff --git a/mods/mobs/dionaea/mob/nymph_ui.dm b/mods/mobs/dionaea/mob/nymph_ui.dm
index cdd3a3f8c6d..fc44f7639a3 100644
--- a/mods/mobs/dionaea/mob/nymph_ui.dm
+++ b/mods/mobs/dionaea/mob/nymph_ui.dm
@@ -23,6 +23,9 @@
UI_ICON_INVENTORY = 'mods/mobs/dionaea/icons/ui_inventory.dmi'
)
+/datum/hud/diona_nymph
+// action_intent_type = /obj/screen/intent/diona_nymph
+
/datum/hud/diona_nymph/get_ui_style_data()
return GET_DECL(/decl/ui_style/diona)
@@ -37,10 +40,9 @@
var/ui_color = get_ui_color()
var/ui_alpha = get_ui_alpha()
- action_intent = new /obj/screen/intent( null, mymob) // Swap to /obj/screen/intent/binary/diona when interaction code supports it.
- mymob.healths = new /obj/screen/diona_health( null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_HEALTH)
- src.other = list()
- src.adding = list(mymob.healths, action_intent)
+ mymob.healths = new /obj/screen/diona_health(null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_HEALTH)
+ other = list()
+ adding = list(mymob.healths)
..()
/obj/screen/diona_health
diff --git a/mods/species/ascent/datum/species.dm b/mods/species/ascent/datum/species.dm
index 809da7c26fb..f6bc5dddb05 100644
--- a/mods/species/ascent/datum/species.dm
+++ b/mods/species/ascent/datum/species.dm
@@ -71,11 +71,6 @@
species_flags = SPECIES_FLAG_NO_SLIP | SPECIES_FLAG_NO_MINOR_CUT
spawn_flags = SPECIES_IS_RESTRICTED
- unarmed_attacks = list(
- /decl/natural_attack/claws/strong/gloves,
- /decl/natural_attack/bite/sharp
- )
-
force_background_info = list(
/decl/background_category/heritage = /decl/background_detail/heritage/ascent,
/decl/background_category/homeworld = /decl/background_detail/location/kharmaani,
diff --git a/mods/species/ascent/datum/species_bodytypes.dm b/mods/species/ascent/datum/species_bodytypes.dm
index 9136d47e269..87a8462b0f7 100644
--- a/mods/species/ascent/datum/species_bodytypes.dm
+++ b/mods/species/ascent/datum/species_bodytypes.dm
@@ -30,6 +30,7 @@
BP_SYSTEM_CONTROLLER = /obj/item/organ/internal/controller
)
limb_mapping = list(BP_CHEST = list(BP_CHEST, BP_M_HAND))
+ footprints_icon = 'icons/mob/footprints/footprints_snake.dmi' // big tail
heat_discomfort_strings = list(
"You feel brittle and overheated.",
diff --git a/mods/species/ascent/effects/razorweb.dm b/mods/species/ascent/effects/razorweb.dm
index c8b05c70deb..0647ffe0c91 100644
--- a/mods/species/ascent/effects/razorweb.dm
+++ b/mods/species/ascent/effects/razorweb.dm
@@ -81,7 +81,7 @@
/obj/effect/razorweb/attackby(var/obj/item/thing, var/mob/user)
var/destroy_self
- if(thing.get_attack_force(user))
+ if(thing.expend_attack_force(user))
visible_message(SPAN_DANGER("\The [user] breaks \the [src] with \the [thing]!"))
destroy_self = TRUE
diff --git a/mods/species/ascent/mobs/bodyparts.dm b/mods/species/ascent/mobs/bodyparts.dm
index a86a379a15c..dba73c0e121 100644
--- a/mods/species/ascent/mobs/bodyparts.dm
+++ b/mods/species/ascent/mobs/bodyparts.dm
@@ -5,7 +5,7 @@
var/list/existing_webs = list()
var/max_webs = 4
var/web_weave_time = 20 SECONDS
- var/cooldown
+ var/organ_cooldown
/obj/item/organ/external/groin/insectoid/mantid/gyne
max_webs = 8
@@ -20,12 +20,12 @@
/obj/item/organ/external/groin/insectoid/mantid/refresh_action_button()
. = ..()
if(.)
- action.button_icon_state = "weave-web-[cooldown ? "off" : "on"]"
+ action.button_icon_state = "weave-web-[organ_cooldown ? "off" : "on"]"
action.button?.update_icon()
/obj/item/organ/external/groin/insectoid/mantid/attack_self(var/mob/user)
. = ..()
- if(. && !cooldown)
+ if(. && !organ_cooldown)
if(!isturf(owner.loc))
to_chat(owner, SPAN_WARNING("You cannot use this ability in this location."))
@@ -41,7 +41,7 @@
playsound(user, 'mods/species/ascent/sounds/razorweb_hiss.ogg', 70)
owner.visible_message(SPAN_WARNING("\The [owner] separates their jaws and begins to weave a web of crystalline filaments..."))
- cooldown = TRUE
+ organ_cooldown = TRUE
refresh_action_button()
addtimer(CALLBACK(src, PROC_REF(reset_cooldown)), web_weave_time)
if(do_after(owner, web_weave_time) && length(existing_webs) < max_webs)
@@ -52,27 +52,27 @@
web.owner = owner
/obj/item/organ/external/groin/insectoid/mantid/proc/reset_cooldown()
- cooldown = FALSE
+ organ_cooldown = FALSE
refresh_action_button()
/obj/item/organ/external/head/insectoid/mantid
name = "crested head"
action_button_name = "Spit Razorweb"
default_action_type = /datum/action/item_action/organ/ascent
- var/cooldown_time = 2.5 MINUTES
- var/cooldown
+ var/organ_cooldown_time = 2.5 MINUTES
+ var/organ_cooldown
/obj/item/organ/external/head/insectoid/mantid/refresh_action_button()
. = ..()
if(.)
- action.button_icon_state = "shot-web-[cooldown ? "off" : "on"]"
+ action.button_icon_state = "shot-web-[organ_cooldown ? "off" : "on"]"
action.button?.update_icon()
/obj/item/organ/external/head/insectoid/mantid/attack_self(var/mob/user)
. = ..()
if(.)
- if(cooldown)
+ if(organ_cooldown)
to_chat(owner, SPAN_WARNING("Your filament channel hasn't refilled yet!"))
return
@@ -81,12 +81,12 @@
playsound(user, 'mods/species/ascent/sounds/razorweb.ogg', 100)
to_chat(owner, SPAN_WARNING("You spit up a wad of razorweb, ready to throw!"))
owner.toggle_throw_mode(TRUE)
- cooldown = TRUE
+ organ_cooldown = TRUE
refresh_action_button()
- addtimer(CALLBACK(src, PROC_REF(reset_cooldown)), cooldown_time)
+ addtimer(CALLBACK(src, PROC_REF(reset_cooldown)), organ_cooldown_time)
else
qdel(web)
/obj/item/organ/external/head/insectoid/mantid/proc/reset_cooldown()
- cooldown = FALSE
+ organ_cooldown = FALSE
refresh_action_button()
diff --git a/mods/species/ascent/mobs/nymph/nymph_inventory.dm b/mods/species/ascent/mobs/nymph/nymph_inventory.dm
index 12396419807..e79adb9931d 100644
--- a/mods/species/ascent/mobs/nymph/nymph_inventory.dm
+++ b/mods/species/ascent/mobs/nymph/nymph_inventory.dm
@@ -1,13 +1,8 @@
-/mob/living/simple_animal/alien/kharmaan/proc/contains_crystals(var/obj/item/W)
- for(var/mat in W.matter)
- if(mat == /decl/material/solid/sand)
- . += W.matter[mat]
- else if(mat == /decl/material/solid/gemstone/crystal)
- . += W.matter[mat]
- else if(mat == /decl/material/solid/quartz)
- . += W.matter[mat]
- else if(mat == /decl/material/solid/glass)
- . += W.matter[mat]
+/mob/living/simple_animal/alien/kharmaan/proc/contains_crystals(var/obj/item/prop)
+ . += prop.matter[/decl/material/solid/sand]
+ . += prop.matter[/decl/material/solid/gemstone/crystal]
+ . += prop.matter[/decl/material/solid/quartz]
+ . += prop.matter[/decl/material/solid/glass]
/datum/inventory_slot/gripper/mouth/nymph/ascent/equipped(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE, var/delete_old_item = TRUE)
var/mob/living/simple_animal/alien/kharmaan/nimp = user
diff --git a/mods/species/ascent/mobs/nymph/nymph_ui.dm b/mods/species/ascent/mobs/nymph/nymph_ui.dm
index c100c95b4cd..e3b6d1ec70c 100644
--- a/mods/species/ascent/mobs/nymph/nymph_ui.dm
+++ b/mods/species/ascent/mobs/nymph/nymph_ui.dm
@@ -38,6 +38,9 @@
UI_ICON_INVENTORY = 'mods/species/ascent/icons/ui_inventory.dmi'
)
+/datum/hud/ascent_nymph
+// action_intent_type = /obj/screen/intent/ascent_nymph
+
/datum/hud/ascent_nymph/get_ui_style_data()
return GET_DECL(/decl/ui_style/ascent)
@@ -51,13 +54,12 @@
var/decl/ui_style/ui_style = get_ui_style_data()
var/ui_color = get_ui_color()
var/ui_alpha = get_ui_alpha()
- molt = new( null, mymob, ui_style, ui_color, ui_alpha)
- food = new /obj/screen/food( null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_NUTRITION)
- drink = new /obj/screen/drink( null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_HYDRATION)
- action_intent = new /obj/screen/intent( null) // Swap to /obj/screen/intent/binary/ascent when interaction code supports it.
- mymob.healths = new /obj/screen/ascent_nymph_health( null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_HEALTH)
- src.other = list()
- src.adding = list(mymob.healths, molt, food, drink, action_intent)
+ molt = new( null, mymob, ui_style, ui_color, ui_alpha)
+ food = new /obj/screen/food( null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_NUTRITION)
+ drink = new /obj/screen/drink( null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_HYDRATION)
+ mymob.healths = new /obj/screen/ascent_nymph_health(null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_HEALTH)
+ other = list()
+ adding = list(mymob.healths, molt, food, drink)
..()
/obj/screen/ascent_nymph_health
diff --git a/mods/species/bayliens/_bayliens.dm b/mods/species/bayliens/_bayliens.dm
index 68d625b481f..80febefc65e 100644
--- a/mods/species/bayliens/_bayliens.dm
+++ b/mods/species/bayliens/_bayliens.dm
@@ -10,6 +10,14 @@
/decl/modpack/bayliens
name = "Baystation 12 Aliens"
+ tabloid_headlines = list(
+ "SHOCKING FIGURES REVEAL MORE TEENS DIE TO UNATHI HONOUR DUELS THAN GUN VIOLENCE",
+ "LOCAL UNATHI SYMPATHIZER: 'I really think you should stop with these spacebaiting articles.'",
+ "DO UNATHI SYMPATHIZERS HATE THE HUMAN RACE?",
+ "TENTACLES OF TERROR: SKRELL BLACK OPS SEIGE NYX NAVAL DEPOT. SHOCKING PHOTOGRAPHS INSIDE!",
+ "LOCAL MAN HAS SEIZURE AFTER SAYING SKRELLIAN NAME; FORCED ASSIMILATION SOON?",
+ "TAJARANS: CUTE AND CUDDLY, OR INFILTRATING THE GOVERNMENT? FIND OUT MORE INSIDE"
+ )
/decl/modpack/bayliens/pre_initialize()
..()
diff --git a/mods/species/bayliens/skrell/datum/species.dm b/mods/species/bayliens/skrell/datum/species.dm
index 0d9acdcd880..c52a6dc6735 100644
--- a/mods/species/bayliens/skrell/datum/species.dm
+++ b/mods/species/bayliens/skrell/datum/species.dm
@@ -14,12 +14,6 @@
traits = list(/decl/trait/malus/intolerance/protein = TRAIT_LEVEL_MINOR)
primitive_form = "Neaera"
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite
- )
description = "The Skrell are a highly advanced race of amphibians hailing from the system known as Qerr'Vallis. Their society is regimented into \
five different castes which the Qerr'Katish, or Royal Caste, rules over. Skrell are strict herbivores who are unable to eat large quantities of \
@@ -117,27 +111,36 @@
var/obj/item/shoes = H.get_equipped_item(slot_shoes_str)
if(!shoes)
var/list/bloodDNA
- var/list/blood_data = REAGENT_DATA(H.vessel, /decl/material/liquid/blood)
+ var/list/blood_data = REAGENT_DATA(H.vessel, blood_reagent)
if(blood_data)
bloodDNA = list(blood_data[DATA_BLOOD_DNA] = blood_data[DATA_BLOOD_TYPE])
else
bloodDNA = list()
- if(T.simulated)
- T.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints/skrellprints, bloodDNA, H.dir, 0, H.get_skin_colour() + "25") // Coming (8c is the alpha value)
+ T.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints/skrellprints, bloodDNA, H.dir, 0, H.get_skin_colour() + "25") // Coming (25 is the alpha value)
if(isturf(old_loc))
var/turf/old_turf = old_loc
- if(old_turf.simulated)
- old_turf.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints/skrellprints, bloodDNA, 0, H.dir, H.get_skin_colour() + "25") // Going (8c is the alpha value)
+ old_turf.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints/skrellprints, bloodDNA, 0, H.dir, H.get_skin_colour() + "25") // Going (25 is the alpha value)
/decl/species/skrell/check_background()
return TRUE
+/decl/material/liquid/mucus/skrell
+ name = "slime"
+ uid = "chem_mucus_skrell"
+ lore_text = "A gooey semi-liquid secreted by skrellian skin."
+
+// Copied from blood.
+// TODO: There's not currently a way to check this, which might be a little annoying for forensics.
+// But this is just a stopgap to stop Skrell from literally leaking blood everywhere they go.
+/decl/material/liquid/mucus/skrell/get_reagent_color(datum/reagents/holder)
+ var/list/goo_data = REAGENT_DATA(holder, type)
+ return goo_data?[DATA_BLOOD_COLOR] || ..()
+
/obj/effect/decal/cleanable/blood/tracks/footprints/skrellprints
name = "wet footprints"
desc = "They look like still wet tracks left by skrellian feet."
+ chemical = /decl/material/liquid/mucus/skrell
-/obj/effect/decal/cleanable/blood/tracks/footprints/skrellprints/dry()
- qdel(src)
/obj/item/organ/internal/eyes/skrell
name = "amphibian eyes"
desc = "Large black orbs, belonging to some sort of giant frog by looks of it."
diff --git a/mods/species/bayliens/tajaran/datum/species.dm b/mods/species/bayliens/tajaran/datum/species.dm
index 231ed1684f0..19de51ffc36 100644
--- a/mods/species/bayliens/tajaran/datum/species.dm
+++ b/mods/species/bayliens/tajaran/datum/species.dm
@@ -45,13 +45,6 @@
thirst_factor = DEFAULT_THIRST_FACTOR * 1.2
gluttonous = GLUT_TINY
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite/sharp
- )
-
move_trail = /obj/effect/decal/cleanable/blood/tracks/paw
available_background_info = list(
diff --git a/mods/species/bayliens/tajaran/datum/species_bodytypes.dm b/mods/species/bayliens/tajaran/datum/species_bodytypes.dm
index 225bf5bc86e..0088067d9b2 100644
--- a/mods/species/bayliens/tajaran/datum/species_bodytypes.dm
+++ b/mods/species/bayliens/tajaran/datum/species_bodytypes.dm
@@ -16,6 +16,7 @@
base_eye_color = "#00aa00"
nail_noun = "claws"
uid = "bodytype_feline"
+ footprints_icon = 'icons/mob/footprints/footprints_paw.dmi'
age_descriptor = /datum/appearance_descriptor/age/tajaran
@@ -27,7 +28,10 @@
eye_low_light_vision_adjustment_speed = 0.3
override_limb_types = list(
- BP_TAIL = /obj/item/organ/external/tail/cat
+ BP_TAIL = /obj/item/organ/external/tail/cat,
+ BP_HEAD = /obj/item/organ/external/head/sharp_bite,
+ BP_L_HAND = /obj/item/organ/external/hand/clawed,
+ BP_R_HAND = /obj/item/organ/external/hand/right/clawed
)
default_sprite_accessories = list(
diff --git a/mods/species/bayliens/tajaran/machinery/suit_cycler.dm b/mods/species/bayliens/tajaran/machinery/suit_cycler.dm
index de0b3b76a70..e3be8485345 100644
--- a/mods/species/bayliens/tajaran/machinery/suit_cycler.dm
+++ b/mods/species/bayliens/tajaran/machinery/suit_cycler.dm
@@ -47,5 +47,6 @@
/obj/item/clothing/suit/space/void
_feline_onmob_icon = 'mods/species/bayliens/tajaran/icons/clothing/nasa/suit.dmi'
+
/obj/item/clothing/suit/space/void/excavation
_feline_onmob_icon = 'mods/species/bayliens/tajaran/icons/clothing/excavation/suit.dmi'
diff --git a/mods/species/bayliens/tritonian/datum/species.dm b/mods/species/bayliens/tritonian/datum/species.dm
index a6e415dbce0..84491dd46cf 100644
--- a/mods/species/bayliens/tritonian/datum/species.dm
+++ b/mods/species/bayliens/tritonian/datum/species.dm
@@ -13,10 +13,3 @@
body_temperature = 302
water_soothe_amount = 5
-
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite/sharp
- )
diff --git a/mods/species/bayliens/tritonian/datum/species_bodytypes.dm b/mods/species/bayliens/tritonian/datum/species_bodytypes.dm
index 0e5614f62d5..dadaac398a3 100644
--- a/mods/species/bayliens/tritonian/datum/species_bodytypes.dm
+++ b/mods/species/bayliens/tritonian/datum/species_bodytypes.dm
@@ -6,6 +6,9 @@
override_organ_types = list(
BP_LUNGS = /obj/item/organ/internal/lungs/gills
)
+ override_limb_types = list(
+ BP_HEAD = /obj/item/organ/external/head/sharp_bite
+ )
/decl/bodytype/human/tritonian/masculine
name = "masculine"
diff --git a/mods/species/bayliens/unathi/datum/species.dm b/mods/species/bayliens/unathi/datum/species.dm
index 43ab46e0049..ad4a508329b 100644
--- a/mods/species/bayliens/unathi/datum/species.dm
+++ b/mods/species/bayliens/unathi/datum/species.dm
@@ -24,13 +24,6 @@
/decl/bodytype/lizard,
/decl/bodytype/lizard/masculine
)
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/tail,
- /decl/natural_attack/claws,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite/sharp
- )
available_accessory_categories = list(
SAC_HORNS,
diff --git a/mods/species/bayliens/unathi/datum/species_bodytypes.dm b/mods/species/bayliens/unathi/datum/species_bodytypes.dm
index 31e9a058438..226241bc9a1 100644
--- a/mods/species/bayliens/unathi/datum/species_bodytypes.dm
+++ b/mods/species/bayliens/unathi/datum/species_bodytypes.dm
@@ -18,6 +18,7 @@
eye_flash_mod = 1.2
nail_noun = "claws"
uid = "bodytype_unathi_fem"
+ footprints_icon = 'mods/species/bayliens/unathi/icons/footprints.dmi'
age_descriptor = /datum/appearance_descriptor/age/lizard
@@ -33,19 +34,24 @@
)
override_organ_types = list(
- BP_EYES = /obj/item/organ/internal/eyes/lizard,
- BP_BRAIN = /obj/item/organ/internal/brain/lizard
+ BP_EYES = /obj/item/organ/internal/eyes/lizard,
+ BP_BRAIN = /obj/item/organ/internal/brain/lizard
)
- override_limb_types = list(BP_TAIL = /obj/item/organ/external/tail/lizard)
+ override_limb_types = list(
+ BP_TAIL = /obj/item/organ/external/tail/lizard,
+ BP_HEAD = /obj/item/organ/external/head/strong_bite,
+ BP_L_HAND = /obj/item/organ/external/hand/clawed,
+ BP_R_HAND = /obj/item/organ/external/hand/right/clawed
+ )
- cold_level_1 = 280 //Default 260 - Lower is better
- cold_level_2 = 220 //Default 200
- cold_level_3 = 130 //Default 120
+ cold_level_1 = 280 //Default 260 - Lower is better
+ cold_level_2 = 220 //Default 200
+ cold_level_3 = 130 //Default 120
- heat_level_1 = 420 //Default 360 - Higher is better
- heat_level_2 = 480 //Default 400
- heat_level_3 = 1100 //Default 1000
+ heat_level_1 = 420 //Default 360 - Higher is better
+ heat_level_2 = 480 //Default 400
+ heat_level_3 = 1100 //Default 1000
heat_discomfort_level = 320
heat_discomfort_strings = list(
@@ -80,3 +86,7 @@
/obj/item/organ/external/tail/lizard
tail_icon = 'mods/species/bayliens/unathi/icons/tail.dmi'
tail_animation_states = 9
+
+/obj/item/organ/external/tail/lizard/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/tail)
+ return unarmed_attack
diff --git a/mods/species/bayliens/unathi/icons/footprints.dmi b/mods/species/bayliens/unathi/icons/footprints.dmi
new file mode 100644
index 00000000000..fe21767b108
Binary files /dev/null and b/mods/species/bayliens/unathi/icons/footprints.dmi differ
diff --git a/mods/species/drakes/_drakes.dme b/mods/species/drakes/_drakes.dme
index 1143d6a510e..025f1c54c51 100644
--- a/mods/species/drakes/_drakes.dme
+++ b/mods/species/drakes/_drakes.dme
@@ -1,10 +1,5 @@
#ifndef MODPACK_DRAKES
#define MODPACK_DRAKES
-
-#ifdef MODPACK_FANTASY
-#warn Fantasy modpack loaded before Drakes modpack, compatibility features will be missing.
-#endif
-
// BEGIN_INCLUDE
#include "_drakes.dm"
#include "_overrides.dm"
diff --git a/mods/species/drakes/_overrides.dm b/mods/species/drakes/_overrides.dm
index a4c564def3c..a4246927c61 100644
--- a/mods/species/drakes/_overrides.dm
+++ b/mods/species/drakes/_overrides.dm
@@ -2,7 +2,7 @@
var/_drake_onmob_icon
var/_drake_hatchling_onmob_icon
-/obj/item/backpack/setup_sprite_sheets()
+/obj/item/setup_sprite_sheets()
. = ..()
if(_drake_onmob_icon)
LAZYSET(sprite_sheets, BODYTYPE_GRAFADREKA, _drake_onmob_icon)
diff --git a/mods/species/drakes/drake_abilities.dm b/mods/species/drakes/drake_abilities.dm
index 85b589c73f6..fb4d7b0fcab 100644
--- a/mods/species/drakes/drake_abilities.dm
+++ b/mods/species/drakes/drake_abilities.dm
@@ -6,9 +6,11 @@
spit_projectile_type = /obj/item/projectile/drake_spit/weak
/datum/ability_handler/predator/grafadreka/can_do_ranged_invocation(mob/user, atom/target)
- return istype(user) && user.check_intent(I_FLAG_HARM) && !user.incapacitated() && isatom(target)
+ return ..() || (istype(user) && user.check_intent(I_FLAG_HARM) && !user.incapacitated() && isatom(target))
/datum/ability_handler/predator/grafadreka/do_ranged_invocation(mob/user, atom/target)
+ if((. = ..()))
+ return
if(world.time < next_spit)
to_chat(user, SPAN_WARNING("You cannot spit again so soon!"))
return TRUE
diff --git a/mods/species/drakes/sifsap.dm b/mods/species/drakes/sifsap.dm
index f0fd4f179ef..5334839e70f 100644
--- a/mods/species/drakes/sifsap.dm
+++ b/mods/species/drakes/sifsap.dm
@@ -44,9 +44,9 @@
M.add_chemical_effect(CE_PULSE, -1)
return ..()
-/decl/material/liquid/sifsap/affect_overdose(mob/living/M, total_dose)
- if(M.has_trait(/decl/trait/sivian_biochemistry))
+/decl/material/liquid/sifsap/affect_overdose(mob/living/victim, total_dose)
+ if(victim.has_trait(/decl/trait/sivian_biochemistry))
return
- M.apply_damage(1, IRRADIATE)
- SET_STATUS_MAX(M, 5, STAT_DROWSY)
+ victim.apply_damage(1, IRRADIATE)
+ SET_STATUS_MAX(victim, 5, STAT_DROWSY)
return ..()
diff --git a/mods/species/drakes/species.dm b/mods/species/drakes/species.dm
index 228b9b9f505..a3a14352074 100644
--- a/mods/species/drakes/species.dm
+++ b/mods/species/drakes/species.dm
@@ -20,10 +20,7 @@
/decl/pronouns/male,
/decl/pronouns/female
)
- unarmed_attacks = list(
- /decl/natural_attack/bite/sharp/drake,
- /decl/natural_attack/claws/strong/drake
- )
+
force_background_info = list(
/decl/background_category/heritage = /decl/background_detail/heritage/grafadreka,
/decl/background_category/homeworld = /decl/background_detail/location/grafadreka,
@@ -37,16 +34,11 @@
traits = list(
/decl/trait/sivian_biochemistry = TRAIT_LEVEL_EXISTS
)
+ move_trail = /obj/effect/decal/cleanable/blood/tracks/paw
// Drakes must be whitelisted for jobs to be able to join as them, see maps.dm.
job_blacklist_by_default = TRUE
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
- character_preview_screen_locs = list(
- "1" = "character_preview_map:1,4:36",
- "2" = "character_preview_map:1,3:31",
- "4" = "character_preview_map:1,2:26",
- "8" = "character_preview_map:1,1:21"
- )
var/list/adult_pain_emotes_with_pain_level = list(
list(/decl/emote/audible/drake_huff, /decl/emote/audible/drake_rattle) = 20
diff --git a/mods/species/drakes/species_bodytypes.dm b/mods/species/drakes/species_bodytypes.dm
index dc5afea4ea4..aae52bd678a 100644
--- a/mods/species/drakes/species_bodytypes.dm
+++ b/mods/species/drakes/species_bodytypes.dm
@@ -38,7 +38,8 @@
override_limb_types = list(
BP_TAIL = /obj/item/organ/external/tail/grafadreka,
BP_L_HAND = /obj/item/organ/external/hand/quadruped/grafadreka,
- BP_R_HAND = /obj/item/organ/external/hand/right/quadruped/grafadreka
+ BP_R_HAND = /obj/item/organ/external/hand/right/quadruped/grafadreka,
+ BP_HEAD = /obj/item/organ/external/head/gripper/grafadreka
)
base_color = "#608894"
base_eye_color = COLOR_SILVER
@@ -46,6 +47,8 @@
antaghud_offset_x = 16
override_organ_types = list(BP_DRAKE_GIZZARD = /obj/item/organ/internal/drake_gizzard)
uid = "bodytype_drake"
+ footprints_icon = 'icons/mob/footprints/footprints_paw.dmi'
+
additional_emotes = list(
/decl/emote/audible/drake_warble,
/decl/emote/audible/drake_purr,
@@ -94,6 +97,13 @@
/decl/emote/visible/tfist
)
+ character_preview_screen_locs = list(
+ "1" = "character_preview_map:1,4:36",
+ "2" = "character_preview_map:1,3:31",
+ "4" = "character_preview_map:1,2:26",
+ "8" = "character_preview_map:1,1:21"
+ )
+
available_mob_postures = list(
/decl/posture/standing,
/decl/posture/lying/drake,
@@ -184,6 +194,7 @@
blood_overlays = 'mods/species/drakes/icons/hatchling_blood.dmi'
eye_icon = 'mods/species/drakes/icons/hatchling_eyes.dmi'
icon_template = 'icons/mob/human_races/species/template.dmi'
+ damage_overlays = 'icons/mob/human_races/species/default_damage_overlays.dmi'
bodytype_category = BODYTYPE_GRAFADREKA_HATCHLING
mob_size = MOB_SIZE_SMALL
pixel_offset_x = 0
@@ -192,9 +203,14 @@
/datum/ability_handler/predator/grafadreka/hatchling
)
z_flags = 0
+ // TODO: weaker attack subtypes for the baby
override_limb_types = list(
- BP_TAIL = /obj/item/organ/external/tail/grafadreka/hatchling
+ BP_TAIL = /obj/item/organ/external/tail/grafadreka/hatchling,
+ BP_L_HAND = /obj/item/organ/external/hand/quadruped/grafadreka,
+ BP_R_HAND = /obj/item/organ/external/hand/right/quadruped/grafadreka,
+ BP_HEAD = /obj/item/organ/external/head/gripper/grafadreka
)
+
default_emotes = list(
/decl/emote/audible/drake_hatchling_growl,
/decl/emote/audible/drake_hatchling_whine,
@@ -203,6 +219,7 @@
/decl/emote/audible/drake_sneeze
)
age_descriptor = /datum/appearance_descriptor/age/grafadreka/hatchling
+ character_preview_screen_locs = null
uid = "bodytype_drake_hatchling"
/decl/bodytype/quadruped/grafadreka/hatchling/Initialize()
@@ -296,6 +313,10 @@
_base_attack_force = 8
needs_attack_dexterity = DEXTERITY_NONE
+/obj/item/organ/external/hand/quadruped/grafadreka/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/claws/strong/drake)
+ return unarmed_attack
+
/obj/item/organ/external/hand/quadruped/grafadreka/Initialize(mapload, material_key, datum/mob_snapshot/supplied_appearance, decl/bodytype/new_bodytype)
. = ..()
item_flags |= ITEM_FLAG_NO_BLUDGEON
@@ -312,6 +333,10 @@
_base_attack_force = 8
needs_attack_dexterity = DEXTERITY_NONE
+/obj/item/organ/external/hand/right/quadruped/grafadreka/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/claws/strong/drake)
+ return unarmed_attack
+
/obj/item/organ/external/hand/right/quadruped/grafadreka/Initialize(mapload, material_key, datum/mob_snapshot/supplied_appearance, decl/bodytype/new_bodytype)
. = ..()
item_flags |= ITEM_FLAG_NO_BLUDGEON
@@ -323,3 +348,7 @@
/obj/item/organ/external/hand/right/quadruped/grafadreka/set_bodytype(decl/bodytype/new_bodytype, override_material, apply_to_internal_organs)
override_material = /decl/material/solid/organic/bone
. = ..()
+
+/obj/item/organ/external/head/gripper/grafadreka/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/bite/sharp/drake)
+ return unarmed_attack
diff --git a/mods/species/neoavians/clothing.dm b/mods/species/neoavians/clothing.dm
index 3172b72a2e5..f4cdcaaed1b 100644
--- a/mods/species/neoavians/clothing.dm
+++ b/mods/species/neoavians/clothing.dm
@@ -18,11 +18,12 @@
_avian_onmob_icon = null
//Backpacks & tanks
-
/obj/item/backpack/satchel
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/satchel.dmi'
//Radsuits (theyre essential?)
+/obj/item/clothing/head/radiation
+ _avian_onmob_icon = 'mods/species/neoavians/icons/clothing/head/rad_helm.dmi'
/obj/item/clothing/head/radiation
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/head/rad_helm.dmi'
@@ -77,12 +78,16 @@
name = "stylish uniform"
icon = 'mods/species/neoavians/icons/clothing/under/stylish_form.dmi'
+/obj/item/clothing/shoes
+ _avian_onmob_icon = 'mods/species/neoavians/icons/clothing/feet/shoes.dmi'
+
/obj/item/clothing/shoes/avian
name = "small shoes"
icon = 'mods/species/neoavians/icons/clothing/feet/shoes.dmi'
color = COLOR_GRAY
bodytype_equip_flags = BODY_EQUIP_FLAG_AVIAN
_avian_onmob_icon = null
+ icon = 'mods/species/neoavians/icons/clothing/feet/shoes.dmi'
/obj/item/clothing/shoes/avian/footwraps
name = "cloth footwraps"
diff --git a/mods/species/neoavians/datum/species.dm b/mods/species/neoavians/datum/species.dm
index a0bfea025ed..065b6c6d932 100644
--- a/mods/species/neoavians/datum/species.dm
+++ b/mods/species/neoavians/datum/species.dm
@@ -52,12 +52,6 @@
swap_flags = MONKEY|SIMPLE_ANIMAL
push_flags = MONKEY|SIMPLE_ANIMAL
- unarmed_attacks = list(
- /decl/natural_attack/bite/sharp,
- /decl/natural_attack/claws,
- /decl/natural_attack/stomp/weak
- )
-
available_background_info = list(
/decl/background_category/heritage = list(
/decl/background_detail/heritage/neoavian,
diff --git a/mods/species/neoavians/datum/species_bodytypes.dm b/mods/species/neoavians/datum/species_bodytypes.dm
index 46abc0d51b6..dd1b48d63e3 100644
--- a/mods/species/neoavians/datum/species_bodytypes.dm
+++ b/mods/species/neoavians/datum/species_bodytypes.dm
@@ -39,6 +39,13 @@
base_eye_color = "#f5c842"
mob_size = MOB_SIZE_SMALL
nail_noun = "talons"
+ override_limb_types = list(
+ BP_L_FOOT = /obj/item/organ/external/foot/avian,
+ BP_R_FOOT = /obj/item/organ/external/foot/right/avian,
+ BP_L_HAND = /obj/item/organ/external/hand/clawed,
+ BP_R_HAND = /obj/item/organ/external/hand/right/clawed,
+ BP_HEAD = /obj/item/organ/external/head/sharp_bite
+ )
has_organ = list(
BP_STOMACH = /obj/item/organ/internal/stomach,
BP_HEART = /obj/item/organ/internal/heart,
diff --git a/mods/species/neoavians/icons/clothing/spacesuit/void/medical/helmet.dmi b/mods/species/neoavians/icons/clothing/spacesuit/void/medical/helmet.dmi
index fe7e1534a7e..645c2a006bf 100644
Binary files a/mods/species/neoavians/icons/clothing/spacesuit/void/medical/helmet.dmi and b/mods/species/neoavians/icons/clothing/spacesuit/void/medical/helmet.dmi differ
diff --git a/mods/species/neoavians/icons/clothing/spacesuit/void/medical_alt/helmet.dmi b/mods/species/neoavians/icons/clothing/spacesuit/void/medical_alt/helmet.dmi
new file mode 100644
index 00000000000..779b0d77fe4
Binary files /dev/null and b/mods/species/neoavians/icons/clothing/spacesuit/void/medical_alt/helmet.dmi differ
diff --git a/mods/species/neoavians/icons/clothing/spacesuit/void/medical_alt/suit.dmi b/mods/species/neoavians/icons/clothing/spacesuit/void/medical_alt/suit.dmi
new file mode 100644
index 00000000000..c84f8e938c6
Binary files /dev/null and b/mods/species/neoavians/icons/clothing/spacesuit/void/medical_alt/suit.dmi differ
diff --git a/mods/species/neoavians/machinery/suit_cycler.dm b/mods/species/neoavians/machinery/suit_cycler.dm
index 2fd6323e6ed..4397f39c94d 100644
--- a/mods/species/neoavians/machinery/suit_cycler.dm
+++ b/mods/species/neoavians/machinery/suit_cycler.dm
@@ -11,7 +11,6 @@
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/mining/helmet.dmi'
//excavation
-
/obj/item/clothing/suit/space/void/excavation
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/mining/suit.dmi'
@@ -19,7 +18,6 @@
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/mining/helmet.dmi'
//engineering
-
/obj/item/clothing/head/helmet/space/void/engineering
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/engineering/helmet.dmi'
@@ -33,15 +31,19 @@
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/atmos/suit.dmi'
//medical
-
/obj/item/clothing/suit/space/void/medical
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/medical/suit.dmi'
/obj/item/clothing/head/helmet/space/void/medical
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/medical/helmet.dmi'
-//security
+/obj/item/clothing/suit/space/void/medical/alt
+ _avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/medical_alt/suit.dmi'
+/obj/item/clothing/head/helmet/space/void/medical/alt
+ _avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/medical_alt/helmet.dmi'
+
+//security
/obj/item/clothing/head/helmet/space/void/security
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/sec/helmet.dmi'
@@ -49,7 +51,6 @@
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/sec/suit.dmi'
//salvage
-
/obj/item/clothing/head/helmet/space/void/engineering/salvage
_avian_onmob_icon = 'mods/species/neoavians/icons/clothing/spacesuit/void/salvage/helmet.dmi'
diff --git a/mods/species/serpentid/datum/species.dm b/mods/species/serpentid/datum/species.dm
index 388b267140f..8dc853194d4 100644
--- a/mods/species/serpentid/datum/species.dm
+++ b/mods/species/serpentid/datum/species.dm
@@ -60,8 +60,6 @@
swap_flags = ALLMOBS
move_trail = /obj/effect/decal/cleanable/blood/tracks/snake
- unarmed_attacks = list(/decl/natural_attack/forelimb_slash)
-
pain_emotes_with_pain_level = list(
list(/decl/emote/audible/bug_hiss) = 40
)
@@ -101,12 +99,6 @@
return FALSE
-/decl/species/serpentid/can_shred(var/mob/living/human/H, var/ignore_intent, var/ignore_antag)
- if(!H.get_equipped_item(slot_handcuffed_str) || H.buckled)
- return ..(H, ignore_intent, TRUE)
- else
- return 0
-
/decl/species/serpentid/handle_movement_delay_special(var/mob/living/human/victim)
var/tally = 0
victim.remove_cloaking_source(src)
diff --git a/mods/species/serpentid/datum/species_bodytypes.dm b/mods/species/serpentid/datum/species_bodytypes.dm
index 6c4e562b451..947019f4db7 100644
--- a/mods/species/serpentid/datum/species_bodytypes.dm
+++ b/mods/species/serpentid/datum/species_bodytypes.dm
@@ -34,15 +34,16 @@
BP_HEAD = list("path" = /obj/item/organ/external/head/insectoid/serpentid),
BP_L_ARM = list("path" = /obj/item/organ/external/arm/insectoid),
BP_L_HAND = list("path" = /obj/item/organ/external/hand/insectoid),
- BP_L_HAND_UPPER = list("path" = /obj/item/organ/external/hand/insectoid/upper),
+ BP_L_HAND_UPPER = list("path" = /obj/item/organ/external/hand/insectoid/upper/serpentid),
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/insectoid),
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/insectoid),
- BP_R_HAND_UPPER = list("path" = /obj/item/organ/external/hand/right/insectoid/upper),
+ BP_R_HAND_UPPER = list("path" = /obj/item/organ/external/hand/right/insectoid/upper/serpentid),
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/insectoid/serpentid),
BP_L_LEG = list("path" = /obj/item/organ/external/leg/insectoid/serpentid),
BP_L_FOOT = list("path" = /obj/item/organ/external/foot/insectoid/serpentid),
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/insectoid/serpentid)
)
+
appearance_descriptors = list(
/datum/appearance_descriptor/height = 1.75,
/datum/appearance_descriptor/body_length = 1
@@ -63,6 +64,7 @@
ARMOR_BIO = ARMOR_BIO_SHIELDED,
ARMOR_RAD = 0.5*ARMOR_RAD_MINOR
)
+ footprints_icon = 'icons/mob/footprints/footprints_snake.dmi'
/decl/bodytype/serpentid/Initialize()
_equip_adjust = list(
@@ -121,3 +123,11 @@
name = "green"
icon_base = 'mods/species/serpentid/icons/body_green.dmi'
uid = "bodytype_serpentid_green"
+
+/obj/item/organ/external/hand/insectoid/upper/serpentid/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/forelimb_slash)
+ return unarmed_attack
+
+/obj/item/organ/external/hand/right/insectoid/upper/serpentid/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/forelimb_slash)
+ return unarmed_attack
diff --git a/mods/species/skrell/datum/species.dm b/mods/species/skrell/datum/species.dm
index 59a1be8470a..76c57542f62 100644
--- a/mods/species/skrell/datum/species.dm
+++ b/mods/species/skrell/datum/species.dm
@@ -12,12 +12,6 @@
)
primitive_form = "Neaera"
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite
- )
description = "The skrell are a highly advanced species of amphibians hailing from \
the system known as Qerr'Vallis, which translates to 'Star of the royals' or 'Light of the Crown'. \
diff --git a/mods/species/tajaran/datum/species.dm b/mods/species/tajaran/datum/species.dm
index bc39f5beedc..e6e5c8673a7 100644
--- a/mods/species/tajaran/datum/species.dm
+++ b/mods/species/tajaran/datum/species.dm
@@ -52,13 +52,6 @@
thirst_factor = DEFAULT_THIRST_FACTOR * 1.2
gluttonous = GLUT_TINY
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite/sharp
- )
-
move_trail = /obj/effect/decal/cleanable/blood/tracks/paw
default_emotes = list(
diff --git a/mods/species/tajaran/datum/species_bodytypes.dm b/mods/species/tajaran/datum/species_bodytypes.dm
index 14134c1f697..a6be9223460 100644
--- a/mods/species/tajaran/datum/species_bodytypes.dm
+++ b/mods/species/tajaran/datum/species_bodytypes.dm
@@ -27,9 +27,11 @@
eye_low_light_vision_adjustment_speed = 0.3
override_limb_types = list(
- BP_TAIL = /obj/item/organ/external/tail/cat
+ BP_TAIL = /obj/item/organ/external/tail/cat,
+ BP_HEAD = /obj/item/organ/external/head/sharp_bite,
+ BP_L_HAND = /obj/item/organ/external/hand/clawed,
+ BP_R_HAND = /obj/item/organ/external/hand/right/clawed
)
-
default_sprite_accessories = list(
SAC_HAIR = list(/decl/sprite_accessory/hair/taj/lynx = list(SAM_COLOR = "#46321c")),
SAC_MARKINGS = list(/decl/sprite_accessory/marking/tajaran/ears = list(SAM_COLOR = "#ae7d32"))
diff --git a/mods/species/teshari/datum/species.dm b/mods/species/teshari/datum/species.dm
index 961dcca689c..fee57b3d085 100644
--- a/mods/species/teshari/datum/species.dm
+++ b/mods/species/teshari/datum/species.dm
@@ -53,12 +53,6 @@
swap_flags = MONKEY|SIMPLE_ANIMAL
push_flags = MONKEY|SIMPLE_ANIMAL
- unarmed_attacks = list(
- /decl/natural_attack/bite/sharp,
- /decl/natural_attack/claws,
- /decl/natural_attack/stomp/weak
- )
-
blood_types = list(
/decl/blood_type/avian/taplus,
/decl/blood_type/avian/taminus,
diff --git a/mods/species/teshari/datum/species_bodytypes.dm b/mods/species/teshari/datum/species_bodytypes.dm
index 5e2c51f6984..8ce0a9ee7e4 100644
--- a/mods/species/teshari/datum/species_bodytypes.dm
+++ b/mods/species/teshari/datum/species_bodytypes.dm
@@ -12,6 +12,13 @@
base_eye_color = "#f5c842"
mob_size = MOB_SIZE_SMALL
nail_noun = "talons"
+ override_limb_types = list(
+ BP_L_FOOT = /obj/item/organ/external/foot/avian,
+ BP_R_FOOT = /obj/item/organ/external/foot/right/avian,
+ BP_L_HAND = /obj/item/organ/external/hand/clawed,
+ BP_R_HAND = /obj/item/organ/external/hand/right/clawed,
+ BP_HEAD = /obj/item/organ/external/head/sharp_bite
+ )
has_organ = list(
BP_STOMACH = /obj/item/organ/internal/stomach,
BP_HEART = /obj/item/organ/internal/heart,
@@ -21,7 +28,6 @@
BP_BRAIN = /obj/item/organ/internal/brain,
BP_EYES = /obj/item/organ/internal/eyes
)
- override_limb_types = list(BP_TAIL = /obj/item/organ/external/tail/avian)
default_sprite_accessories = list(
SAC_HAIR = list(/decl/sprite_accessory/hair/avian = list(SAM_COLOR = "#252525")),
SAC_MARKINGS = list(/decl/sprite_accessory/marking/avian = list(SAM_COLOR = "#454545"))
diff --git a/mods/species/unathi/datum/species.dm b/mods/species/unathi/datum/species.dm
index 5eed1b3b6b5..9a63a510ab5 100644
--- a/mods/species/unathi/datum/species.dm
+++ b/mods/species/unathi/datum/species.dm
@@ -24,13 +24,6 @@
/decl/bodytype/unathi,
/decl/bodytype/unathi/masculine
)
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/tail,
- /decl/natural_attack/claws,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite/sharp
- )
available_accessory_categories = list(
SAC_HORNS,
diff --git a/mods/species/unathi/datum/species_bodytypes.dm b/mods/species/unathi/datum/species_bodytypes.dm
index e3fe7d1cbe1..8f1278f846c 100644
--- a/mods/species/unathi/datum/species_bodytypes.dm
+++ b/mods/species/unathi/datum/species_bodytypes.dm
@@ -19,6 +19,13 @@
nail_noun = "claws"
uid = "bodytype_unathi_fem"
+ override_limb_types = list(
+ BP_TAIL = /obj/item/organ/external/tail/unathi,
+ BP_HEAD = /obj/item/organ/external/head/strong_bite,
+ BP_L_HAND = /obj/item/organ/external/hand/clawed,
+ BP_R_HAND = /obj/item/organ/external/hand/right/clawed
+ )
+
age_descriptor = /datum/appearance_descriptor/age/unathi
default_sprite_accessories = list(
@@ -80,3 +87,7 @@
/obj/item/organ/external/tail/unathi
tail_icon = 'mods/species/unathi/icons/tail.dmi'
tail_animation_states = 9
+
+/obj/item/organ/external/tail/unathi/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/tail)
+ return unarmed_attack
diff --git a/mods/species/utility_frames/species.dm b/mods/species/utility_frames/species.dm
index 77a9f1f7ebc..0e9ce9013bc 100644
--- a/mods/species/utility_frames/species.dm
+++ b/mods/species/utility_frames/species.dm
@@ -32,11 +32,6 @@
preview_outfit = null
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/punch
- )
available_pronouns = list(
/decl/pronouns,
/decl/pronouns/neuter
diff --git a/mods/species/vox/_vox.dme b/mods/species/vox/_vox.dme
index 83d61f50f51..0e0e635d99b 100644
--- a/mods/species/vox/_vox.dme
+++ b/mods/species/vox/_vox.dme
@@ -8,7 +8,6 @@
#include "datum\cultures_vox.dm"
#include "datum\descriptors_vox.dm"
#include "datum\factions_vox.dm"
-#include "datum\heist_compatibility.dm"
#include "datum\language.dm"
#include "datum\locations_vox.dm"
#include "datum\outfits.dm"
diff --git a/mods/species/vox/datum/species.dm b/mods/species/vox/datum/species.dm
index 02f7fed9313..eac1ad15786 100644
--- a/mods/species/vox/datum/species.dm
+++ b/mods/species/vox/datum/species.dm
@@ -32,14 +32,6 @@
/mob/living/human/proc/toggle_vox_pressure_seal
)
- unarmed_attacks = list(
- /decl/natural_attack/stomp,
- /decl/natural_attack/kick,
- /decl/natural_attack/claws/strong/gloves,
- /decl/natural_attack/punch,
- /decl/natural_attack/bite/strong
- )
-
rarity_value = 4
description = {"The Vox are the broken remnants of a once-proud race, now reduced to little more
diff --git a/mods/species/vox/datum/species_bodytypes.dm b/mods/species/vox/datum/species_bodytypes.dm
index cff74b6141d..092cfeb50b9 100644
--- a/mods/species/vox/datum/species_bodytypes.dm
+++ b/mods/species/vox/datum/species_bodytypes.dm
@@ -30,9 +30,13 @@
BP_BRAIN
)
override_limb_types = list(
- BP_GROIN = /obj/item/organ/external/groin/vox,
- BP_TAIL = /obj/item/organ/external/tail/vox
+ BP_GROIN = /obj/item/organ/external/groin/vox,
+ BP_TAIL = /obj/item/organ/external/tail/vox,
+ BP_L_HAND = /obj/item/organ/external/hand/vox,
+ BP_R_HAND = /obj/item/organ/external/hand/right/vox,
+ BP_HEAD = /obj/item/organ/external/head/strong_bite
)
+
has_organ = list(
BP_STOMACH = /obj/item/organ/internal/stomach/vox,
BP_HEART = /obj/item/organ/internal/heart/vox,
@@ -172,3 +176,11 @@
/obj/item/organ/external/tail/vox/stanchion
tail_icon = 'mods/species/vox/icons/body/stanchion/body.dmi'
+
+/obj/item/organ/external/hand/vox/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/claws/strong/gloves)
+ return unarmed_attack
+
+/obj/item/organ/external/hand/right/vox/get_natural_attacks()
+ var/static/unarmed_attack = GET_DECL(/decl/natural_attack/claws/strong/gloves)
+ return unarmed_attack
diff --git a/mods/species/vox/datum/unit_testing.dm b/mods/species/vox/datum/unit_testing.dm
index 1026f897cad..1010d534842 100644
--- a/mods/species/vox/datum/unit_testing.dm
+++ b/mods/species/vox/datum/unit_testing.dm
@@ -4,7 +4,7 @@
/datum/unit_test/mob_damage/vox
name = "MOB: Vox damage check template"
- template = /datum/unit_test/mob_damage/vox
+ abstract_type = /datum/unit_test/mob_damage/vox
mob_type = /mob/living/human/vox
/datum/unit_test/mob_damage/vox/brute
diff --git a/mods/~compatibility/patches/fantasy.dm b/mods/~compatibility/patches/fantasy.dm
new file mode 100644
index 00000000000..4b4d6f7feab
--- /dev/null
+++ b/mods/~compatibility/patches/fantasy.dm
@@ -0,0 +1,9 @@
+// Override drake lore and names for the fantasy modpack.
+#ifdef MODPACK_DRAKES
+#include "fantasy/drake_fantasy.dm"
+#endif
+
+// Make whetstones available for the fantasy modpack/
+#ifdef MODPACK_ITEM_SHARPENING
+#include "fantasy/whetstone_fantasy.dm"
+#endif
diff --git a/mods/~compatibility/patches/fantasy/drake_fantasy.dm b/mods/~compatibility/patches/fantasy/drake_fantasy.dm
new file mode 100644
index 00000000000..70ad5e628e7
--- /dev/null
+++ b/mods/~compatibility/patches/fantasy/drake_fantasy.dm
@@ -0,0 +1,21 @@
+// Rename grafadreka
+/decl/species/grafadreka
+ name = "Meredrake"
+ name_plural = "Meredrakes"
+ description = "Meredrakes, sometimes called mire-drakes, are large reptillian pack predators, widely assumed to be cousins to true dragons. \
+ They are commonly found living in caves or burrows bordering grassland or forest, and while they prefer to hunt deer or rabbits, they will sometimes attack travellers if pickings are slim enough. \
+ While they are not domesticated, they can be habituated and trained as working animals if captured young enough."
+
+/decl/sprite_accessory/marking/grafadreka
+ species_allowed = list("Meredrake")
+
+/decl/language/grafadreka
+ desc = "Hiss hiss, feed me rabbits."
+
+/decl/material/liquid/sifsap
+ name = "drake spittle"
+ lore_text = "A complex chemical slurry brewed up in the gullet of meredrakes."
+
+/obj/aura/sifsap_salve
+ name = "Drakespittle Salve"
+ descriptor = "glowing spittle"
diff --git a/mods/~compatibility/patches/fantasy/whetstone_fantasy.dm b/mods/~compatibility/patches/fantasy/whetstone_fantasy.dm
new file mode 100644
index 00000000000..b2821d26fa6
--- /dev/null
+++ b/mods/~compatibility/patches/fantasy/whetstone_fantasy.dm
@@ -0,0 +1,7 @@
+// Make whetstones available in character generation.
+/decl/loadout_option/fantasy/utility/whetstone
+ name = "whetstone"
+ path = /obj/item/whetstone
+ available_materials = null
+ loadout_flags = null
+ uid = "gear_fantasy_whetstone"
diff --git a/mods/species/vox/datum/heist_compatibility.dm b/mods/~compatibility/patches/heist_vox.dm
similarity index 98%
rename from mods/species/vox/datum/heist_compatibility.dm
rename to mods/~compatibility/patches/heist_vox.dm
index 776057948c0..e37a3416faa 100644
--- a/mods/species/vox/datum/heist_compatibility.dm
+++ b/mods/~compatibility/patches/heist_vox.dm
@@ -1,4 +1,3 @@
-#ifdef GAMEMODE_PACK_HEIST
/decl/special_role/raider/Initialize()
. = ..()
LAZYSET(outfits_per_species, SPECIES_VOX, /decl/outfit/vox_raider)
@@ -41,4 +40,3 @@
vox.SetName(vox.real_name)
var/decl/special_role/raider/raiders = GET_DECL(/decl/special_role/raider)
raiders.update_access(vox)
-#endif
\ No newline at end of file
diff --git a/mods/~compatibility/patches/mixed_gamemodes.dm b/mods/~compatibility/patches/mixed_gamemodes.dm
new file mode 100644
index 00000000000..c554702eff5
--- /dev/null
+++ b/mods/~compatibility/patches/mixed_gamemodes.dm
@@ -0,0 +1,12 @@
+// TODO: #ifdef GAMEMODE_PACK_MERCENARY
+#if defined(GAMEMODE_PACK_HEIST)
+#include "mixed_gamemodes/crossfire.dm"
+#endif
+#if defined(GAMEMODE_PACK_REVOLUTIONARY)
+#include "mixed_gamemodes/siege.dm"
+#endif
+// #endif
+
+#if defined(GAMEMODE_PACK_REVOLUTIONARY) && defined(GAMEMODE_PACK_CULT)
+#include "mixed_gamemodes/uprising.dm"
+#endif
\ No newline at end of file
diff --git a/mods/gamemodes/mixed/crossfire.dm b/mods/~compatibility/patches/mixed_gamemodes/crossfire.dm
similarity index 100%
rename from mods/gamemodes/mixed/crossfire.dm
rename to mods/~compatibility/patches/mixed_gamemodes/crossfire.dm
diff --git a/mods/gamemodes/mixed/siege.dm b/mods/~compatibility/patches/mixed_gamemodes/siege.dm
similarity index 100%
rename from mods/gamemodes/mixed/siege.dm
rename to mods/~compatibility/patches/mixed_gamemodes/siege.dm
diff --git a/mods/gamemodes/mixed/uprising.dm b/mods/~compatibility/patches/mixed_gamemodes/uprising.dm
similarity index 100%
rename from mods/gamemodes/mixed/uprising.dm
rename to mods/~compatibility/patches/mixed_gamemodes/uprising.dm
diff --git a/mods/~compatibility/patches/psionics.dm b/mods/~compatibility/patches/psionics.dm
new file mode 100644
index 00000000000..93473b9271f
--- /dev/null
+++ b/mods/~compatibility/patches/psionics.dm
@@ -0,0 +1,13 @@
+// Give borers a paramount rank psi aura, and gives them a ranged psychic attack.
+#ifdef CONTENT_PACK_BORERS
+#include "psionics/borer_psi.dm"
+#endif
+// Allows psion blood to be used to create soulstones,
+// and lets full soulstones nullify psi and shatter into nullglass.
+#ifdef GAMEMODE_PACK_CULT
+#include "psionics/cult_psi.dm"
+#endif
+// Adds psi abilities to the counselor.
+#ifdef MODPACK_STANDARD_JOBS
+#include "psionics/psi_jobs.dm"
+#endif
\ No newline at end of file
diff --git a/mods/content/psionics/system/psionics/mob/borer_power.dm b/mods/~compatibility/patches/psionics/borer_psi.dm
similarity index 97%
rename from mods/content/psionics/system/psionics/mob/borer_power.dm
rename to mods/~compatibility/patches/psionics/borer_psi.dm
index 48f62c8adab..68c70ec95f7 100644
--- a/mods/content/psionics/system/psionics/mob/borer_power.dm
+++ b/mods/~compatibility/patches/psionics/borer_psi.dm
@@ -1,4 +1,3 @@
-#ifdef CONTENT_PACK_BORERS
/mob/living/simple_animal/borer
var/image/aura_image
@@ -52,5 +51,4 @@
SET_STATUS_MAX(M, STAT_WEAK, 10)
set_ability_cooldown(15 SECONDS)
- return TRUE
-#endif
\ No newline at end of file
+ return TRUE
\ No newline at end of file
diff --git a/mods/~compatibility/patches/psionics/cult_psi.dm b/mods/~compatibility/patches/psionics/cult_psi.dm
new file mode 100644
index 00000000000..0fa46de32d6
--- /dev/null
+++ b/mods/~compatibility/patches/psionics/cult_psi.dm
@@ -0,0 +1,18 @@
+// Make psion blood usable for soulstone synthesis.
+/decl/chemical_reaction/synthesis/soulstone/donor_is_magic(mob/living/donor)
+ return ..() || !!donor?.get_ability_handler(/datum/ability_handler/psionics)
+
+// Make soulstones interact with psionics.
+/obj/item/soulstone/disrupts_psionics()
+ . = !full ? src : FALSE
+
+/obj/item/soulstone/shatter()
+ for(var/i=1 to rand(2,5))
+ new /obj/item/shard(get_turf(src), full ? /decl/material/nullglass : /decl/material/solid/gemstone/crystal)
+ . = ..()
+
+/obj/item/soulstone/withstand_psi_stress(var/stress, var/atom/source)
+ . = ..(stress, source)
+ if(. > 0)
+ . = max(0, . - rand(2,5))
+ shatter()
\ No newline at end of file
diff --git a/mods/~compatibility/patches/psionics/psi_jobs.dm b/mods/~compatibility/patches/psionics/psi_jobs.dm
new file mode 100644
index 00000000000..d62d097022f
--- /dev/null
+++ b/mods/~compatibility/patches/psionics/psi_jobs.dm
@@ -0,0 +1,6 @@
+/datum/job/standard/counselor/equip_job(var/mob/living/human/H)
+ if(H.mind.role_alt_title == "Counselor")
+ psi_faculties = list("[PSI_REDACTION]" = PSI_RANK_OPERANT)
+ if(H.mind.role_alt_title == "Mentalist")
+ psi_faculties = list("[PSI_COERCION]" = PSI_RANK_OPERANT)
+ return ..()
\ No newline at end of file
diff --git a/mods/~compatibility/patches/supermatter.dm b/mods/~compatibility/patches/supermatter.dm
new file mode 100644
index 00000000000..27f6a6f4475
--- /dev/null
+++ b/mods/~compatibility/patches/supermatter.dm
@@ -0,0 +1,12 @@
+// Add the supermatter monitor to engineering jobs' default software.
+#ifdef MODPACK_STANDARD_JOBS
+#include "supermatter/supermatter_jobs.dm"
+#endif
+// Disable Narsie during the supermatter cascade.
+#ifdef GAMEMODE_PACK_CULT
+#include "supermatter/sm_disable_narsie.dm"
+#endif
+// Add the supermatter meteor to the meteor gamemode's cataclysmic meteors list.
+#ifdef GAMEMODE_PACK_METEOR
+#include "supermatter/sm_meteor.dm"
+#endif
\ No newline at end of file
diff --git a/mods/~compatibility/patches/supermatter/sm_disable_narsie.dm b/mods/~compatibility/patches/supermatter/sm_disable_narsie.dm
new file mode 100644
index 00000000000..a660384347b
--- /dev/null
+++ b/mods/~compatibility/patches/supermatter/sm_disable_narsie.dm
@@ -0,0 +1,4 @@
+// Disable Narsie when a supermatter cascade begins.
+/datum/universal_state/supermatter_cascade/OnEnter()
+ var/decl/special_role/cultist/cult = GET_DECL(/decl/special_role/cultist)
+ cult.allow_narsie = 0
\ No newline at end of file
diff --git a/mods/~compatibility/patches/supermatter/sm_meteor.dm b/mods/~compatibility/patches/supermatter/sm_meteor.dm
new file mode 100644
index 00000000000..df383bc3f76
--- /dev/null
+++ b/mods/~compatibility/patches/supermatter/sm_meteor.dm
@@ -0,0 +1,3 @@
+/decl/game_mode/meteor/Initialize()
+ . = ..() // No debounce, decls only init once.
+ meteors_cataclysm[/obj/effect/meteor/destroyer/supermatter] = 1
\ No newline at end of file
diff --git a/mods/~compatibility/patches/supermatter/supermatter_jobs.dm b/mods/~compatibility/patches/supermatter/supermatter_jobs.dm
new file mode 100644
index 00000000000..2a62b17318c
--- /dev/null
+++ b/mods/~compatibility/patches/supermatter/supermatter_jobs.dm
@@ -0,0 +1,7 @@
+/datum/job/standard/chief_engineer/New()
+ ..()
+ software_on_spawn |= /datum/computer_file/program/supermatter_monitor
+
+/datum/job/standard/engineer/New()
+ ..()
+ software_on_spawn |= /datum/computer_file/program/supermatter_monitor
\ No newline at end of file
diff --git a/mods/~compatibility/readme.md b/mods/~compatibility/readme.md
new file mode 100644
index 00000000000..d422273e7bb
--- /dev/null
+++ b/mods/~compatibility/readme.md
@@ -0,0 +1,22 @@
+# Modpack Compatibility System
+This folder exists as a way to work around the fact that the previous system for modpack cross-compatibility, define-gating, is sensitive to include order. This resulted in a lot of boilerplate, like having to emit warnings if modpacks were included in the wrong order. This meant that you could also introduce cyclical dependencies, where no matter what it would emit a warning and content would be missing.
+
+To avoid this issue, we instead include all compatibility patches last, so it is load order agnostic.
+
+## FAQ
+### Why aren't the compatibility files in the modpacks themselves?
+I didn't want to edit the modpack include validation script to exclude the compatibility patches from all DMEs.
+
+### Why is it organised using subfolders?
+I didn't like using `#if defined(FOO) && defined(BAR)` and nested `#ifdef`s were hard to follow, so instead I group them by modpack.
+
+### Is there a general rule for which modpacks get their own folder?
+Not really. I just grouped them in roughly the way that would result in the largest existing groupings, and then chose groupings that would make the most sense to expand in the future (fantasy and standard jobs).
+
+### Do all patches need to be in a subfolder?
+No, it's totally fine to just put something in the base patches directory if there's only one patch for either of the mods in that pairing. That said, sometimes it can make sense to add a folder with just one patch if you can foresee future development requiring additional patches in the same category.
+
+### How do I decide which folder a patch goes in if both modpacks have folders?
+I tend to personally go based on whatever it's mostly about; a hypothetical patch renaming and respriting psionics for the fantasy modpack would go in the fantasy folder. Alternatively, you could think of it as going for whichever one is more specific.
+
+That said, if one has a lot more patches than the other, or if one modpack (take Standard Jobs, for example) is patched by several modpacks that already have folders, it's fine to just go with whatever produces the largest patch subfolders (or gets rid of small/redundant ones).
\ No newline at end of file
diff --git a/mods/~compatibility/~compatibility.dm b/mods/~compatibility/~compatibility.dm
new file mode 100644
index 00000000000..6d3b770558f
--- /dev/null
+++ b/mods/~compatibility/~compatibility.dm
@@ -0,0 +1,20 @@
+// Add Vox-specific content for the Heist gamemode (Vox raider outfit, mirror to transform into a Vox as a raider)
+#if defined(GAMEMODE_PACK_HEIST) && defined(MODPACK_VOX)
+#include "patches/heist_vox.dm"
+#endif
+
+#ifdef MODPACK_PSIONICS
+#include "patches/psionics.dm"
+#endif
+
+#ifdef GAMEMODE_PACK_MIXED
+#include "patches/mixed_gamemodes.dm"
+#endif
+
+#ifdef MODPACK_FANTASY_SPECIES
+#include "patches/fantasy.dm"
+#endif
+
+#ifdef CONTENT_PACK_SUPERMATTER
+#include "patches/supermatter.dm"
+#endif
diff --git a/nano/images/shaded_hills/shaded_hills-1.png b/nano/images/shaded_hills/shaded_hills-1.png
new file mode 100644
index 00000000000..862e93356aa
Binary files /dev/null and b/nano/images/shaded_hills/shaded_hills-1.png differ
diff --git a/nano/images/shaded_hills/shaded_hills-2.png b/nano/images/shaded_hills/shaded_hills-2.png
new file mode 100644
index 00000000000..cc7727eb7d2
Binary files /dev/null and b/nano/images/shaded_hills/shaded_hills-2.png differ
diff --git a/nano/images/shaded_hills/shaded_hills-3.png b/nano/images/shaded_hills/shaded_hills-3.png
new file mode 100644
index 00000000000..ab087ace58e
Binary files /dev/null and b/nano/images/shaded_hills/shaded_hills-3.png differ
diff --git a/nano/images/shaded_hills/shaded_hills-4.png b/nano/images/shaded_hills/shaded_hills-4.png
new file mode 100644
index 00000000000..97408dc32f6
Binary files /dev/null and b/nano/images/shaded_hills/shaded_hills-4.png differ
diff --git a/nano/images/shaded_hills/shaded_hills-5.png b/nano/images/shaded_hills/shaded_hills-5.png
new file mode 100644
index 00000000000..a4d8cf90dd2
Binary files /dev/null and b/nano/images/shaded_hills/shaded_hills-5.png differ
diff --git a/nano/images/shaded_hills/shaded_hills-6.png b/nano/images/shaded_hills/shaded_hills-6.png
new file mode 100644
index 00000000000..3cb34e5cb67
Binary files /dev/null and b/nano/images/shaded_hills/shaded_hills-6.png differ
diff --git a/nano/templates/radio_basic.tmpl b/nano/templates/radio_basic.tmpl
index fc94e17029c..b3ba6f4830a 100644
--- a/nano/templates/radio_basic.tmpl
+++ b/nano/templates/radio_basic.tmpl
@@ -138,12 +138,11 @@ Used In File(s): /code/game/objects/item/devices/radio/radio.dm
◼{{:value.display_name}}
- {{if value.secure_channel}}
- {{:helper.link('On', null, {'ch_name' : value.chan, 'listen' : 1}, value.listening ? 'selected' : null)}}
- {{:helper.link('Off', null, {'ch_name' : value.chan, 'listen' : 0}, value.listening ? null : 'selected')}}
- {{else}}
- {{:helper.link('Switch', null, {'spec_freq' : value.chan}, data.rawfreq == value.chan ? 'selected' : null)}}
- {{/if}}
+ {{:helper.link('On', null, {'ch_name' : value.chan, 'listen' : 1}, value.listening ? 'selected' : null)}}
+ {{:helper.link('Off', null, {'ch_name' : value.chan, 'listen' : 0}, value.listening ? null : 'selected')}}
+ {{if !value.secure_channel}}
+ {{:helper.link('Switch', null, {'spec_freq' : value.chan}, data.rawfreq == value.chan ? 'selected' : null)}}
+ {{/if}}
{{/for}}
{{/if}}
diff --git a/nebula.dme b/nebula.dme
index 02615909325..3bd032e7efd 100644
--- a/nebula.dme
+++ b/nebula.dme
@@ -10,6 +10,7 @@
#define DEBUG
// END_PREFERENCES
// BEGIN_INCLUDE
+#include "code\___compile_options.dm"
#include "code\___opendream_linting.dm"
#include "code\__globals.dm"
#include "code\_macros.dm"
@@ -20,7 +21,6 @@
#include "code\__datastructures\stack.dm"
#include "code\__defines\_byond_version_compat.dm"
#include "code\__defines\_compile_helpers.dm"
-#include "code\__defines\_compile_options.dm"
#include "code\__defines\_planes+layers.dm"
#include "code\__defines\_tick.dm"
#include "code\__defines\admin.dm"
@@ -60,6 +60,7 @@
#include "code\__defines\intent.dm"
#include "code\__defines\interactions.dm"
#include "code\__defines\inventory_sizes.dm"
+#include "code\__defines\item_effects.dm"
#include "code\__defines\items_clothing.dm"
#include "code\__defines\jobs.dm"
#include "code\__defines\languages.dm"
@@ -192,7 +193,6 @@
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\skybox.dm"
#include "code\_onclick\hud\screen\_screen.dm"
-#include "code\_onclick\hud\screen\screen_abilities.dm"
#include "code\_onclick\hud\screen\screen_action_button.dm"
#include "code\_onclick\hud\screen\screen_ai_button.dm"
#include "code\_onclick\hud\screen\screen_attack_selector.dm"
@@ -211,6 +211,7 @@
#include "code\_onclick\hud\screen\screen_intent.dm"
#include "code\_onclick\hud\screen\screen_internal.dm"
#include "code\_onclick\hud\screen\screen_inventory.dm"
+#include "code\_onclick\hud\screen\screen_inventory_hands.dm"
#include "code\_onclick\hud\screen\screen_lighting.dm"
#include "code\_onclick\hud\screen\screen_maneuver.dm"
#include "code\_onclick\hud\screen\screen_module.dm"
@@ -220,7 +221,6 @@
#include "code\_onclick\hud\screen\screen_radial.dm"
#include "code\_onclick\hud\screen\screen_resist.dm"
#include "code\_onclick\hud\screen\screen_robot_drop_grab.dm"
-#include "code\_onclick\hud\screen\screen_robot_intent.dm"
#include "code\_onclick\hud\screen\screen_robot_inventory.dm"
#include "code\_onclick\hud\screen\screen_robot_modules.dm"
#include "code\_onclick\hud\screen\screen_robot_panel.dm"
@@ -282,8 +282,8 @@
#include "code\controllers\subsystems\mapping.dm"
#include "code\controllers\subsystems\misc_late.dm"
#include "code\controllers\subsystems\overlays.dm"
+#include "code\controllers\subsystems\overmap.dm"
#include "code\controllers\subsystems\pathfinding.dm"
-#include "code\controllers\subsystems\plants.dm"
#include "code\controllers\subsystems\radiation.dm"
#include "code\controllers\subsystems\shuttle.dm"
#include "code\controllers\subsystems\skybox.dm"
@@ -327,7 +327,7 @@
#include "code\controllers\subsystems\processing\mobs.dm"
#include "code\controllers\subsystems\processing\nano.dm"
#include "code\controllers\subsystems\processing\obj.dm"
-#include "code\controllers\subsystems\processing\overmap.dm"
+#include "code\controllers\subsystems\processing\plants.dm"
#include "code\controllers\subsystems\processing\processing.dm"
#include "code\controllers\subsystems\processing\projectiles.dm"
#include "code\controllers\subsystems\processing\temperature.dm"
@@ -427,8 +427,13 @@
#include "code\datums\extensions\abilities\abilities.dm"
#include "code\datums\extensions\abilities\abilities_mob.dm"
#include "code\datums\extensions\abilities\abilities_predator.dm"
+#include "code\datums\extensions\abilities\ability_button.dm"
+#include "code\datums\extensions\abilities\ability_decl.dm"
#include "code\datums\extensions\abilities\ability_handler.dm"
#include "code\datums\extensions\abilities\ability_item.dm"
+#include "code\datums\extensions\abilities\ability_projectile.dm"
+#include "code\datums\extensions\abilities\ability_targeting.dm"
+#include "code\datums\extensions\abilities\readme.dm"
#include "code\datums\extensions\appearance\appearance.dm"
#include "code\datums\extensions\appearance\base_icon_state.dm"
#include "code\datums\extensions\appearance\cardborg.dm"
@@ -740,6 +745,7 @@
#include "code\game\atoms_fires.dm"
#include "code\game\atoms_fluids.dm"
#include "code\game\atoms_init.dm"
+#include "code\game\atoms_interactions.dm"
#include "code\game\atoms_layering.dm"
#include "code\game\atoms_movable.dm"
#include "code\game\atoms_movable_grabs.dm"
@@ -747,7 +753,6 @@
#include "code\game\atoms_movable_overlay.dm"
#include "code\game\atoms_temperature.dm"
#include "code\game\base_turf.dm"
-#include "code\game\images.dm"
#include "code\game\movietitles.dm"
#include "code\game\response_team.dm"
#include "code\game\sound.dm"
@@ -782,9 +787,6 @@
#include "code\game\gamemodes\endgame\endgame.dm"
#include "code\game\gamemodes\endgame\ftl_jump\ftl_jump.dm"
#include "code\game\gamemodes\endgame\nuclear_explosion\nuclear_explosion.dm"
-#include "code\game\gamemodes\endgame\supermatter_cascade\cascade_blob.dm"
-#include "code\game\gamemodes\endgame\supermatter_cascade\portal.dm"
-#include "code\game\gamemodes\endgame\supermatter_cascade\universe.dm"
#include "code\game\gamemodes\events\power_failure.dm"
#include "code\game\gamemodes\extended\extended.dm"
#include "code\game\gamemodes\nuclear\nuclear.dm"
@@ -1023,6 +1025,7 @@
#include "code\game\objects\effects\effect_system.dm"
#include "code\game\objects\effects\explosion_particles.dm"
#include "code\game\objects\effects\fake_fire.dm"
+#include "code\game\objects\effects\footprints.dm"
#include "code\game\objects\effects\force_portal.dm"
#include "code\game\objects\effects\gateway.dm"
#include "code\game\objects\effects\gibspawner.dm"
@@ -1071,12 +1074,14 @@
#include "code\game\objects\items\_item_materials.dm"
#include "code\game\objects\items\_item_melting.dm"
#include "code\game\objects\items\_item_reagents.dm"
+#include "code\game\objects\items\_item_sharpness.dm"
#include "code\game\objects\items\apc_frame.dm"
#include "code\game\objects\items\blackout.dm"
#include "code\game\objects\items\blueprints.dm"
#include "code\game\objects\items\bodybag.dm"
#include "code\game\objects\items\buttons.dm"
#include "code\game\objects\items\candelabra.dm"
+#include "code\game\objects\items\chisel.dm"
#include "code\game\objects\items\christmas.dm"
#include "code\game\objects\items\contraband.dm"
#include "code\game\objects\items\crutches.dm"
@@ -1085,6 +1090,7 @@
#include "code\game\objects\items\fleece.dm"
#include "code\game\objects\items\glassjar.dm"
#include "code\game\objects\items\holosign_creator.dm"
+#include "code\game\objects\items\horseshoe.dm"
#include "code\game\objects\items\hourglass.dm"
#include "code\game\objects\items\instruments.dm"
#include "code\game\objects\items\latexballoon.dm"
@@ -1106,6 +1112,8 @@
#include "code\game\objects\items\trash.dm"
#include "code\game\objects\items\umbrella.dm"
#include "code\game\objects\items\waterskin.dm"
+#include "code\game\objects\items\artifice\chain.dm"
+#include "code\game\objects\items\artifice\hook.dm"
#include "code\game\objects\items\blades\_blade.dm"
#include "code\game\objects\items\blades\axe.dm"
#include "code\game\objects\items\blades\axe_fire.dm"
@@ -1252,7 +1260,6 @@
#include "code\game\objects\items\weapons\RPD.dm"
#include "code\game\objects\items\weapons\RSF.dm"
#include "code\game\objects\items\weapons\secrets_disk.dm"
-#include "code\game\objects\items\weapons\shields.dm"
#include "code\game\objects\items\weapons\soap.dm"
#include "code\game\objects\items\weapons\staff.dm"
#include "code\game\objects\items\weapons\stunbaton.dm"
@@ -1312,7 +1319,6 @@
#include "code\game\objects\items\weapons\grenades\prank_grenades.dm"
#include "code\game\objects\items\weapons\grenades\smokebomb.dm"
#include "code\game\objects\items\weapons\grenades\spawnergrenade.dm"
-#include "code\game\objects\items\weapons\grenades\supermatter.dm"
#include "code\game\objects\items\weapons\implants\implant.dm"
#include "code\game\objects\items\weapons\implants\implantcase.dm"
#include "code\game\objects\items\weapons\implants\implantchair.dm"
@@ -1350,6 +1356,12 @@
#include "code\game\objects\items\weapons\melee\energy_projected.dm"
#include "code\game\objects\items\weapons\melee\energy_sword.dm"
#include "code\game\objects\items\weapons\melee\misc.dm"
+#include "code\game\objects\items\weapons\shields\_shield.dm"
+#include "code\game\objects\items\weapons\shields\shield_crafted.dm"
+#include "code\game\objects\items\weapons\shields\shield_crafted_buckler.dm"
+#include "code\game\objects\items\weapons\shields\shield_crafting.dm"
+#include "code\game\objects\items\weapons\shields\shield_energy.dm"
+#include "code\game\objects\items\weapons\shields\shield_riot.dm"
#include "code\game\objects\items\weapons\storage\backpack.dm"
#include "code\game\objects\items\weapons\storage\bags.dm"
#include "code\game\objects\items\weapons\storage\basket.dm"
@@ -1414,6 +1426,8 @@
#include "code\game\objects\structures\__structure.dm"
#include "code\game\objects\structures\_structure_construction.dm"
#include "code\game\objects\structures\_structure_icon.dm"
+#include "code\game\objects\structures\_structure_interactions.dm"
+#include "code\game\objects\structures\_structure_lock.dm"
#include "code\game\objects\structures\_structure_materials.dm"
#include "code\game\objects\structures\ai_decoy.dm"
#include "code\game\objects\structures\armor_stand.dm"
@@ -1478,8 +1492,8 @@
#include "code\game\objects\structures\showcase.dm"
#include "code\game\objects\structures\signs.dm"
#include "code\game\objects\structures\skele_stand.dm"
+#include "code\game\objects\structures\snowman.dm"
#include "code\game\objects\structures\stasis_cage.dm"
-#include "code\game\objects\structures\structure_lock.dm"
#include "code\game\objects\structures\tables.dm"
#include "code\game\objects\structures\tank_dispenser.dm"
#include "code\game\objects\structures\target_stake.dm"
@@ -1639,6 +1653,7 @@
#include "code\game\verbs\who.dm"
#include "code\modules\abstract\_abstract.dm"
#include "code\modules\abstract\abstract_exterior_marker.dm"
+#include "code\modules\abstract\abstract_fluid_direction.dm"
#include "code\modules\abstract\abstract_ramp_sculptor.dm"
#include "code\modules\abstract\airlock_helper.dm"
#include "code\modules\acting\acting_items.dm"
@@ -2211,6 +2226,7 @@
#include "code\modules\codex\entries\weapons.dm"
#include "code\modules\crafting\handmade_fancy.dm"
#include "code\modules\crafting\handmade_items.dm"
+#include "code\modules\crafting\forging\bellows.dm"
#include "code\modules\crafting\metalwork\metalwork_items.dm"
#include "code\modules\crafting\pottery\pottery_moulds.dm"
#include "code\modules\crafting\pottery\pottery_structures.dm"
@@ -2731,6 +2747,7 @@
#include "code\modules\materials\definitions\gasses\material_gas_mundane.dm"
#include "code\modules\materials\definitions\liquids\_mat_liquid.dm"
#include "code\modules\materials\definitions\liquids\materials_liquid_chemistry.dm"
+#include "code\modules\materials\definitions\liquids\materials_liquid_mundane.dm"
#include "code\modules\materials\definitions\liquids\materials_liquid_solvents.dm"
#include "code\modules\materials\definitions\liquids\materials_liquid_soup.dm"
#include "code\modules\materials\definitions\liquids\materials_liquid_toxins.dm"
@@ -2882,6 +2899,7 @@
#include "code\modules\mob\living\living_give.dm"
#include "code\modules\mob\living\living_grabs.dm"
#include "code\modules\mob\living\living_hallucinations.dm"
+#include "code\modules\mob\living\living_hud.dm"
#include "code\modules\mob\living\living_maneuvers.dm"
#include "code\modules\mob\living\living_organs.dm"
#include "code\modules\mob\living\living_powers.dm"
@@ -3168,7 +3186,6 @@
#include "code\modules\modular_computers\file_system\programs\engineering\rcon_console.dm"
#include "code\modules\modular_computers\file_system\programs\engineering\shields_monitor.dm"
#include "code\modules\modular_computers\file_system\programs\engineering\shutoff_valve.dm"
-#include "code\modules\modular_computers\file_system\programs\engineering\supermatter_monitor.dm"
#include "code\modules\modular_computers\file_system\programs\generic\camera.dm"
#include "code\modules\modular_computers\file_system\programs\generic\configurator.dm"
#include "code\modules\modular_computers\file_system\programs\generic\crew_manifest.dm"
@@ -3422,6 +3439,7 @@
#include "code\modules\posture\posture_bodytype.dm"
#include "code\modules\posture\posture_mob.dm"
#include "code\modules\posture\posture_subtypes.dm"
+#include "code\modules\power\admin_setup_engine.dm"
#include "code\modules\power\apc.dm"
#include "code\modules\power\batteryrack.dm"
#include "code\modules\power\breaker_box.dm"
@@ -3783,14 +3801,6 @@
#include "code\modules\species\station\human_bodytypes.dm"
#include "code\modules\species\station\monkey.dm"
#include "code\modules\species\station\monkey_bodytypes.dm"
-#include "code\modules\spells\construct_spells.dm"
-#include "code\modules\spells\spell_code.dm"
-#include "code\modules\spells\spells.dm"
-#include "code\modules\spells\aoe_turf\aoe_turf.dm"
-#include "code\modules\spells\aoe_turf\conjure\conjure.dm"
-#include "code\modules\spells\targeted\ethereal_jaunt.dm"
-#include "code\modules\spells\targeted\shift.dm"
-#include "code\modules\spells\targeted\targeted.dm"
#include "code\modules\sprite_accessories\_accessory.dm"
#include "code\modules\sprite_accessories\_accessory_category.dm"
#include "code\modules\sprite_accessories\cosmetics\_accessory_cosmetics.dm"
@@ -3832,9 +3842,6 @@
#include "code\modules\submaps\submap_job.dm"
#include "code\modules\submaps\submap_join.dm"
#include "code\modules\submaps\submap_landmark.dm"
-#include "code\modules\supermatter\setup_supermatter.dm"
-#include "code\modules\supermatter\sm_looping_sound.dm"
-#include "code\modules\supermatter\supermatter.dm"
#include "code\modules\surgery\__surgery_setup.dm"
#include "code\modules\surgery\_surgery.dm"
#include "code\modules\surgery\bones.dm"
@@ -4104,5 +4111,6 @@
#include "maps\~mapsystem\maps_unit_testing.dm"
#include "maps\~unit_tests\unit_testing.dm"
#include "mods\_modpack.dm"
+#include "mods\~compatibility\~compatibility.dm"
#include "~code\global_init.dm"
// END_INCLUDE
diff --git a/test/check-paths.sh b/test/check-paths.sh
index dcf902b9335..852c681ae6c 100755
--- a/test/check-paths.sh
+++ b/test/check-paths.sh
@@ -23,34 +23,35 @@ exactly() { # exactly N name search [mode] [filter]
# With the potential exception of << if you increase any of these numbers you're probably doing it wrong
# Additional exception August 2020: \b is a regex symbol as well as a BYOND macro.
-exactly 1 "escapes" '\\\\(red|blue|green|black|b|i[^mc])'
-exactly 8 "Del()s" '\WDel\('
+exactly 3 "escapes" '\\(red|blue|green|black|b|i[^mc])'
+exactly 3 "Del()s" '(?> uses" '>>(?!>)' -P
+exactly 1 "world<< uses" 'world\s*<<'
+exactly 74 "'in world' uses" '\s+\bin world\b(?=\s*$|\s*//|\s*\))' -P
+exactly 1 "world.log<< uses" 'world.log\s*<<'
+exactly 18 "<< uses" '(?> uses" '(?\\])>>(?!>)' -P
exactly 0 "incorrect indentations" '^( {4,})' -P
-exactly 22 "text2path uses" 'text2path'
-exactly 4 "update_icon() override" '/update_icon\((.*)\)' -P
-exactly 0 "goto uses" 'goto '
+exactly 23 "text2path uses" 'text2path'
+exactly 4 "update_icon() overrides" '\/update_icon\(' -P
+exactly 0 "goto uses" '\bgoto\b'
exactly 9 "atom/New uses" '^/(obj|atom|area|mob|turf).*/New\('
exactly 1 "decl/New uses" '^/decl.*/New\('
-exactly 0 "tag uses" '\stag = ' -P '*.dmm'
-exactly 3 "unmarked globally scoped variables" '^(/|)var/(?!global)' -P
-exactly 0 "global-marked member variables" '\t(/|)var.*/global/.+' -P
-exactly 0 "static-marked globally scoped variables" '^(/|)var.*/static/.+' -P
+exactly 3 "tag uses" '(? 2:
+ ckey = sys.argv[2]
+ if ckey is not None:
+ ckey = ckey.lower()
+
+ singletargetmap = None
+ if len(sys.argv) > 3:
+ singletargetmap = sys.argv[3]
+ if singletargetmap is not None:
+ singletargetmap = singletargetmap.lower()
+
# Work out what maps we actually need to replicate to.
# This should be updated as map directories change, or the script will break.
targetmaps = []
@@ -40,7 +52,7 @@ def main():
if os.path.isdir(dir):
targetmap = dir.path
targetmap = targetmap.replace(mapdir + os.sep, "")
- if targetmap not in ignoremaps and targetmap != mapname:
+ if (targetmap not in ignoremaps) and (targetmap != mapname) and ((singletargetmap is None) or (singletargetmap == targetmap)):
targetmaps.append(targetmap)
# Make sure we can actually see the save directory.
@@ -62,6 +74,8 @@ def main():
continue
if match.group(1) != mapname:
continue
+ if (ckey is not None) and (ckey != root[root.rfind("/")+1:]):
+ continue
savefile = os.path.join(root, file)
with open(savefile, "r") as loadedsave:
wrote = 0
diff --git a/~code/global_init.dm b/~code/global_init.dm
index 82950bb246d..c483e8f9e8b 100644
--- a/~code/global_init.dm
+++ b/~code/global_init.dm
@@ -11,15 +11,14 @@
Pre-map initialization stuff should go here.
*/
-var/global_init = new /datum/global_init()
+var/global/global_init = new /datum/global_init()
/datum/global_init/New()
SSconfiguration.load_all_configuration()
generate_game_id()
makeDatumRefLists()
- qdel(src) //we're done
+ QDEL_IN(src, 0) //we're done. give it some time to finish setting up though
/datum/global_init/Destroy()
- global_init = null
- ..()
- return QDEL_HINT_HARDDEL
+ global.global_init = null
+ return ..()
|