diff --git a/citadel.dme b/citadel.dme
index 8bfc4bba8e6d..7e694404da5c 100644
--- a/citadel.dme
+++ b/citadel.dme
@@ -291,6 +291,7 @@
#include "code\__DEFINES\mobs\silicon_privileges.dm"
#include "code\__DEFINES\mobs\sprite_accessories.dm"
#include "code\__DEFINES\mobs\stat.dm"
+#include "code\__DEFINES\mobs\target_zone.dm"
#include "code\__DEFINES\mobs\wounds.dm"
#include "code\__DEFINES\objects\objects.dm"
#include "code\__DEFINES\objects\type_generation.dm"
@@ -542,7 +543,7 @@
#include "code\controllers\configuration\entries\urls.dm"
#include "code\controllers\configuration_old\configuration.dm"
#include "code\controllers\configuration_old\configuration_vr.dm"
-#include "code\controllers\observer_listener\atom\observer.dm"
+#include "code\controllers\repository\biologies.dm"
#include "code\controllers\repository\designs.dm"
#include "code\controllers\repository\flooring.dm"
#include "code\controllers\repository\guidebook.dm"
@@ -790,7 +791,6 @@
#include "code\datums\components\_component.dm"
#include "code\datums\components\anti_magic.dm"
#include "code\datums\components\connect_loc_behalf.dm"
-#include "code\datums\components\cyberpsychosis.dm"
#include "code\datums\components\gps_signal.dm"
#include "code\datums\components\horror_aura.dm"
#include "code\datums\components\jousting.dm"
@@ -2059,6 +2059,7 @@
#include "code\game\rendering\legacy\rigmech.dm"
#include "code\game\rendering\legacy\robot.dm"
#include "code\game\rendering\legacy\spell_screen_objects.dm"
+#include "code\game\rendering\legacy\zone_sel.dm"
#include "code\game\rendering\legacy\intents\throwing.dm"
#include "code\game\rendering\legacy\objects\waypoint_tracker.dm"
#include "code\game\rendering\parallax\parallax.dm"
@@ -2477,6 +2478,21 @@
#include "code\modules\awaymissions\pamphlet.dm"
#include "code\modules\awaymissions\trigger.dm"
#include "code\modules\awaymissions\zlevel.dm"
+#include "code\modules\biology\biology.dm"
+#include "code\modules\biology\biology_mob_state.dm"
+#include "code\modules\biology\biology_organ_state.dm"
+#include "code\modules\biology\types\crystalline.dm"
+#include "code\modules\biology\types\organic.dm"
+#include "code\modules\biology\types\simple.dm"
+#include "code\modules\biology\types\synthetic.dm"
+#include "code\modules\biology\types\organic\chimeric.dm"
+#include "code\modules\biology\types\organic\diona.dm"
+#include "code\modules\biology\types\organic\phoronoid.dm"
+#include "code\modules\biology\types\organic\plant.dm"
+#include "code\modules\biology\types\organic\promethean.dm"
+#include "code\modules\biology\types\organic\replicant.dm"
+#include "code\modules\biology\types\organic\xenomorph.dm"
+#include "code\modules\biology\types\synthetic\nanoswarm.dm"
#include "code\modules\blob2\_defines.dm"
#include "code\modules\blob2\announcement.dm"
#include "code\modules\blob2\blobs\base_blob.dm"
@@ -3609,7 +3625,6 @@
#include "code\modules\mob\mobility.dm"
#include "code\modules\mob\movement.dm"
#include "code\modules\mob\perspective.dm"
-#include "code\modules\mob\physiology.dm"
#include "code\modules\mob\pulling.dm"
#include "code\modules\mob\say.dm"
#include "code\modules\mob\say_vr.dm"
@@ -3684,6 +3699,7 @@
#include "code\modules\mob\living\living-defense-legacy.dm"
#include "code\modules\mob\living\living-defense.dm"
#include "code\modules\mob\living\living-inventory.dm"
+#include "code\modules\mob\living\living-physiology.dm"
#include "code\modules\mob\living\living.dm"
#include "code\modules\mob\living\living_defines.dm"
#include "code\modules\mob\living\living_powers.dm"
@@ -3693,7 +3709,6 @@
#include "code\modules\mob\living\mobility.dm"
#include "code\modules\mob\living\movement.dm"
#include "code\modules\mob\living\offense.dm"
-#include "code\modules\mob\living\organs.dm"
#include "code\modules\mob\living\resist.dm"
#include "code\modules\mob\living\say.dm"
#include "code\modules\mob\living\status_procs.dm"
@@ -3713,8 +3728,11 @@
#include "code\modules\mob\living\bot\secbot.dm"
#include "code\modules\mob\living\bot\SLed209bot.dm"
#include "code\modules\mob\living\carbon\breathe.dm"
+#include "code\modules\mob\living\carbon\carbon-death.dm"
#include "code\modules\mob\living\carbon\carbon-defense.dm"
#include "code\modules\mob\living\carbon\carbon-hands.dm"
+#include "code\modules\mob\living\carbon\carbon-life.dm"
+#include "code\modules\mob\living\carbon\carbon-organs.dm"
#include "code\modules\mob\living\carbon\carbon.dm"
#include "code\modules\mob\living\carbon\carbon_defense.dm"
#include "code\modules\mob\living\carbon\carbon_defines.dm"
@@ -3725,8 +3743,6 @@
#include "code\modules\mob\living\carbon\give.dm"
#include "code\modules\mob\living\carbon\health.dm"
#include "code\modules\mob\living\carbon\inventory.dm"
-#include "code\modules\mob\living\carbon\life.dm"
-#include "code\modules\mob\living\carbon\organs.dm"
#include "code\modules\mob\living\carbon\perspective.dm"
#include "code\modules\mob\living\carbon\physiology.dm"
#include "code\modules\mob\living\carbon\rendering.dm"
@@ -3773,6 +3789,8 @@
#include "code\modules\mob\living\carbon\human\human-damage.dm"
#include "code\modules\mob\living\carbon\human\human-defense-legacy.dm"
#include "code\modules\mob\living\carbon\human\human-defense.dm"
+#include "code\modules\mob\living\carbon\human\human-life-legacy.dm"
+#include "code\modules\mob\living\carbon\human\human-login-legacy.dm"
#include "code\modules\mob\living\carbon\human\human.dm"
#include "code\modules\mob\living\carbon\human\human_attackhand.dm"
#include "code\modules\mob\living\carbon\human\human_defines.dm"
@@ -3783,10 +3801,6 @@
#include "code\modules\mob\living\carbon\human\human_resist.dm"
#include "code\modules\mob\living\carbon\human\human_species.dm"
#include "code\modules\mob\living\carbon\human\inventory.dm"
-#include "code\modules\mob\living\carbon\human\inventory_legacy.dm"
-#include "code\modules\mob\living\carbon\human\life.dm"
-#include "code\modules\mob\living\carbon\human\login.dm"
-#include "code\modules\mob\living\carbon\human\logout.dm"
#include "code\modules\mob\living\carbon\human\MedicalSideEffects.dm"
#include "code\modules\mob\living\carbon\human\mobility.dm"
#include "code\modules\mob\living\carbon\human\movement.dm"
@@ -3811,6 +3825,9 @@
#include "code\modules\mob\living\carbon\human\traits\trait_groups.dm"
#include "code\modules\mob\living\carbon\human\traits\weaver_objs.dm"
#include "code\modules\mob\living\carbon\human\traits\weaver_recipies.dm"
+#include "code\modules\mob\living\physiology\global_physiology.dm"
+#include "code\modules\mob\living\physiology\local_physiology.dm"
+#include "code\modules\mob\living\physiology\physiology_modifier.dm"
#include "code\modules\mob\living\silicon\damage_procs.dm"
#include "code\modules\mob\living\silicon\death.dm"
#include "code\modules\mob\living\silicon\emote.dm"
@@ -4248,7 +4265,14 @@
#include "code\modules\nifsoft\software\13_soulcatcher.dm"
#include "code\modules\nifsoft\software\14_commlink.dm"
#include "code\modules\nifsoft\software\15_misc.dm"
+#include "code\modules\organs\organ-legacy-damage.dm"
+#include "code\modules\organs\organ-legacy-eating.dm"
+#include "code\modules\organs\organ-legacy-health.dm"
+#include "code\modules\organs\organ-legacy.dm"
+#include "code\modules\organs\organ-mappings.dm"
+#include "code\modules\organs\organ-tick.dm"
#include "code\modules\organs\organ.dm"
+#include "code\modules\organs\external\external-wound.dm"
#include "code\modules\organs\external\external.dm"
#include "code\modules\organs\external\external_icons.dm"
#include "code\modules\organs\external\robolimbs.dm"
@@ -4256,14 +4280,21 @@
#include "code\modules\organs\external\species\adherent.dm"
#include "code\modules\organs\external\species\alraune.dm"
#include "code\modules\organs\external\species\diona.dm"
+#include "code\modules\organs\external\species\naramadi.dm"
#include "code\modules\organs\external\species\shadekin.dm"
#include "code\modules\organs\external\species\skrell.dm"
#include "code\modules\organs\external\species\slime.dm"
#include "code\modules\organs\external\species\teshari.dm"
#include "code\modules\organs\external\species\unathi.dm"
+#include "code\modules\organs\external\species\werebeast.dm"
#include "code\modules\organs\external\species\xenos.dm"
-#include "code\modules\organs\external\subtypes\standard.dm"
-#include "code\modules\organs\external\subtypes\standard_vr.dm"
+#include "code\modules\organs\external\subtypes\standard-arm.dm"
+#include "code\modules\organs\external\subtypes\standard-chest.dm"
+#include "code\modules\organs\external\subtypes\standard-foot.dm"
+#include "code\modules\organs\external\subtypes\standard-groin.dm"
+#include "code\modules\organs\external\subtypes\standard-hand.dm"
+#include "code\modules\organs\external\subtypes\standard-head.dm"
+#include "code\modules\organs\external\subtypes\standard-leg.dm"
#include "code\modules\organs\external\subtypes\stump.dm"
#include "code\modules\organs\external\wounds\amputation.dm"
#include "code\modules\organs\external\wounds\brute.dm"
@@ -4280,7 +4311,6 @@
#include "code\modules\organs\internal\species\alraune.dm"
#include "code\modules\organs\internal\species\diona.dm"
#include "code\modules\organs\internal\species\replicant.dm"
-#include "code\modules\organs\internal\species\shadekin.dm"
#include "code\modules\organs\internal\species\slime.dm"
#include "code\modules\organs\internal\species\subspecies_graver.dm"
#include "code\modules\organs\internal\species\subspecies_spacer.dm"
@@ -4848,6 +4878,7 @@
#include "code\modules\species\species_getters.dm"
#include "code\modules\species\species_helpers.dm"
#include "code\modules\species\species_hud.dm"
+#include "code\modules\species\species_organ_entry.dm"
#include "code\modules\species\species_shapeshift.dm"
#include "code\modules\species\outsider\celestials.dm"
#include "code\modules\species\outsider\replicant.dm"
@@ -4861,6 +4892,7 @@
#include "code\modules\species\protean\protean_blob.dm"
#include "code\modules\species\protean\protean_powers.dm"
#include "code\modules\species\shadekin\blackeyed.dm"
+#include "code\modules\species\shadekin\shadekin-organs.dm"
#include "code\modules\species\shadekin\shadekin.dm"
#include "code\modules\species\shadekin\shadekin_abilities.dm"
#include "code\modules\species\shadekin\shadekin_hud.dm"
diff --git a/code/__DEFINES/controllers/spatial_grids.dm b/code/__DEFINES/controllers/spatial_grids.dm
index 1f048e243a91..1f9759e361f6 100644
--- a/code/__DEFINES/controllers/spatial_grids.dm
+++ b/code/__DEFINES/controllers/spatial_grids.dm
@@ -12,6 +12,7 @@
* todo: /atom/movable/recover_spatial_grid(), macro should have components remade using that.
*/
#define TYPE_REGISTER_SPATIAL_GRID(TYPEPATH, GRID) \
+##TYPEPATH{} \
##TYPEPATH/Initialize(...) { \
. = ..(); \
if(. == INITIALIZE_HINT_QDEL) { \
diff --git a/code/__DEFINES/mobs/biology.dm b/code/__DEFINES/mobs/biology.dm
index 8e13326318b4..62bbe0a8c834 100644
--- a/code/__DEFINES/mobs/biology.dm
+++ b/code/__DEFINES/mobs/biology.dm
@@ -1,7 +1,7 @@
//* This file is explicitly licensed under the MIT license. *//
-//* Copyright (c) 2024 silicons *//
+//* Copyright (c) 2024 Citadel Station Developers *//
-//* biology flags
+//* biology flags *//
/// humanlike, organic, normal biology
#define BIOLOGY_TYPE_HUMAN (1<<0)
@@ -13,12 +13,14 @@
#define BIOLOGY_TYPE_CHIMERA (1<<3)
/// protean
#define BIOLOGY_TYPE_NANITES (1<<4)
+/// diona (legally not plant)
+#define BIOLOGY_TYPE_DIONA (1<<5)
/// plant
-#define BIOLOGY_TYPE_PLANT (1<<5)
+#define BIOLOGY_TYPE_PLANT (1<<6)
/// crystalline (adherent)
-#define BIOLOGY_TYPE_CRYSTALLINE (1<<6)
+#define BIOLOGY_TYPE_CRYSTALLINE (1<<7)
-#define BIOLOGY_TYPES_FLESHY (BIOLOGY_TYPE_HUMAN | BIOLOGY_TYPE_CHIMERA | BIOLOGY_TYPE_PLANT | BIOLOGY_TYPE_SLIME)
+#define BIOLOGY_TYPES_FLESHY (BIOLOGY_TYPE_HUMAN | BIOLOGY_TYPE_CHIMERA | BIOLOGY_TYPE_PLANT | BIOLOGY_TYPE_DIONA| BIOLOGY_TYPE_SLIME)
#define BIOLOGY_TYPES_SYNTHETIC (BIOLOGY_TYPE_SYNTH | BIOLOGY_TYPE_NANITES)
#define BIOLOGY_TYPES_ALL (ALL)
diff --git a/code/__DEFINES/mobs/life.dm b/code/__DEFINES/mobs/life.dm
index 8339578956fa..4a4997704448 100644
--- a/code/__DEFINES/mobs/life.dm
+++ b/code/__DEFINES/mobs/life.dm
@@ -1,17 +1,38 @@
//* This file is explicitly licensed under the MIT license. *//
-//* Copyright (c) 2023 Citadel Station developers. *//
+//* Copyright (c) 2023 Citadel Station Developers *//
//* This file is called 'life', but realistically is the resting place of all things metabolism, health, and related. *//
-//? Health - Core
-/** Round damage values to this value
+//* Health / Damage Simulation *//
+
+/**
+ * Round damage values to this value
* Atom damage uses this too!
*/
#define DAMAGE_PRECISION 0.01
+/**
+ * Round damage tier values to this value
+ * Atom damage uses this too!
+ */
#define DAMAGE_TIER_PRECISION 0.01
+/**
+ * Round armor values to this value
+ * Atom damage uses this too!
+ */
#define ARMOR_PRECISION 0.001
+/**
+ * Round armor tier values to this value
+ * Atom damage uses this too!
+ */
#define ARMOR_TIER_PRECISION 0.01
+//* Life Ticking *//
+
+/// Should tick physical processes
+#define LIFE_TICK_PHYSICAL (1<<0)
+/// Should tick biological processes
+#define LIFE_TICK_BIOLOGICAL (1<<1)
+
//* Health - Environmental Interactions *//
/// % of temperature recovered when going towards favorable
diff --git a/code/__DEFINES/mobs/organs.dm b/code/__DEFINES/mobs/organs.dm
index 259494f92fa9..c69717bd1e5a 100644
--- a/code/__DEFINES/mobs/organs.dm
+++ b/code/__DEFINES/mobs/organs.dm
@@ -1,4 +1,103 @@
-//! *ALL DEFINES RELATED TO ORGANS GO HERE* !//
+//* Organ Flags *//
+
+/// This organ is abstract.
+///
+/// * Do not allow adding / removing by players.
+/// * Do not allow players to interact with it by any means, including by scanning it.
+#define ORGAN_FLAG_ABSTRACT (1<<0)
+#warn impl
+
+#warn DEFINE_BITFIELD
+
+//* Organ Discovery Flags *//
+
+/// Does not show up on simple scanners like cyborg analyzers.
+#define ORGAN_DISCOVERY_NO_SIMPLE_SCAN (1<<0)
+/// Does not show up on advanced imaging like body scanners.
+#define ORGAN_DISCOVERY_NO_ADVANCED_SCAN (1<<1)
+#warn impl
+
+#warn DEFINE_BITFIELD
+
+//* Organ Keys *//
+//* Organ keys are strings used to key the 'keyed_organs' list on carbons. *//
+//* *//
+//* While usually arbitrary for an organ, they do have attached connotations of *//
+//* what the organ will be casted to when fetched. As an example, ORGAN_KEY_BRAIN *//
+//* will always be an organ of /obj/item/organ/internal/brain type. *//
+//* *//
+//* Organ keys should always be annotated in the below list with their expected type. *//
+
+//* Bodyparts *//
+
+#warn tag all the ext organs these describe!!!!
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_HEAD "head"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_CHEST "chest"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_LEFT_ARM "left_arm"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_LEFT_HAND "left_hand"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_RIGHT_ARM "right_arm"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_RIGHT_HAND "right_hand"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_GROIN "groin"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_LEFT_LEG "left_leg"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_LEFT_FOOT "left_foot"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_RIGHT_LEG "right_leg"
+/// External organ key for standard set.
+/// * Type: /obj/item/organ/external
+#define ORGAN_KEY_EXT_RIGHT_FOOT "right_foot"
+
+//* Common *//
+
+/// The key for brain organs.
+/// * Type: /obj/item/organ/internal/brain
+#define ORGAN_KEY_BRAIN "brain"
+/// The key for lung organs.
+/// * Type: /obj/item/organ/internal/lungs
+#define ORGAN_KEY_LUNGS "lungs"
+/// The key for eye organs.
+/// * Type: /obj/item/organ/internal/eyes
+#define ORGAN_KEY_EYES "eyes"
+
+//* Species - Shadekin *//
+
+/// The key for shadekin dimensional nodes
+/// * Type: /obj/item/organ/internal/shadekin/dimensional_cluster
+#define ORGAN_KEY_SHADEKIN_DIMENSIONAL_CLUSTER "shadekin-dimensional-cluster"
+
+//* Species - Xenomorph *//
+
+/// The key for xenomorph plasma vessels.
+/// * Type: /obj/item/organ/internal/xenomorph/plasmavessel
+#define ORGAN_KEY_XENOMORPH_PLASMA_VESSEL "xeno-plasma-vessel"
+
+#warn hook / implement
+
+//* Organ Default Lists *//
+//* Used in lists to overrule a host biology's default organ lists. *//
+
+/// Omit this organ.
+#define ORGAN_DEFAULT_OMIT "omit"
+
+//! legacy below !//
//These control the damage thresholds for the various ways of removing limbs
#define DROPLIMB_THRESHOLD_EDGE 5
diff --git a/code/__DEFINES/mobs/target_zone.dm b/code/__DEFINES/mobs/target_zone.dm
new file mode 100644
index 000000000000..aa2834b60868
--- /dev/null
+++ b/code/__DEFINES/mobs/target_zone.dm
@@ -0,0 +1,36 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * This file contains targeting zones for the zone selector doll.
+ */
+
+#define TARGET_ZONE_HEAD "head"
+#define TARGET_ZONE_EYES "eyes"
+#define TARGET_ZONE_MOUTH "mouth"
+#define TARGET_ZONE_TORSO "torso"
+#define TARGET_ZONE_LEFT_ARM "l_arm"
+#define TARGET_ZONE_LEFT_HAND "l_hand"
+#define TARGET_ZONE_RIGHT_ARM "r_arm"
+#define TARGET_ZONE_RIGHT_HAND "r_hand"
+#define TARGET_ZONE_GROIN "groin"
+#define TARGET_ZONE_LEFT_LEG "l_leg"
+#define TARGET_ZONE_LEFT_FOOT "l_foot"
+#define TARGET_ZONE_RIGHT_LEG "r_leg"
+#define TARGET_ZONE_RIGHT_FOOT "r_foot"
+
+GLOBAL_REAL_LIST(all_target_zones) = list(
+ TARGET_ZONE_HEAD,
+ TARGET_ZONE_EYES,
+ TARGET_ZONE_MOUTH,
+ TARGET_ZONE_TORSO,
+ TARGET_ZONE_LEFT_ARM,
+ TARGET_ZONE_LEFT_HAND,
+ TARGET_ZONE_RIGHT_ARM,
+ TARGET_ZONE_RIGHT_HAND,
+ TARGET_ZONE_GROIN,
+ TARGET_ZONE_LEFT_LEG,
+ TARGET_ZONE_LEFT_FOOT,
+ TARGET_ZONE_RIGHT_LEG,
+ TARGET_ZONE_RIGHT_FOOT,
+)
diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm
index e31d3a0b9884..19b75258c73e 100644
--- a/code/__DEFINES/qdel.dm
+++ b/code/__DEFINES/qdel.dm
@@ -10,6 +10,8 @@
///qdel should assume this object won't gc, and queue a hard delete using a hard reference.
#define QDEL_HINT_HARDDEL 3
///qdel should assume this object won't gc, and hard del it post haste.
+///
+/// * This directly routes to native `del`. This hint shouldn't be used 99.9999% of the time.
#define QDEL_HINT_HARDDEL_NOW 4
//defines for the gc_destroyed var
diff --git a/code/__DEFINES/spans.dm b/code/__DEFINES/spans.dm
index 9874f5439968..a0fc70c7d025 100644
--- a/code/__DEFINES/spans.dm
+++ b/code/__DEFINES/spans.dm
@@ -1,3 +1,8 @@
+//* Spans *//
+//* These are standard 's allowed within saycode or other chat output contexts. *//
+//* Using them within TGUI interfaces driectly is generally discouraged *//
+//* as there's no guarantee that the spans are included in all TGUI CSS. *//
+
/**
* Standard Spans
* Sorted alphabetically
diff --git a/code/controllers/observer_listener/atom/observer.dm b/code/controllers/observer_listener/atom/observer.dm
deleted file mode 100644
index b26dcc131679..000000000000
--- a/code/controllers/observer_listener/atom/observer.dm
+++ /dev/null
@@ -1,26 +0,0 @@
-#define OBSERVER_EVENT_DESTROY "OnDestroy"
-
-/atom
- var/list/observer_events
-
-/atom/Destroy()
- for(var/list/listeners in observer_events)
- listeners.Cut()
-
- return ..()
-
-/atom/proc/register(var/event, var/procOwner, var/proc_call)
- var/list/listeners = get_listener_list_from_event(event)
- listeners[procOwner] = proc_call
-
-/atom/proc/unregister(var/event, var/procOwner)
- var/list/listeners = get_listener_list_from_event(event)
- listeners -= procOwner
-
-/atom/proc/get_listener_list_from_event(var/observer_event)
- if(!observer_events) observer_events = list()
- var/list/listeners = observer_events[observer_event]
- if(!listeners)
- listeners = list()
- observer_events[observer_event] = listeners
- return listeners
diff --git a/code/controllers/repository/biologies.dm b/code/controllers/repository/biologies.dm
new file mode 100644
index 000000000000..7167b48c14e7
--- /dev/null
+++ b/code/controllers/repository/biologies.dm
@@ -0,0 +1,6 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+REPOSITORY_DEF(biologies)
+ name = "Repository - Biologies"
+ expected_type = /datum/prototype/biology
diff --git a/code/controllers/subsystem/job/_legacy_job_stuff.dm b/code/controllers/subsystem/job/_legacy_job_stuff.dm
index 4b3dd3343312..03879b3d4688 100644
--- a/code/controllers/subsystem/job/_legacy_job_stuff.dm
+++ b/code/controllers/subsystem/job/_legacy_job_stuff.dm
@@ -329,8 +329,8 @@
captain_announcement.Announce("All hands, [alt_title ? alt_title : "Facility Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
if(istype(H)) //give humans wheelchairs, if they need them.
- var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
- var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
+ var/obj/item/organ/external/l_foot = H.legacy_organ_by_zone("l_foot")
+ var/obj/item/organ/external/r_foot = H.legacy_organ_by_zone("r_foot")
var/obj/item/storage/S = locate() in H.contents
var/obj/item/wheelchair/R
if(S)
diff --git a/code/datums/components/cyberpsychosis.dm b/code/datums/components/cyberpsychosis.dm
deleted file mode 100644
index 50ec7ae7fc01..000000000000
--- a/code/datums/components/cyberpsychosis.dm
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
-Following a resurgence in interest regarding cybernetics, augments, and general Cyberpunk themes, I was asked if I could make Cyberpsychosis viable.
-This is an attempt at that. It isn't intended to produce any serious long-term effects, so much as provide some internal feedback to Role-Play off of.
-Initial Design Goals (X = Complete, / = WIP):
-[X]Occasional visual glitching, similar to hallucinations, but less pervasive.
-[X]Occasional audio glitching, as above.
-[X]Messages posted in the user's chat randomly. (Snippets of memories, visual glitching descriptions, intrusive thoughts, etc.)
-[X]The creation of a specialized drug that can reduce the above symptoms when ingested.
-[X]Related to the drug, some form of temporarily extending the time between symptom firing while the chem is in-system.
-[X]Some form of system that calculates "instability" based off of prosthetics, augments, and implants at spawn, that also increases when more are added.
-*/
-
-/datum/component/cyberpsychosis
- var/capacity = 100
- var/cybernetics_count = 0
- var/counted = 0
- var/adjusted = 0
- var/medicated = 0
- var/symptom_delay = 3000
- var/last_symptom = 0
-
-/datum/component/cyberpsychosis/Initialize(radius)
- if(!istype(parent))
- return COMPONENT_INCOMPATIBLE
- else
- START_PROCESSING(SSobj, src)
-
-/datum/component/cyberpsychosis/process()
- count_cybernetics()
- update_capacity()
- update_medication()
- process_symptoms()
-
-//This proc will tabulate the number of prosthetic limbs, organs, augments, and implants into a number.
-/datum/component/cyberpsychosis/proc/count_cybernetics()
- var/mob/living/carbon/human/H = parent
- . = 0
- if(counted)
- return
- else
- for(var/obj/item/organ/O in H.organs)
- if(O.robotic >= ORGAN_ROBOT)
- cybernetics_count++
- counted = 1
-
-//This subtracts the above sum from var/capacity, which is set to 100 by default.
-/datum/component/cyberpsychosis/proc/update_capacity()
- if(adjusted)
- return
- if(!adjusted && cybernetics_count >= 1)
- capacity -= cybernetics_count*5
- adjusted = 1
-
-/datum/component/cyberpsychosis/proc/update_medication()
- var/mob/living/carbon/human/H = parent
- if(!medicated && H.reagents.has_reagent("neuratrextate", 1))
- medicated = 1
- if(medicated && !H.reagents.has_reagent("neuratrextate", 1))
- medicated = 0
-
-//Dynamically changing the Capacity of a cyberware user isn't really working out.
-//So instead I think we can just flag them as medicated, and use that as a check in rendering symptoms.
-//This proc will provide different symptoms, with the frequency inversely related to the value of capacity.
-//This is basically the one that all the above checkboxes will address.
-
-/datum/component/cyberpsychosis/proc/process_symptoms()
- if(medicated)
- return
- if(world.time > last_symptom + symptom_delay)
- fire_symptoms()
- last_symptom = world.time
-
-/datum/component/cyberpsychosis/proc/fire_symptoms()
- var/mob/living/carbon/human/H = parent
- if(capacity <= 95) //This level is benign in terms of capacity loss. Don't want to just dump symptoms on them on the daily.
- var/message_t1 = rand(1,6)
- switch(message_t1)
- if(1)
- to_chat(H, "The skin around your implants itches.")
- if(2)
- to_chat(H, "You feel momentary pressure behind your eyes.")
- if(3)
- to_chat(H, "Your tongue feels too big.")
- if(4)
- to_chat(H, "You hear someone whispering nearby.")
- if(5)
- to_chat(H, "There is a stinging pain in your scalp.")
- if(6)
- to_chat(H, "For a brief moment you nearly remember the scent of your mother's perfume.")
- else if(capacity < 90) //At this level, we just want snippets of memories and audible hallucinations.
- var/message_t2 = rand(1,8)
- var/audio_t1 = rand(1,8)
- var/select_symptom = rand(1,2)
- switch(select_symptom)
- if(1)
- switch(message_t2)
- if(1)
- to_chat(H, "You catch a whiff of your favorite food.")
- if(2)
- to_chat(H, "The sound of your childhood home in Summer rings in your ears for a split second.")
- if(3)
- to_chat(H, "You remember the temperature of your oldest bedroom.")
- if(4)
- to_chat(H, "The eyes of your first friend stare curiously up at you.")
- if(5)
- to_chat(H, "Someone familiar calls your first name.")
- if(6)
- to_chat(H, "You came here once, on a school trip.")
- if(7)
- to_chat(H, "Didn't I tell you not to come back?")
- if(8)
- to_chat(H, "The walls seem to bubble at the corners of your vision.")
- if(2)
- switch(audio_t1)
- if(1)
- SEND_SOUND(src, sound('sound/machines/airlock.ogg'))
- if(2)
- if(prob(50))
- SEND_SOUND(src, sound('sound/soundbytes/effects/explosion/explosion1.ogg'))
- else
- SEND_SOUND(src, sound('sound/soundbytes/effects/explosion/explosion2.ogg'))
- if(3)
- SEND_SOUND(src, sound('sound/soundbytes/effects/explosion/explosionfar.ogg'))
- if(4)
- SEND_SOUND(src, sound('sound/effects/Glassbr1.ogg'))
- if(5)
- SEND_SOUND(src, sound('sound/effects/Glassbr2.ogg'))
- if(6)
- SEND_SOUND(src, sound('sound/effects/Glassbr3.ogg'))
- if(7)
- SEND_SOUND(src, sound('sound/machines/twobeep.ogg'))
- if(8)
- SEND_SOUND(src, sound('sound/machines/windowdoor.ogg'))
- else if(capacity < 70) //At this level, the user starts to get snippets and messages reminding them of past memories. If this is coded right, they cascade down to the bottom.
- var/message_t3 = rand(1,8)
- switch(message_t3)
- if(1)
- to_chat(H, "You can remember how they all stared at you.")
- if(2)
- to_chat(H, "The stinging pain of your biggest regret spreads deep into your chest.")
- if(3)
- to_chat(H, "Someone is watching you.")
- if(4)
- to_chat(H, "The memory of their screaming is as strong as when you were actually there.")
- if(5)
- to_chat(H, "Who are you?")
- if(6)
- to_chat(H, "Wind whips by your face as you stare blankly out at the horizon. You feel alone.")
- if(7)
- to_chat(H, "You look down at your hands. Weren't you going to make it big? What happened?")
- if(8)
- to_chat(H, "You are having trouble breathing. Oh God. You're drowning.")
- else if(capacity < 40) //At this level, the victim begins to have more pronounced visual hallucinations, on top of the stacking symptoms above.
- var/message_t4 = rand(1,2)
- switch(message_t4)
- if(1)
- to_chat(H, "Visual pixel artifacting crackles into the air before you. Just as quickly as it appears, it's gone.")
- if(2)
- to_chat(H, "The ground suddenly falls out from under you, smearing into neon vertex lines on a skewed Z-Axis.")
- else if(capacity < 20) //The user's condition is rapidly degrading. More aggressive and intrusive messages come into play. Paranoia and aggravation increases.
- var/message_t5 = rand(1,7)
- switch(message_t5)
- if(1)
- to_chat(H, "You should rip out your implants.")
- if(2)
- to_chat(H, "I know what you did.")
- if(3)
- to_chat(H, "Security is already on its way.")
- if(4)
- to_chat(H, "They're going to find it. Then you're fucked.")
- if(5)
- to_chat(H, "Kill them all. It's the only way to be safe.")
- if(6)
- to_chat(H, "KILLKILLKILLKILLKILLKILL")
- if(7)
- to_chat(H, "The screeching pain of your cybernetics is unending. It drowns you.")
- if(8) //Cruelty Squad direct quote here. Bit of an easter egg.
- to_chat(H, "A point in the horizon, a melting scene from your childhood. Your mortality is showing. A frantic drift towards nothing, biology doomed to an infinite recursive loop. Teeth with teeth with teeth. Take a bite. Serene scent of a coastal town, warmth of the sun. Bitter tears. Lust for power. This is where you abandoned your dreams. You are a high net worth individual, an expanding vortex of pathetic trauma. Finally a beautiful fucking nerve ape. A pure soul is born, its neurotransactions stutter into being. 30583750937509353 operations per nanosecond. Beauty eludes your porous mind.")
- if(9)
- to_chat(H, "An image of a fractal parrot renders over your vision. Something about it draws you in, crushing, spinning. A black hole. Glory unending. You taste meat between your synapses. You cannot think. You are falling into the Parrot.")
- else if(capacity < 10) //This is the most critical level. On top of stacking everything above, this should be pretty critical in some way.
- var/modifier_to_add = /datum/modifier/berserk
- var/berserk_length = 30 SECONDS
- H.add_modifier(modifier_to_add * berserk_length)
- return
-
-/datum/component/cyberpsychosis/Destroy()
- STOP_PROCESSING(SSobj, src)
- return ..()
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index e6d8793f5fad..fb4f07c633dd 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -305,17 +305,26 @@
//* Serialization *//
/**
- * serializes us to a list
- * note that *everything* will be trampled down to a number or text.
- * do not store raw types.
+ * Serializes into a list.
*
- * do not serialize type with this; type should always be stored externally from data.
+ * Requirements:
+ * * Do not serialize our type with this. The caller handles type / prototype IDs.
+ * * Text and number are generally safe to serialize directly.
+ * * Lists are generally able to be serialized directly if it only consists of text and numbers.
+ * * Raw typepaths are generally **not** safe to serialize directly.
+ *
+ * Reference types:
+ * * Repositories: /datum/prototype's may be serialized by ID.
+ * * Others: Reference types outside of these must support serialize() to be serialized along with us,
+ * and should have their serialized data included..
+ *
+ * todo: comment about filestores (photography-like's)
*/
/datum/proc/serialize()
return list()
/**
- * deserializes from a list
+ * Deserializes from a list.
*
* @params
* * data - json_decode()'d list.
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 3dbeb041241a..2d8b065b44bf 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -421,7 +421,7 @@
switch(href_list["implant"])
if("remove")
for(var/obj/item/implant/loyalty/I in H.contents)
- for(var/obj/item/organ/external/organs in H.organs)
+ for(var/obj/item/organ/external/organs as anything in H.external_organs)
if(I in organs.implants)
qdel(I)
break
diff --git a/code/datums/unarmed_attack.dm b/code/datums/unarmed_attack.dm
index bf61721472c9..31709b025e5f 100644
--- a/code/datums/unarmed_attack.dm
+++ b/code/datums/unarmed_attack.dm
@@ -131,7 +131,7 @@ GLOBAL_LIST_EMPTY(unarmed_attack_cache)
if(user.species.infect_wounds) //Creates a pre-damaged, pre-infected wound. As nasty as this code.
if(prob(infected_wound_probability))
- var/obj/item/organ/external/affecting = target.get_organ(zone)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(zone)
var/attack_message
var/datum/wound/W
if(damage_mode & DAMAGE_MODE_EDGE)
@@ -145,12 +145,12 @@ GLOBAL_LIST_EMPTY(unarmed_attack_cache)
target.visible_message("[user] [attack_message]")
/datum/unarmed_attack/proc/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
- var/obj/item/organ/external/affecting = target.get_organ(zone)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(zone)
user.visible_message("[user] [pick(attack_verb_legacy)] [target] in the [affecting.name]!")
playsound(user.loc, attack_sound, 25, 1, -1)
/datum/unarmed_attack/proc/handle_eye_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target)
- var/obj/item/organ/internal/eyes/eyes = target.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/eyes = target.keyed_organs[ORGAN_KEY_EYES]
var/datum/gender/TU = GLOB.gender_datums[user.get_visible_gender()]
var/datum/gender/TT = GLOB.gender_datums[target.get_visible_gender()]
if(eyes)
@@ -191,7 +191,7 @@ GLOBAL_LIST_EMPTY(unarmed_attack_cache)
damage_tier = MELEE_TIER_UNARMED_FISTS
/datum/unarmed_attack/punch/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
- var/obj/item/organ/external/affecting = target.get_organ(zone)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(zone)
var/organ = affecting.name
var/datum/gender/TU = GLOB.gender_datums[user.get_visible_gender()]
@@ -247,15 +247,17 @@ GLOBAL_LIST_EMPTY(unarmed_attack_cache)
if (user.legcuffed)
return FALSE
- if(!(zone in list("l_leg", "r_leg", "l_foot", "r_foot", BP_GROIN)))
+ var/static/list/valid_zones = list(
+ TARGET_ZONE_LEFT_LEG,
+ TARGET_ZONE_LEFT_FOOT,
+ TARGET_ZONE_RIGHT_LEG,
+ TARGET_ZONE_RIGHT_FOOT,
+ TARGET_ZONE_GROIN,
+ )
+ if(!(zone in valid_zones))
return FALSE
- var/obj/item/organ/external/E = user.organs_by_name["l_foot"]
- if(E && !E.is_stump())
- return TRUE
-
- E = user.organs_by_name["r_foot"]
- if(E && !E.is_stump())
+ if(user.get_organ_for_zone(TARGET_ZONE_LEFT_FOOT) || user.get_organ_for_zone(TARGET_ZONE_RIGHT_FOOT))
return TRUE
return FALSE
@@ -267,7 +269,7 @@ GLOBAL_LIST_EMPTY(unarmed_attack_cache)
return damage + max(0, shoes ? shoes.damage_force - 5 : 0)
/datum/unarmed_attack/kick/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
- var/obj/item/organ/external/affecting = target.get_organ(zone)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(zone)
var/datum/gender/TT = GLOB.gender_datums[target.get_visible_gender()]
var/organ = affecting.name
@@ -312,7 +314,7 @@ GLOBAL_LIST_EMPTY(unarmed_attack_cache)
return damage + max(0, shoes ? shoes.damage_force - 5 : 0)
/datum/unarmed_attack/stomp/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
- var/obj/item/organ/external/affecting = target.get_organ(zone)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(zone)
var/organ = affecting.name
var/obj/item/clothing/shoes = user.shoes
var/datum/gender/TU = GLOB.gender_datums[user.get_visible_gender()]
diff --git a/code/game/antagonist/alien/borer.dm b/code/game/antagonist/alien/borer.dm
index ba99b34af99c..1a4714d4a045 100644
--- a/code/game/antagonist/alien/borer.dm
+++ b/code/game/antagonist/alien/borer.dm
@@ -45,12 +45,12 @@ var/datum/antagonist/borer/borers
var/mob/living/carbon/human/host
for(var/mob/living/carbon/human/H in GLOB.mob_list)
if(H.stat != DEAD && !H.has_brain_worms())
- var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/head = H.legacy_organ_by_zone(BP_HEAD)
if(head && !(head.robotic >= ORGAN_ROBOT))
host = H
break
if(istype(host))
- var/obj/item/organ/external/head = host.get_organ(BP_HEAD)
+ var/obj/item/organ/external/head = host.legacy_organ_by_zone(BP_HEAD)
borer.host = host
head.implants += borer
borer.forceMove(head)
diff --git a/code/game/atoms/_atom.dm b/code/game/atoms/_atom.dm
index e0d07548e9e3..f8be7b317206 100644
--- a/code/game/atoms/_atom.dm
+++ b/code/game/atoms/_atom.dm
@@ -206,7 +206,6 @@
* Top level of the destroy chain for most atoms
*
* Cleans up the following:
- * * Removes alternate apperances from huds that see them
* * qdels the reagent holder from atoms if it exists
* * clears the orbiters list
* * clears overlays and priority overlays
diff --git a/code/game/atoms/movable/movable.dm b/code/game/atoms/movable/movable.dm
index 9be084a15cc5..faf709582e11 100644
--- a/code/game/atoms/movable/movable.dm
+++ b/code/game/atoms/movable/movable.dm
@@ -213,10 +213,6 @@
unbuckle_all_mobs(BUCKLE_OP_FORCE)
for(var/atom/movable/AM in contents)
qdel(AM)
- /*
- if(loc)
- loc.handle_contents_del(src)
- */
var/turf/un_opaque
if(opacity && isturf(loc))
un_opaque = loc
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index 72c3d1f508ff..5ac562071eec 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -299,7 +299,7 @@ var/global/list/datum/gene/dna_genes[0]
body_markings.Cut()
- for(var/obj/item/organ/external/E in character.organs)
+ for(var/obj/item/organ/external/E as anything in character.external_organs)
E.s_base = s_base
if(E.markings.len)
body_markings[E.organ_tag] = E.markings.Copy()
diff --git a/code/game/gamemodes/changeling/powers/armblade.dm b/code/game/gamemodes/changeling/powers/armblade.dm
index 9946b4d9d0b9..f61b52a94498 100644
--- a/code/game/gamemodes/changeling/powers/armblade.dm
+++ b/code/game/gamemodes/changeling/powers/armblade.dm
@@ -109,7 +109,7 @@
if(istype(loc,/mob/living))
var/mob/living/carbon/human/host = loc
if(istype(host))
- for(var/obj/item/organ/external/organ in host.organs)
+ for(var/obj/item/organ/external/organ as anything in host.external_organs)
for(var/obj/item/O in organ.implants)
if(O == src)
organ.implants -= src
diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm
index 02235cdc910d..1628a86a4bfb 100644
--- a/code/game/gamemodes/changeling/powers/panacea.dm
+++ b/code/game/gamemodes/changeling/powers/panacea.dm
@@ -39,7 +39,7 @@
C.adjustToxLoss(-heal_amount)
sleep(10)
- for(var/obj/item/organ/external/E in C.organs)
+ for(var/obj/item/organ/external/E as anything in C.external_organs)
var/obj/item/organ/external/G = E
if(G.germ_level)
var/germ_heal = heal_amount * 100
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 4c5775b16454..6882ea55bf60 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -23,7 +23,7 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
- var/obj/item/organ/external/affecting = H.get_hand_organ(held_index)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(zone)
to_chat(user, "An inexplicable force rips through your [affecting.name], tearing the sword from your grasp!")
//random amount of damage between half of the blade's force and the full force of the blade.
H.apply_damage(rand(damage_force/2, damage_force), DAMAGE_TYPE_BRUTE, held_index % 2? BP_L_HAND : BP_R_HAND, 0, sharp=1, edge=1)
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 395c22d25dde..6ec1fc1fbaa7 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -280,8 +280,7 @@ var/list/sacrificed = list()
if(I.damage <= 5 && I.organ_tag == O_EYES)
H.remove_blindness_source(TRAIT_BLINDNESS_EYE_DMG)
// check their limbs
- for(var/obj/item/organ/E in H.bad_external_organs)
- var/obj/item/organ/external/affected = E
+ for(var/obj/item/organ/external/affected in H.external_organs)
// fix bones
if((affected.damage < affected.min_broken_damage) && (affected.status & ORGAN_BROKEN))
affected.status &= ~ORGAN_BROKEN
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index a40b745449c3..54ea3f331695 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -401,21 +401,21 @@ var/global/list/all_objectives = list()
return FALSE
var/mob/living/carbon/human/H = target.current
- for(var/obj/item/organ/external/E in H.organs)
+ for(var/obj/item/organ/external/E as anything in H.external_organs)
if(E.status & ORGAN_BROKEN)
return TRUE
for(var/limb_tag in H.species.has_limbs) //todo check prefs for robotic limbs and amputations.
var/list/organ_data = H.species.has_limbs[limb_tag]
var/limb_type = organ_data["path"]
var/found
- for(var/obj/item/organ/external/E in H.organs)
+ for(var/obj/item/organ/external/E as anything in H.external_organs)
if(limb_type == E.type)
found = 1
break
if(!found)
return TRUE
- var/obj/item/organ/external/head/head = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/head = H.legacy_organ_by_zone(BP_HEAD)
if(head.disfigured)
return TRUE
return FALSE
diff --git a/code/game/gamemodes/technomancer/instability.dm b/code/game/gamemodes/technomancer/instability.dm
index f39cb1a26bc6..4e1561e7a29f 100644
--- a/code/game/gamemodes/technomancer/instability.dm
+++ b/code/game/gamemodes/technomancer/instability.dm
@@ -48,11 +48,6 @@
if(100 to 200)
wiz_instability_display.icon_state = "instability3"
-/mob/living/PhysicalLife()
- if((. = ..()))
- return
- handle_instability()
-
// Proc: handle_instability()
// Parameters: 0
// Description: Makes instability decay. instability_effects() handles the bad effects for having instability. It will also hold back
diff --git a/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm b/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm
index 1896cc69ba95..bda5bbfac1a9 100644
--- a/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm
+++ b/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm
@@ -35,7 +35,7 @@
if(ishuman(L))
var/mob/living/carbon/human/H = L
- var/obj/item/organ/external/affected = H.get_organ(check_zone(BP_TORSO))
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(check_zone(BP_TORSO))
H.electrocute_act(power, src, H.get_siemens_coefficient_organ(affected), affected)
else
L.electrocute_act(power, src, 0.75, BP_TORSO)
diff --git a/code/game/gamemodes/technomancer/spells/energy_siphon.dm b/code/game/gamemodes/technomancer/spells/energy_siphon.dm
index b05bc7fb2670..0e70da06182b 100644
--- a/code/game/gamemodes/technomancer/spells/energy_siphon.dm
+++ b/code/game/gamemodes/technomancer/spells/energy_siphon.dm
@@ -183,7 +183,7 @@
return
if(ishuman(target_mob)) // Otherwise someone else stood in the beam and is going to pay for it.
var/mob/living/carbon/human/H = target_mob
- var/obj/item/organ/external/affected = H.get_organ(check_zone(BP_TORSO))
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(check_zone(BP_TORSO))
H.electrocute_act(power, src, H.get_siemens_coefficient_organ(affected), affected, 0)
else
target_mob.electrocute_act(power, src, 0.75, BP_TORSO)
diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_metal.dm b/code/game/gamemodes/technomancer/spells/insert/mend_metal.dm
index 53ab439df667..683749d1e6e0 100644
--- a/code/game/gamemodes/technomancer/spells/insert/mend_metal.dm
+++ b/code/game/gamemodes/technomancer/spells/insert/mend_metal.dm
@@ -25,7 +25,7 @@
origin.adjust_instability(10)
for(var/i = 0, i<5,i++)
if(H)
- for(var/obj/item/organ/external/O in H.organs)
+ for(var/obj/item/organ/external/O as anything in H.external_organs)
if(O.robotic < ORGAN_ROBOT) // Robot parts only.
continue
O.heal_damage(heal_power / 5, 0, internal = 1, robo_repair = 1)
diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm b/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm
index fe49d37195c4..4dd87f34b3ea 100644
--- a/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm
+++ b/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm
@@ -33,7 +33,7 @@
if(O.damage <= 5 && O.organ_tag == O_EYES) // Fix eyes
H.remove_blindness_source(TRAIT_BLINDNESS_EYE_DMG)
- for(var/obj/item/organ/external/O in H.organs) // Fix limbs
+ for(var/obj/item/organ/external/O as anything in H.external_organs) // Fix limbs
if(!O.robotic < ORGAN_ROBOT) // No robot parts for this.
continue
O.heal_damage(0, heal_power / 5, internal = 1, robo_repair = 0)
diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_wires.dm b/code/game/gamemodes/technomancer/spells/insert/mend_wires.dm
index 72585ef208fb..e36e18fcc988 100644
--- a/code/game/gamemodes/technomancer/spells/insert/mend_wires.dm
+++ b/code/game/gamemodes/technomancer/spells/insert/mend_wires.dm
@@ -25,7 +25,7 @@
origin.adjust_instability(10)
for(var/i = 0, i<5,i++)
if(H)
- for(var/obj/item/organ/external/O in H.organs)
+ for(var/obj/item/organ/external/O as anything in H.external_organs)
if(O.robotic < ORGAN_ROBOT) // Robot parts only.
continue
O.heal_damage(0, heal_power / 5, internal = 1, robo_repair = 1)
diff --git a/code/game/gamemodes/technomancer/spells/mend_organs.dm b/code/game/gamemodes/technomancer/spells/mend_organs.dm
index 9a2b38273361..3560dfb0b901 100644
--- a/code/game/gamemodes/technomancer/spells/mend_organs.dm
+++ b/code/game/gamemodes/technomancer/spells/mend_organs.dm
@@ -37,7 +37,7 @@
if(O.damage <= 5 && O.organ_tag == O_EYES) // Fix eyes
H.remove_blindness_source(TRAIT_BLINDNESS_EYE_DMG)
- for(var/obj/item/organ/external/O in H.organs) // Fix limbs
+ for(var/obj/item/organ/external/O as anything in H.external_organs) // Fix limbs
if(!O.robotic < ORGAN_ROBOT) // No robot parts for this.
continue
O.heal_damage(0, heal_power / 4, internal = 1, robo_repair = 0)
diff --git a/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm b/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm
index 29f7b747bd56..6b5afba9852b 100644
--- a/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm
+++ b/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm
@@ -34,7 +34,7 @@
return
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
- for(var/obj/item/organ/external/E in H.organs)
+ for(var/obj/item/organ/external/E as anything in H.external_organs)
var/obj/item/organ/external/O = E
if(O.robotic >= ORGAN_ROBOT)
O.heal_damage(4 * spell_power, 4 * spell_power, 0, 1)
diff --git a/code/game/gamemodes/technomancer/spells/projectile/chain_lightning.dm b/code/game/gamemodes/technomancer/spells/projectile/chain_lightning.dm
index 0a20eab1dbcd..cde6e55d0f19 100644
--- a/code/game/gamemodes/technomancer/spells/projectile/chain_lightning.dm
+++ b/code/game/gamemodes/technomancer/spells/projectile/chain_lightning.dm
@@ -46,7 +46,7 @@
//First we shock the guy we just hit.
if(ishuman(target_mob))
var/mob/living/carbon/human/H = target_mob
- var/obj/item/organ/external/affected = H.get_organ(check_zone(BP_TORSO))
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(check_zone(BP_TORSO))
H.electrocute_act(power, src, H.get_siemens_coefficient_organ(affected), affected, 0)
else
target_mob.electrocute_act(power, src, 0.75, BP_TORSO)
@@ -69,7 +69,7 @@
var/siemens_comparison = 0
for(var/mob/living/carbon/human/H in filtered_targets)
- var/obj/item/organ/external/affected = H.get_organ(check_zone(BP_TORSO))
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(check_zone(BP_TORSO))
var/their_siemens = H.get_siemens_coefficient_organ(affected)
if(their_siemens > siemens_comparison) //We want as conductive as possible, so higher is better.
new_target = H
diff --git a/code/game/gamemodes/technomancer/spells/projectile/lightning.dm b/code/game/gamemodes/technomancer/spells/projectile/lightning.dm
index 028d34ec997a..669b34bf872e 100644
--- a/code/game/gamemodes/technomancer/spells/projectile/lightning.dm
+++ b/code/game/gamemodes/technomancer/spells/projectile/lightning.dm
@@ -41,7 +41,7 @@
return
if(ishuman(target_mob))
var/mob/living/carbon/human/H = target_mob
- var/obj/item/organ/external/affected = H.get_organ(check_zone(BP_TORSO))
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(check_zone(BP_TORSO))
H.electrocute_act(power, src, H.get_siemens_coefficient_organ(affected), affected, 0)
else
target_mob.electrocute_act(power, src, 0.75, BP_TORSO)
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index ae3898fc44ea..2de95b9a3774 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -319,7 +319,7 @@
occupantData["ingested"] = ingestedData
var/extOrganData[0]
- for(var/obj/item/organ/external/E in H.organs)
+ for(var/obj/item/organ/external/E as anything in H.external_organs)
var/organData[0]
organData["name"] = E.name
organData["open"] = E.open
@@ -504,7 +504,7 @@
dat += "
Other Wounds | "
dat += ""
- for(var/obj/item/organ/external/e in occupant.organs)
+ for(var/obj/item/organ/external/e as anything in occupant.external_organs)
dat += ""
var/AN = ""
var/open = ""
diff --git a/code/game/machinery/computer/arcade/amputation.dm b/code/game/machinery/computer/arcade/amputation.dm
index a978a40bdf79..6c853aa17f7c 100644
--- a/code/game/machinery/computer/arcade/amputation.dm
+++ b/code/game/machinery/computer/arcade/amputation.dm
@@ -11,7 +11,7 @@
if(!iscarbon(user))
return
var/mob/living/carbon/c_user = user
- if(!c_user.get_organ(BP_L_ARM) && !c_user.get_organ(BP_R_ARM))
+ if(!c_user.legacy_organ_by_zone(BP_L_ARM) && !c_user.legacy_organ_by_zone(BP_R_ARM))
return
to_chat(c_user, SPAN_WARNING("You move your hand towards the machine, and begin to hesitate as a bloodied guillotine emerges from inside of it..."))
if(do_after(c_user, 50, target = src))
@@ -20,7 +20,7 @@
var/which_hand = BP_L_ARM
if(!(c_user.get_active_held_item() % 2))
which_hand = BP_R_ARM
- var/obj/item/organ/external/chopchop = c_user.get_organ(which_hand)
+ var/obj/item/organ/external/chopchop = c_user.legacy_organ_by_zone(which_hand)
chopchop.droplimb()
qdel(chopchop)
//user.mind?.adjust_experience(/datum/skill/gaming, 100)
diff --git a/code/game/machinery/doors/airlock/airlock.dm b/code/game/machinery/doors/airlock/airlock.dm
index b18db9b23ca5..7b040ec02b03 100644
--- a/code/game/machinery/doors/airlock/airlock.dm
+++ b/code/game/machinery/doors/airlock/airlock.dm
@@ -245,7 +245,7 @@ GLOBAL_REAL_VAR(airlock_typecache) = typecacheof(list(
/obj/machinery/door/airlock/attack_alien(var/mob/user) //Familiar, right? Doors. -Mechoid
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/X = user
- if(istype(X.species, /datum/species/xenos))
+ if(istype(X.species, /datum/species/xenomorph))
if(src.locked || src.welded)
visible_message("\The [user] begins digging into \the [src] internals!")
src.do_animate(DOOR_ANIMATION_DENY)
@@ -654,7 +654,7 @@ About the new airlock wires panel:
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/X = user
- if(istype(X.species, /datum/species/xenos))
+ if(istype(X.species, /datum/species/xenomorph))
src.attack_alien(user)
return
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index 9df2f78a99fd..da46109afff3 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -119,7 +119,7 @@
/obj/machinery/door/blast/attack_hand(mob/user, datum/event_args/actor/clickchain/e_args)
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/X = user
- if(istype(X.species, /datum/species/xenos))
+ if(istype(X.species, /datum/species/xenomorph))
src.attack_alien(user)
return
..()
@@ -172,7 +172,7 @@
/obj/machinery/door/blast/attack_alien(var/mob/user) //Familiar, right? Doors.
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/X = user
- if(istype(X.species, /datum/species/xenos))
+ if(istype(X.species, /datum/species/xenomorph))
if(src.density)
visible_message("\The [user] begins forcing \the [src] open!")
if(do_after(user, 15 SECONDS,src))
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 423e176d4d09..eaf785af4441 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -176,7 +176,7 @@ GLOBAL_LIST_INIT(firelock_align_types, typecacheof(list(
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/X = user
- if(istype(X.species, /datum/species/xenos))
+ if(istype(X.species, /datum/species/xenomorph))
src.attack_alien(user)
return
@@ -233,7 +233,7 @@ GLOBAL_LIST_INIT(firelock_align_types, typecacheof(list(
/obj/machinery/door/firedoor/attack_alien(var/mob/user) //Familiar, right? Doors.
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/X = user
- if(istype(X.species, /datum/species/xenos))
+ if(istype(X.species, /datum/species/xenomorph))
if(src.blocked)
visible_message("\The [user] begins digging into \the [src] internals!")
if(do_after(user,5 SECONDS,src))
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index fd2df07fd4a6..bcaf42c150af 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -83,7 +83,7 @@
if(!H.eyecheck() <= 0)
continue
flash_time *= H.species.flash_mod
- var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/E = H.keyed_organs[ORGAN_KEY_EYES]
if(!E)
return
if(E.is_bruised() && prob(E.damage + 50))
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index d652621f749a..73cc90680e5d 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -181,7 +181,7 @@
if(!(get_dist(src, attached_victim) <= 1 && isturf(attached_victim.loc)))
to_chat(attached_victim, SPAN_USERDANGER("The IV drip needle is ripped out of you, leaving an open bleeding wound!"))
var/list/arm_zones = shuffle(list(BP_R_ARM, BP_L_ARM))
- var/obj/item/organ/external/chosen_limb = attached_victim.get_organ(arm_zones[1]) || attached_victim.get_organ(arm_zones[2]) || attached_victim.get_organ(BP_TORSO)
+ var/obj/item/organ/external/chosen_limb = attached_victim.legacy_organ_by_zone(arm_zones[1]) || attached_victim.legacy_organ_by_zone(arm_zones[2]) || attached_victim.legacy_organ_by_zone(BP_TORSO)
chosen_limb.inflict_bodypart_damage(
brute = 3,
damage_mode = DAMAGE_MODE_SHARP,
diff --git a/code/game/machinery/misc/bioscan_antenna.dm b/code/game/machinery/misc/bioscan_antenna.dm
index 22da7d056c67..15386d9182b2 100644
--- a/code/game/machinery/misc/bioscan_antenna.dm
+++ b/code/game/machinery/misc/bioscan_antenna.dm
@@ -62,7 +62,7 @@ GLOBAL_LIST_EMPTY(bioscan_antenna_list)
// todo: better xenomorphs
if(ishuman(user))
var/mob/living/carbon/human/H = user
- if(istype(H.species, /datum/species/xenos))
+ if(istype(H.species, /datum/species/xenomorph))
if(!network_key)
to_chat(H, SPAN_WARNING("[src] is already de-programmed."))
else
diff --git a/code/game/machinery/oxygen_pump.dm b/code/game/machinery/oxygen_pump.dm
index a2cf6a659191..48ef4e50dc10 100644
--- a/code/game/machinery/oxygen_pump.dm
+++ b/code/game/machinery/oxygen_pump.dm
@@ -94,9 +94,6 @@
if(!user)
user = target
// Check target validity
- if(!target.organs_by_name[BP_HEAD])
- to_chat(user, SPAN_WARNING("\The [target] doesn't have a head."))
- return
if(!target.check_has_mouth())
to_chat(user, SPAN_WARNING("\The [target] doesn't have a mouth."))
return
diff --git a/code/game/machinery/virtual_reality/vr_console.dm b/code/game/machinery/virtual_reality/vr_console.dm
index 92f25b7bb879..893320117459 100644
--- a/code/game/machinery/virtual_reality/vr_console.dm
+++ b/code/game/machinery/virtual_reality/vr_console.dm
@@ -90,16 +90,12 @@
return
go_in(target, user)
-
-
/obj/machinery/sleeper/relaymove(var/mob/user)
..()
if(usr.incapacitated())
return
go_out()
-
-
/obj/machinery/vr_sleeper/emp_act(var/severity)
if(machine_stat & (BROKEN|NOPOWER))
..(severity)
@@ -110,9 +106,9 @@
// ### Fry the brain? Yes. Maybe.
if(prob(15 / ( severity / 4 )) && occupant.species.has_organ[O_BRAIN] && occupant.internal_organs_by_name[O_BRAIN])
var/obj/item/organ/O = occupant.internal_organs_by_name[O_BRAIN]
- O.take_damage(severity * 2)
+ O.take_damage((severity / 4) * 5)
visible_message("\The [src]'s internal lighting flashes rapidly, before the hatch swings open with a cloud of smoke.")
- smoke.set_up(severity, 0, src)
+ smoke.set_up(ceil(severity / 4 * 2), 0, src)
smoke.start("#202020")
INVOKE_ASYNC(src, PROC_REF(go_out))
diff --git a/code/game/machinery/vitals_monitor.dm b/code/game/machinery/vitals_monitor.dm
index e5f0c1197e9d..0085c90134a7 100644
--- a/code/game/machinery/vitals_monitor.dm
+++ b/code/game/machinery/vitals_monitor.dm
@@ -38,7 +38,7 @@
var/breathing = "none"
if(victim.stat != DEAD && !(victim.status_flags & STATUS_FAKEDEATH))
- var/obj/item/organ/internal/brain/brain = victim.internal_organs_by_name[O_BRAIN]
+ var/obj/item/organ/internal/brain/brain = victim.keyed_organs[ORGAN_KEY_BRAIN]
if(istype(brain))
if(victim.getBrainLoss())
brain_activity = "anomalous"
@@ -47,7 +47,7 @@
else
brain_activity = "normal"
- var/obj/item/organ/internal/lungs/lungs = victim.internal_organs_by_name[O_LUNGS]
+ var/obj/item/organ/internal/lungs/lungs = victim.keyed_organs[ORGAN_KEY_LUNGS]
if(istype(lungs))
var/oxyloss = victim.getOxyLoss()
if(oxyloss > 50)
@@ -106,7 +106,7 @@
add_overlay("pulse_thready")
add_overlay("pulse_warning")
- var/obj/item/organ/internal/brain/brain = victim.internal_organs_by_name[O_BRAIN]
+ var/obj/item/organ/internal/brain/brain = victim.keyed_organs[ORGAN_KEY_BRAIN]
if(istype(brain) && victim.stat != DEAD && !(victim.status_flags & STATUS_FAKEDEATH))
if(victim.getBrainLoss())
add_overlay("brain_verybad")
@@ -118,7 +118,7 @@
else
add_overlay("brain_warning")
- var/obj/item/organ/internal/lungs/lungs = victim.internal_organs_by_name[O_LUNGS]
+ var/obj/item/organ/internal/lungs/lungs = victim.keyed_organs[ORGAN_KEY_LUNGS]
if(istype(lungs) && victim.stat != DEAD && !(victim.status_flags & STATUS_FAKEDEATH))
var/oxyloss = victim.getOxyLoss()
if(oxyloss > 50)
diff --git a/code/game/objects/effects/debris/cleanable/blood.dm b/code/game/objects/effects/debris/cleanable/blood.dm
index 220680d47bd7..d0f528142481 100644
--- a/code/game/objects/effects/debris/cleanable/blood.dm
+++ b/code/game/objects/effects/debris/cleanable/blood.dm
@@ -91,8 +91,8 @@ var/global/list/image/splatter_cache=list()
if(amount < 1)
return
- var/obj/item/organ/external/l_foot = perp.get_organ("l_foot")
- var/obj/item/organ/external/r_foot = perp.get_organ("r_foot")
+ var/obj/item/organ/external/l_foot = perp.legacy_organ_by_zone("l_foot")
+ var/obj/item/organ/external/r_foot = perp.legacy_organ_by_zone("r_foot")
var/hasfeet = 1
if((!l_foot || l_foot.is_stump()) && (!r_foot || r_foot.is_stump()))
hasfeet = 0
diff --git a/code/game/objects/effects/traps.dm b/code/game/objects/effects/traps.dm
index 6aa6397fc601..27ab9226db17 100644
--- a/code/game/objects/effects/traps.dm
+++ b/code/game/objects/effects/traps.dm
@@ -228,8 +228,8 @@ Add those other swinging traps you mentioned above!
/obj/effect/trap/pit/bone_breaker/proc/break_legs(mob/victim as mob)
var/broken_legs = 0
var/mob/living/carbon/human/target = victim
- var/obj/item/organ/external/left_leg = target.get_organ(BP_L_LEG)
- var/obj/item/organ/external/right_leg = target.get_organ(BP_R_LEG)
+ var/obj/item/organ/external/left_leg = target.legacy_organ_by_zone(BP_L_LEG)
+ var/obj/item/organ/external/right_leg = target.legacy_organ_by_zone(BP_R_LEG)
playsound(src, 'sound/effects/bang.ogg', 100, 1)
if(left_leg && left_leg.fracture())
broken_legs++
@@ -540,16 +540,17 @@ Add those other swinging traps you mentioned above!
if(!tripped)
return
- else if(istype(AM, /mob/living))
- var/mob/living/M = AM
+ else if(istype(AM, /mob/living/carbon))
+ var/mob/living/carbon/M = AM
var/damage = rand(min_damage, max_damage)
var/list/target_limbs = list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)
var/selected = pick(target_limbs)
- var/obj/item/organ/external/target = M.get_organ(selected)
- M.apply_damage(damage, DAMAGE_TYPE_BRUTE)
- target.droplimb()
- M.visible_message("[M] is slashed by the spinning blades!", \
- "You are slashed by the spinning blades!")
+ var/obj/item/organ/external/target = M.legacy_organ_by_zone(selected)
+ if(target)
+ M.apply_damage(damage, DAMAGE_TYPE_BRUTE)
+ target.droplimb()
+ M.visible_message("[M] is slashed by the spinning blades!", \
+ "You are slashed by the spinning blades!")
/* This is all per-tick processing stuff. It isn't working the way I want, so I'm reverting it.
@@ -596,16 +597,17 @@ if (istype(AM, /mob/living))
if(!tripped)
return
- else if(istype(AM, /mob/living))
- var/mob/living/M = AM
+ else if(istype(AM, /mob/living/carbon))
+ var/mob/living/carbon/M = AM
var/damage = rand(min_damage, max_damage)
var/list/target_limbs = list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)
var/selected = pick(target_limbs)
- var/obj/item/organ/external/target = M.get_organ(selected)
- M.apply_damage(damage, DAMAGE_TYPE_BRUTE)
- target.droplimb()
- M.visible_message("[M] is ripped by the whirling sawblades!", \
- "You are ripped open by the whirling sawblades!")
+ var/obj/item/organ/external/target = M.legacy_organ_by_zone(selected)
+ if(target)
+ M.apply_damage(damage, DAMAGE_TYPE_BRUTE)
+ target.droplimb()
+ M.visible_message("[M] is ripped by the whirling sawblades!", \
+ "You are ripped open by the whirling sawblades!")
//Flame Trap
@@ -778,16 +780,16 @@ if (istype(AM, /mob/living))
if(tripped)
return
- if(istype(AM, /mob/living))
+ if(istype(AM, /mob/living/carbon))
fire()
update_icon()
- var/mob/living/M = AM
+ var/mob/living/carbon/M = AM
var/list/throw_dirs = list(1, 2, 4, 8, 5, 6, 9, 10)
var/turf/T2 = get_step(AM, pick(throw_dirs))
var/damage = rand(min_damage, max_damage)
var/list/bone_sites = list(BP_HEAD, BP_TORSO, BP_GROIN, BP_L_ARM, BP_L_HAND, BP_R_ARM, BP_R_HAND, BP_L_LEG, BP_L_FOOT, BP_R_LEG, BP_R_FOOT)
var/selected = pick(bone_sites)
- var/obj/item/organ/external/target = M.get_organ(selected)
+ var/obj/item/organ/external/target = M.legacy_organ_by_zone(selected)
var/head_slot = SLOT_HEAD
M.apply_damage(damage, DAMAGE_TYPE_BRUTE)
target.fracture()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 77c2eb3ea3a6..f6aaa6be5ad2 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -492,7 +492,7 @@
src.add_fingerprint(user)
if(istype(H))
- var/obj/item/organ/internal/eyes/eyes = H.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/eyes = H.keyed_organs[ORGAN_KEY_EYES]
if(H != user)
for(var/mob/O in (viewers(M) - user - M))
@@ -520,7 +520,7 @@
if (eyes.damage >= eyes.min_broken_damage)
if(M.stat != 2)
to_chat(M, "You go blind!")
- var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(BP_HEAD)
affecting.inflict_bodypart_damage(
brute = 7,
)
diff --git a/code/game/objects/items/defib/shockpaddles.dm b/code/game/objects/items/defib/shockpaddles.dm
index 6194487dc220..3ebf6d2a5dda 100644
--- a/code/game/objects/items/defib/shockpaddles.dm
+++ b/code/game/objects/items/defib/shockpaddles.dm
@@ -245,7 +245,7 @@
/obj/item/shockpaddles/proc/do_electrocute(mob/living/carbon/human/H, mob/user, var/target_zone)
- var/obj/item/organ/external/affecting = H.get_organ(target_zone)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(target_zone)
if(!affecting)
to_chat(user, "They are missing that body part!")
return
diff --git a/code/game/objects/items/devices/hacktool.dm b/code/game/objects/items/devices/hacktool.dm
index fdcff5492e65..0b4dc0fb7f45 100644
--- a/code/game/objects/items/devices/hacktool.dm
+++ b/code/game/objects/items/devices/hacktool.dm
@@ -17,7 +17,7 @@
/obj/item/multitool/hacktool/Destroy()
for(var/T in known_targets)
var/atom/target = T
- target.unregister(OBSERVER_EVENT_DESTROY, src)
+ UnregisterSignal(target, COMSIG_PARENT_QDELETING)
known_targets.Cut()
qdel(hack_state)
hack_state = null
@@ -68,7 +68,7 @@
return 0
known_targets.Insert(1, target) // Insert the newly hacked target first,
- target.register(OBSERVER_EVENT_DESTROY, src, TYPE_PROC_REF(/obj/item/multitool/hacktool, on_target_destroy))
+ RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(on_target_destroy))
return 1
/obj/item/multitool/hacktool/proc/sanity_check()
@@ -77,7 +77,7 @@
if(known_targets.len > max_known_targets)
for(var/i = (max_known_targets + 1) to known_targets.len)
var/atom/A = known_targets[i]
- A.unregister(OBSERVER_EVENT_DESTROY, src)
+ UnregisterSignal(A, COMSIG_PARENT_QDELETING)
known_targets.Cut(max_known_targets + 1)
/obj/item/multitool/hacktool/proc/on_target_destroy(var/target)
diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm
index 91865cec554a..cc16c4904abf 100644
--- a/code/game/objects/items/devices/laserpointer.dm
+++ b/code/game/objects/items/devices/laserpointer.dm
@@ -108,7 +108,7 @@
eye_prot = 4
var/severity = (rand(0, 1) + diode.rating - eye_prot)
var/mob/living/carbon/human/H = C
- var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/E = H.keyed_organs[ORGAN_KEY_EYES]
if(!E)
outmsg = "You shine [src] at [C], but they don't seem to have eyes."
return
diff --git a/code/game/objects/items/id_cards/syndicate_ids.dm b/code/game/objects/items/id_cards/syndicate_ids.dm
index a5ebf6d4076d..db5a9ed7c810 100644
--- a/code/game/objects/items/id_cards/syndicate_ids.dm
+++ b/code/game/objects/items/id_cards/syndicate_ids.dm
@@ -71,14 +71,14 @@
unset_registered_user()
registered_user = user
user.set_id_info(src)
- user.register(OBSERVER_EVENT_DESTROY, src, TYPE_PROC_REF(/obj/item/card/id/syndicate, unset_registered_user))
+ RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(unset_registered_user))
return TRUE
/obj/item/card/id/syndicate/proc/unset_registered_user(var/mob/user)
if(!registered_user || (user && user != registered_user))
return
- registered_user.unregister(OBSERVER_EVENT_DESTROY, src)
registered_user = null
+ UnregisterSignal(registered_user, COMSIG_PARENT_QDELETING)
/obj/item/card/id/syndicate/CanUseTopic(mob/user)
if(user != registered_user)
diff --git a/code/game/objects/items/melee/types/ninja_energy_blade.dm b/code/game/objects/items/melee/types/ninja_energy_blade.dm
index 10e586432e40..3106be2ae693 100644
--- a/code/game/objects/items/melee/types/ninja_energy_blade.dm
+++ b/code/game/objects/items/melee/types/ninja_energy_blade.dm
@@ -52,10 +52,10 @@
/obj/item/melee/ninja_energy_blade/process(delta_time)
if(!creator || loc != creator || !creator.is_holding(src))
// Tidy up a bit.
- if(istype(loc,/mob/living))
- var/mob/living/carbon/human/host = loc
+ if(istype(loc,/mob/living/carbon))
+ var/mob/living/carbon/host = loc
if(istype(host))
- for(var/obj/item/organ/external/organ in host.organs)
+ for(var/obj/item/organ/external/organ in host.external_organs)
for(var/obj/item/O in organ.implants)
if(O == src)
organ.implants -= src
diff --git a/code/game/objects/items/scanners/health.dm b/code/game/objects/items/scanners/health.dm
index a5a907d2b98b..1a79e2b6fda9 100644
--- a/code/game/objects/items/scanners/health.dm
+++ b/code/game/objects/items/scanners/health.dm
@@ -227,7 +227,7 @@
var/fracture_dat = "" // All the fractures
var/infection_dat = "" // All the infections
var/ib_dat = "" // All the IB
- for(var/obj/item/organ/external/e in H.organs)
+ for(var/obj/item/organ/external/e as anything in H.external_organs)
if(!e)
continue
// Broken limbs
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 748b839080cb..ffdc381a6e0b 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -33,7 +33,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(!affecting)
to_chat(user, "No body part there to work on!")
@@ -98,7 +98,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(affecting.open)
to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!")
@@ -160,7 +160,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(affecting.open)
to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!")
@@ -229,7 +229,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(affecting.open)
to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!")
@@ -268,7 +268,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(affecting.open)
to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!")
@@ -330,7 +330,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(affecting.open)
to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!")
@@ -373,7 +373,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
var/limb = affecting.name
if(!(affecting.organ_tag in splintable_organs))
to_chat(user, "You can't use \the [src] to apply a splint there!")
@@ -470,7 +470,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(affecting.open)
to_chat(user, "The [affecting.name] is cut open, you'll need more than a salve!")
@@ -538,7 +538,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(affecting.open)
to_chat(user, "The [affecting.name] is cut open, you'll need more than a salve!")
diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm
index 4f5e15997fe4..03d62e275ed0 100644
--- a/code/game/objects/items/stacks/nanopaste.dm
+++ b/code/game/objects/items/stacks/nanopaste.dm
@@ -35,7 +35,7 @@
if (istype(L,/mob/living/carbon/human)) //Repairing robolimbs
var/mob/living/carbon/human/H = L
- var/obj/item/organ/external/S = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/S = H.legacy_organ_by_zone(user.zone_sel.selecting)
if (S && (S.robotic >= ORGAN_ROBOT))
if(!S.get_damage())
to_chat(user, "Nothing to fix here.")
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 03498f3fb1e0..f0682c59b9a4 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -97,6 +97,7 @@
name = "boxed augment implant (with injector)"
var/case_type = /obj/item/implantcase/shades
+// todo: all of these should be autosurgeons
/obj/item/storage/box/syndie_kit/imp_aug/Initialize(mapload)
new /obj/item/implanter(src)
new case_type(src)
diff --git a/code/game/objects/items/stream_projector/medichine.dm b/code/game/objects/items/stream_projector/medichine.dm
index 4583723dc05b..3ac52ba35fd2 100644
--- a/code/game/objects/items/stream_projector/medichine.dm
+++ b/code/game/objects/items/stream_projector/medichine.dm
@@ -698,8 +698,8 @@ GLOBAL_LIST_EMPTY(medichine_cell_datums)
var/brute_loss_instances = 0
var/burn_loss_instances = 0
var/list/datum/wound/wounds_healing = list()
- for(var/obj/item/organ/external/ext as anything in humanlike.bad_external_organs)
- if(!ext.is_any_biology_type(biology_types))
+ for(var/obj/item/organ/external/ext as anything in humanlike.external_organs)
+ if(!(ext?.biology?.biology_type & biology_types))
continue
// only heal 15 wounds at a time thank you!
if(length(wounds_healing) > 15)
@@ -847,7 +847,7 @@ GLOBAL_LIST_EMPTY(medichine_cell_datums)
return 0
var/can_deal = (hard_limit + hard_overrun_allowed) - humanlike.halloss
var/will_deal = 0
- for(var/obj/item/organ/external/ext as anything in humanlike.bad_external_organs)
+ for(var/obj/item/organ/external/ext as anything in humanlike.external_organs)
var/size_ratio = organ_rel_size[ext.organ_tag] / GLOB.organ_combined_size
if(!size_ratio)
continue
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index a2eced2bcc8e..2c0fceee61b2 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -286,7 +286,7 @@
safety = clamp( safety + eye_safety_modifier, -1, 2)
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
- var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/E = H.keyed_organs[ORGAN_KEY_EYES]
if(!E)
return
if(H.nif && H.nif.flag_check(NIF_V_UVFILTER,NIF_FLAGS_VISION))
diff --git a/code/game/objects/items/weapons/autopsy.dm b/code/game/objects/items/weapons/autopsy.dm
index 5a893235ee3e..6b92511aa55a 100644
--- a/code/game/objects/items/weapons/autopsy.dm
+++ b/code/game/objects/items/weapons/autopsy.dm
@@ -173,7 +173,7 @@
src.timeofdeath = M.timeofdeath
- var/obj/item/organ/external/S = M.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/S = M.legacy_organ_by_zone(user.zone_sel.selecting)
if(!S)
to_chat(user, "You can't scan this body part.")
return
diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm
index 5e51f09d4afc..048473953e4e 100644
--- a/code/game/objects/items/weapons/cosmetics.dm
+++ b/code/game/objects/items/weapons/cosmetics.dm
@@ -143,6 +143,6 @@
ui_users[user] = AC
AC.nano_ui_interact(user)
var/mob/living/carbon/human/H = user
- var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/E = H.keyed_organs[ORGAN_KEY_EYES]
if(istype(E))
E.change_eye_color()
diff --git a/code/game/objects/items/weapons/duct_tape.dm b/code/game/objects/items/weapons/duct_tape.dm
index fd572daf27fc..65518e1a0679 100644
--- a/code/game/objects/items/weapons/duct_tape.dm
+++ b/code/game/objects/items/weapons/duct_tape.dm
@@ -29,10 +29,6 @@
return
else
if(user.zone_sel.selecting == O_EYES)
-
- if(!H.organs_by_name[BP_HEAD])
- to_chat(user, "\The [H] doesn't have a head.")
- return
if(!H.has_eyes())
to_chat(user, "\The [H] doesn't have any eyes.")
return
@@ -42,6 +38,9 @@
if(H.head && (H.head.body_cover_flags & FACE))
to_chat(user, "Remove their [H.head] first.")
return
+ if(!H.has_slot(/datum/inventory_slot/inventory/glasses::id))
+ to_chat(user, SPAN_WARNING("There's nowhere to tape!"))
+ return
user.visible_message("\The [user] begins taping over \the [H]'s eyes!")
if(!do_after(user, 30))
@@ -59,9 +58,6 @@
if(!can_place)
return
- if(!H || !src || !H.organs_by_name[BP_HEAD] || !H.has_eyes() || H.glasses || (H.head && (H.head.body_cover_flags & FACE)))
- return
-
user.visible_message("\The [user] has taped up \the [H]'s eyes!")
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/blindfold/tape(H), SLOT_ID_GLASSES)
H.update_inv_glasses()
@@ -69,9 +65,6 @@
return
else if(user.zone_sel.selecting == O_MOUTH || user.zone_sel.selecting == BP_HEAD)
- if(!H.organs_by_name[BP_HEAD])
- to_chat(user, "\The [H] doesn't have a head.")
- return
if(!H.check_has_mouth())
to_chat(user, "\The [H] doesn't have a mouth.")
return
@@ -81,6 +74,9 @@
if(H.head && (H.head.body_cover_flags & FACE))
to_chat(user, "Remove their [H.head] first.")
return
+ if(!H.has_slot(/datum/inventory_slot/inventory/mask::id))
+ to_chat(user, SPAN_WARNING("There's nowhere to tape!"))
+ return
user.visible_message("\The [user] begins taping up \the [H]'s mouth!")
if(!do_after(user, 30))
@@ -98,9 +94,6 @@
if(!can_place)
return
- if(!H || !src || !H.organs_by_name[BP_HEAD] || !H.check_has_mouth() || (H.head && (H.head.body_cover_flags & FACE)))
- return
-
user.visible_message("\The [user] has taped up \the [H]'s mouth!")
H.equip_to_slot_or_del(new /obj/item/clothing/mask/muzzle/tape(H), SLOT_ID_MASK)
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 1a447da35f2b..d8c4c3c43173 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -79,7 +79,7 @@
//This really should be in mob not every check
if(ishuman(M))
- var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/E = H.keyed_organs[ORGAN_KEY_EYES]
if (E && E.damage >= E.min_bruised_damage)
to_chat(M, "Your eyes start to burn badly!")
if(!banglet && !(istype(src , /obj/item/grenade/flashbang/clusterbang)))
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 81d985e3017f..ca7681101813 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -29,7 +29,7 @@
implanted = TRUE
if(ishuman(source))
var/mob/living/carbon/human/H = source
- var/obj/item/organ/external/affected = H.get_organ(target_zone)
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(target_zone)
if(affected)
affected.implants |= src
part = affected
diff --git a/code/game/objects/items/weapons/implants/implantaugment.dm b/code/game/objects/items/weapons/implants/implantaugment.dm
index cdbb56e3b955..c9f9451ca914 100644
--- a/code/game/objects/items/weapons/implants/implantaugment.dm
+++ b/code/game/objects/items/weapons/implants/implantaugment.dm
@@ -1,6 +1,7 @@
//////////////////////////////
// Nanite Organ Implant
//////////////////////////////
+// todo: replace with autosurgeons
/obj/item/implant/organ
name = "nanite fabrication implant"
desc = "A buzzing implant covered in a writhing layer of metal insects."
@@ -27,27 +28,13 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/NewOrgan = new organ_to_implant()
-
- var/obj/item/organ/external/E = H.get_organ(NewOrgan.parent_organ)
- to_chat(H, "You feel a tingling sensation in your [part].")
- if(E && !(H.internal_organs_by_name[NewOrgan.organ_tag]))
+ var/obj/item/organ/NewOrgan = new organ_to_implant
+ if(NewOrgan.insert(H))
spawn(rand(1 SECONDS, 30 SECONDS))
to_chat(H, "You feel a pressure in your [E] as the tingling fades, the lump caused by the implant now gone.")
-
- NewOrgan.forceMove(H)
- NewOrgan.owner = H
- if(E.internal_organs == null)
- E.internal_organs = list()
- E.internal_organs |= NewOrgan
- H.internal_organs_by_name[NewOrgan.organ_tag] = NewOrgan
- H.internal_organs |= NewOrgan
- NewOrgan.handle_organ_mod_special()
-
- spawn(1)
+ spawn(0)
if(!QDELETED(src))
qdel(src)
-
else
qdel(NewOrgan)
to_chat(H, "You feel a pinching sensation in your [part]. The implant remains.")
@@ -142,7 +129,7 @@
I.parent_organ = BP_L_ARM
I.target_slot = /datum/inventory_slot/abstract/hand/left
- . = H.get_organ(I.parent_organ)
+ . = H.legacy_organ_by_zone(I.parent_organ)
/*
* Limb implant primary subtypes.
diff --git a/code/game/objects/items/weapons/implants/implantreagent_vr.dm b/code/game/objects/items/weapons/implants/implantreagent_vr.dm
index e192a0fd1647..c556183bcde1 100644
--- a/code/game/objects/items/weapons/implants/implantreagent_vr.dm
+++ b/code/game/objects/items/weapons/implants/implantreagent_vr.dm
@@ -81,7 +81,7 @@
var/obj/item/implant/reagent_generator/rimplant
- for(var/obj/item/organ/external/E in organs)
+ for(var/obj/item/organ/external/E in external_organs)
for(var/obj/item/implant/I in E.implants)
if(istype(I, /obj/item/implant/reagent_generator))
rimplant = I
diff --git a/code/game/objects/items/weapons/material/shards.dm b/code/game/objects/items/weapons/material/shards.dm
index 3341973c4be0..db61aa8cbfd3 100644
--- a/code/game/objects/items/weapons/material/shards.dm
+++ b/code/game/objects/items/weapons/material/shards.dm
@@ -129,7 +129,7 @@
var/list/check = list("l_foot", "r_foot")
while(check.len)
var/picked = pick(check)
- var/obj/item/organ/external/affecting = H.get_organ(picked)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(picked)
if(affecting)
if(affecting.robotic >= ORGAN_ROBOT)
return
diff --git a/code/game/objects/items/weapons/mop_deploy.dm b/code/game/objects/items/weapons/mop_deploy.dm
index 3253c988f78b..efe43d1ac48c 100644
--- a/code/game/objects/items/weapons/mop_deploy.dm
+++ b/code/game/objects/items/weapons/mop_deploy.dm
@@ -68,7 +68,7 @@
if(istype(loc,/mob/living))
var/mob/living/carbon/human/host = loc
if(istype(host))
- for(var/obj/item/organ/external/organ in host.organs)
+ for(var/obj/item/organ/external/organ as anything in host.external_organs)
for(var/obj/item/O in organ.implants)
if(O == src)
organ.implants -= src
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 4a05db8d2370..ccd1c87624a1 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -155,7 +155,7 @@
var/obj/item/organ/external/affecting = null
if(ishuman(L))
var/mob/living/carbon/human/H = L
- affecting = H.get_organ(target_zone)
+ affecting = H.legacy_organ_by_zone(target_zone)
if(user.a_intent == INTENT_HARM)
. = ..()
diff --git a/code/game/objects/obj.dm b/code/game/objects/obj.dm
index 237a5e97a615..14bba628a09c 100644
--- a/code/game/objects/obj.dm
+++ b/code/game/objects/obj.dm
@@ -565,15 +565,15 @@
switch(pick(list("ankle","wrist","head","knee","elbow")))
if("ankle")
- affecting = H.get_organ(pick(BP_L_FOOT, BP_R_FOOT))
+ affecting = H.legacy_organ_by_zone(pick(BP_L_FOOT, BP_R_FOOT))
if("knee")
- affecting = H.get_organ(pick(BP_L_LEG, BP_R_LEG))
+ affecting = H.legacy_organ_by_zone(pick(BP_L_LEG, BP_R_LEG))
if("wrist")
- affecting = H.get_organ(pick(BP_L_HAND, BP_R_HAND))
+ affecting = H.legacy_organ_by_zone(pick(BP_L_HAND, BP_R_HAND))
if("elbow")
- affecting = H.get_organ(pick(BP_L_ARM, BP_R_ARM))
+ affecting = H.legacy_organ_by_zone(pick(BP_L_ARM, BP_R_ARM))
if("head")
- affecting = H.get_organ(BP_HEAD)
+ affecting = H.legacy_organ_by_zone(BP_HEAD)
if(affecting)
to_chat(M, "You land heavily on your [affecting.name]!")
diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm
index 6cb403308261..cf1ae6360f9f 100644
--- a/code/game/objects/structures/aliens.dm
+++ b/code/game/objects/structures/aliens.dm
@@ -48,7 +48,7 @@
/obj/structure/alien/resin/attack_hand(mob/user, datum/event_args/actor/clickchain/e_args)
if(iscarbon(user))
var/mob/living/carbon/C = user
- if(locate(/obj/item/organ/internal/xenos/hivenode) in C.internal_organs)
+ if(C.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
visible_message(SPAN_WARNING("[C] strokes the [name], and it melts away!"))
qdel(src)
return CLICKCHAIN_DID_SOMETHING | CLICKCHAIN_DO_NOT_PROPAGATE
@@ -337,7 +337,7 @@ Alien plants should do something if theres a lot of poison
/obj/structure/alien/egg/attack_hand(mob/user, datum/event_args/actor/clickchain/e_args)
var/mob/living/carbon/M = user
- if(!istype(M) || !(locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs))
+ if(!istype(M) || !(M.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode)))
return ..()
switch(status)
diff --git a/code/game/objects/structures/mineral_bath.dm b/code/game/objects/structures/mineral_bath.dm
index 63e8f801fa81..eb814dfb6264 100644
--- a/code/game/objects/structures/mineral_bath.dm
+++ b/code/game/objects/structures/mineral_bath.dm
@@ -144,7 +144,7 @@
/obj/structure/adherent_bath/proc/crystal_heal_damage(mob/living/carbon/human/patient)
patient.cure_radiation(RAD_MOB_CURE_ADHERENT_BATH)
- for(var/thing in patient.organs)
+ for(var/thing in patient.external_organs)
var/obj/item/organ/external/E = thing
if(BP_IS_CRYSTAL(E))
if(E.brute_dam || E.burn_dam)
@@ -156,7 +156,7 @@
return TRUE
/obj/structure/adherent_bath/proc/crystal_remove_shrapn(mob/living/carbon/human/patient)
- for(var/thing in patient.organs)
+ for(var/thing in patient.external_organs)
var/obj/item/organ/external/E = thing
if(BP_IS_CRYSTAL(E))
for(var/obj/implanted_object in E.implants)
@@ -168,7 +168,7 @@
/obj/structure/adherent_bath/proc/crystal_debrittle_crystals(mob/living/carbon/human/patient)
- for(var/thing in patient.organs)
+ for(var/thing in patient.external_organs)
if(istype(thing, /obj/item/organ))
var/obj/item/organ/O = thing
if(O.status & ORGAN_BRITTLE)
diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
index d9e4a6b18fd1..2bfa8c37b647 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
@@ -55,10 +55,10 @@
var/mob/living/carbon/xenos = user
var/mob/living/carbon/victim = M
- if(istype(victim) && locate(/obj/item/organ/internal/xenos/hivenode) in victim.internal_organs)
+ if(istype(victim) && victim.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
return
- if(istype(xenos) && !((locate(/obj/item/organ/internal/xenos/hivenode) in xenos.internal_organs)))
+ if(istype(xenos) && !((xenos.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))))
return
if(M == user)
diff --git a/code/game/rendering/legacy/alert.dm b/code/game/rendering/legacy/alert.dm
index fce64d37e72a..9953550d7f3e 100644
--- a/code/game/rendering/legacy/alert.dm
+++ b/code/game/rendering/legacy/alert.dm
@@ -524,8 +524,8 @@ so as to remain in compliance with the most up-to-date laws."
var/mob/living/L = owner
to_chat(usr, jointext(list(
"[usr == L? "You are" : "[L] is"] [lowertext(name)].",
- "Encumbrance: [L.cached_carry_encumbrance] / [L.physiology.carry_strength]",
- "Weight: [L.cached_carry_weight] / [L.physiology.carry_strength]",
+ "Encumbrance: [L.cached_carry_encumbrance] / [L.global_physiology.carry_strength]",
+ "Weight: [L.cached_carry_weight] / [L.global_physiology.carry_strength]",
), "
"))
/atom/movable/screen/alert/encumbered/minor
diff --git a/code/game/rendering/legacy/zone_sel.dm b/code/game/rendering/legacy/zone_sel.dm
new file mode 100644
index 000000000000..2f9dbcd08286
--- /dev/null
+++ b/code/game/rendering/legacy/zone_sel.dm
@@ -0,0 +1,77 @@
+
+/atom/movable/screen/zone_sel
+ name = "damage zone"
+ icon_state = "zone_sel"
+ screen_loc = ui_zonesel
+ var/selecting = TARGET_ZONE_TORSO
+
+/atom/movable/screen/zone_sel/Click(location, control,params)
+ var/list/PL = params2list(params)
+ var/icon_x = text2num(PL["icon-x"])
+ var/icon_y = text2num(PL["icon-y"])
+ var/old_selecting = selecting //We're only going to update_icon() if there's been a change
+
+ switch(icon_y)
+ if(1 to 3) //Feet
+ switch(icon_x)
+ if(10 to 15)
+ selecting = TARGET_ZONE_RIGHT_FOOT
+ if(17 to 22)
+ selecting = TARGET_ZONE_LEFT_FOOT
+ else
+ return 1
+ if(4 to 9) //Legs
+ switch(icon_x)
+ if(10 to 15)
+ selecting = TARGET_ZONE_RIGHT_LEG
+ if(17 to 22)
+ selecting = TARGET_ZONE_LEFT_LEG
+ else
+ return 1
+ if(10 to 13) //Hands and groin
+ switch(icon_x)
+ if(8 to 11)
+ selecting = TARGET_ZONE_RIGHT_HAND
+ if(12 to 20)
+ selecting = TARGET_ZONE_GROIN
+ if(21 to 24)
+ selecting = TARGET_ZONE_LEFT_HAND
+ else
+ return 1
+ if(14 to 22) //Chest and arms to shoulders
+ switch(icon_x)
+ if(8 to 11)
+ selecting = TARGET_ZONE_RIGHT_ARM
+ if(12 to 20)
+ selecting = TARGET_ZONE_TORSO
+ if(21 to 24)
+ selecting = TARGET_ZONE_LEFT_ARM
+ else
+ return 1
+ if(23 to 30) //Head, but we need to check for eye or mouth
+ if(icon_x in 12 to 20)
+ selecting = TARGET_ZONE_HEAD
+ switch(icon_y)
+ if(23 to 24)
+ if(icon_x in 15 to 17)
+ selecting = TARGET_ZONE_MOUTH
+ if(26) //Eyeline, eyes are on 15 and 17
+ if(icon_x in 14 to 18)
+ selecting = TARGET_ZONE_EYES
+ if(25 to 27)
+ if(icon_x in 15 to 17)
+ selecting = TARGET_ZONE_EYES
+
+ if(old_selecting != selecting)
+ update_icon()
+ return 1
+
+/atom/movable/screen/zone_sel/proc/set_selected_zone(bodypart)
+ var/old_selecting = selecting
+ selecting = bodypart
+ if(old_selecting != selecting)
+ update_icon()
+
+/atom/movable/screen/zone_sel/update_icon()
+ cut_overlays()
+ add_overlay(image('icons/mob/zone_sel.dmi', "[selecting]"))
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index fa96e39a4c46..36c62bdc796c 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -716,7 +716,7 @@
to_chat(usr,"That mob type ([H.type]) doesn't support NIFs, sorry.")
return
- if(!H.get_organ(BP_HEAD))
+ if(!H.legacy_organ_by_zone(BP_HEAD))
to_chat(usr,"Target is unsuitable.")
return
diff --git a/code/modules/admin/verbs/smite.dm b/code/modules/admin/verbs/smite.dm
index 05a60a174919..c33759be7db9 100644
--- a/code/modules/admin/verbs/smite.dm
+++ b/code/modules/admin/verbs/smite.dm
@@ -35,45 +35,45 @@
switch(smite_choice)
if(SMITE_BREAKLEGS)
var/broken_legs = 0
- var/obj/item/organ/external/left_leg = target.get_organ(BP_L_LEG)
+ var/obj/item/organ/external/left_leg = target.legacy_organ_by_zone(BP_L_LEG)
if(left_leg && left_leg.fracture())
broken_legs++
- var/obj/item/organ/external/right_leg = target.get_organ(BP_R_LEG)
+ var/obj/item/organ/external/right_leg = target.legacy_organ_by_zone(BP_R_LEG)
if(right_leg && right_leg.fracture())
broken_legs++
if(!broken_legs)
to_chat(src,"[target] didn't have any breakable legs, sorry.")
if(SMITE_DISLOCATEALL)
- var/obj/item/organ/external/left_leg = target.get_organ(BP_L_LEG)
+ var/obj/item/organ/external/left_leg = target.legacy_organ_by_zone(BP_L_LEG)
left_leg.dislocate()
- var/obj/item/organ/external/right_leg = target.get_organ(BP_R_LEG)
+ var/obj/item/organ/external/right_leg = target.legacy_organ_by_zone(BP_R_LEG)
right_leg.dislocate()
- var/obj/item/organ/external/left_arm = target.get_organ(BP_L_ARM)
+ var/obj/item/organ/external/left_arm = target.legacy_organ_by_zone(BP_L_ARM)
left_arm.dislocate()
- var/obj/item/organ/external/right_arm = target.get_organ(BP_R_ARM)
+ var/obj/item/organ/external/right_arm = target.legacy_organ_by_zone(BP_R_ARM)
right_arm.dislocate()
- var/obj/item/organ/external/head = target.get_organ(BP_HEAD)
+ var/obj/item/organ/external/head = target.legacy_organ_by_zone(BP_HEAD)
head.dislocate()
if(SMITE_DROP_LIMB_PICK)
var/picked_organ_tag = input("Select the limb you wanna remove of [target]","Limb Choice") as null|anything in list(BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM,BP_R_FOOT,BP_L_FOOT, BP_R_HAND, BP_L_HAND)
- var/obj/item/organ/external/limb = target.get_organ(picked_organ_tag)
+ var/obj/item/organ/external/limb = target.legacy_organ_by_zone(picked_organ_tag)
to_chat(target, SPAN_ALERTSYNDIE("Your sins have cost you your [limb.name]"))
limb?.droplimb(FALSE, pick(DROPLIMB_EDGE,DROPLIMB_BURN,DROPLIMB_BLUNT))
if(SMITE_DROP_LIMB_RANDOM)
var/rand_organ_tag = pick(BP_L_LEG, BP_R_LEG)
- var/obj/item/organ/external/limb = target.get_organ(rand_organ_tag)
+ var/obj/item/organ/external/limb = target.legacy_organ_by_zone(rand_organ_tag)
limb?.droplimb(FALSE, pick(DROPLIMB_EDGE,DROPLIMB_BURN,DROPLIMB_BLUNT))
rand_organ_tag = pick(BP_L_ARM, BP_R_ARM)
- limb = target.get_organ(rand_organ_tag)
+ limb = target.legacy_organ_by_zone(rand_organ_tag)
limb?.droplimb(FALSE, pick(DROPLIMB_EDGE,DROPLIMB_BURN,DROPLIMB_BLUNT))
to_chat(target, SPAN_ALERTSYNDIE("Your sins have cost you an arm and an leg"))
if(SMITE_DROP_LIMB_ALL)
for( var/limb_tag in list(BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM))
- var/obj/item/organ/external/limb = target.get_organ(limb_tag)
+ var/obj/item/organ/external/limb = target.legacy_organ_by_zone(limb_tag)
limb?.droplimb(FALSE, pick(DROPLIMB_EDGE,DROPLIMB_BURN,DROPLIMB_BLUNT))
to_chat(target, SPAN_ALERTSYNDIE(pick("The gods have bestowed you nuggethood", "The gods crave McDonalds", "The gods have turned you into a fucknugget")))
diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm
index 45bf675ac64d..5026b54f4f48 100644
--- a/code/modules/assembly/mousetrap.dm
+++ b/code/modules/assembly/mousetrap.dm
@@ -29,11 +29,11 @@
switch(type)
if("feet")
if(!H.shoes)
- affecting = H.get_organ(pick("l_leg", "r_leg"))
+ affecting = H.legacy_organ_by_zone(pick("l_leg", "r_leg"))
H.afflict_paralyze(20 * 3)
if("l_hand", "r_hand")
if(!H.gloves)
- affecting = H.get_organ(type)
+ affecting = H.legacy_organ_by_zone(type)
H.afflict_stun(20 * 3)
affecting?.inflict_bodypart_damage(
brute = 1,
diff --git a/code/modules/atmospherics/environmental/zas/phoron.dm b/code/modules/atmospherics/environmental/zas/phoron.dm
index 7089db160136..26e563f48c9e 100644
--- a/code/modules/atmospherics/environmental/zas/phoron.dm
+++ b/code/modules/atmospherics/environmental/zas/phoron.dm
@@ -102,7 +102,7 @@ var/image/contamination_overlay = image('icons/effects/contamination.dmi')
domutcheck(src,null)
/mob/living/carbon/human/proc/burn_eyes()
- var/obj/item/organ/internal/eyes/E = internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/E = keyed_organs[ORGAN_KEY_EYES]
if(E)
if(isSynthetic())
return //robotic eyes are not affected
diff --git a/code/modules/biology/README.md b/code/modules/biology/README.md
new file mode 100644
index 000000000000..fb5b3ad5d571
--- /dev/null
+++ b/code/modules/biology/README.md
@@ -0,0 +1,7 @@
+# Biologies
+
+Datumized handling of things like health, life tick, germ handling, etc.
+
+Basically, our codebase has a distinct issue of needing to effectively support multiple medical systems.
+
+That's not easy to do with just if statements or even switch statements, so we datumized it.
diff --git a/code/modules/biology/biology.dm b/code/modules/biology/biology.dm
new file mode 100644
index 000000000000..1a64151b2e1b
--- /dev/null
+++ b/code/modules/biology/biology.dm
@@ -0,0 +1,119 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology
+ //* Hardcoded *//
+
+ /// The type for our organ state. Defaults to not making a state holder.
+ var/organ_state_holder_type
+ /// The type for our mob state. Defaults to not making a state holder.
+ var/mob_state_holder_type
+ /// The biology type we're considered. This is for quick lookups.
+ var/biology_type = NONE
+
+ //* Organs & Mappings *//
+ /// The typepaths to map specific organ slots to, by default.
+ var/list/default_organ_mappings = list(
+ ORGAN_KEY_EXT_HEAD = /obj/item/organ/external/head,
+ ORGAN_KEY_EXT_CHEST = /obj/item/organ/external/chest,
+ ORGAN_KEY_EXT_GROIN = /obj/item/organ/external/groin,
+ ORGAN_KEY_EXT_LEFT_ARM = /obj/item/organ/external/arm/left,
+ ORGAN_KEY_EXT_LEFT_HAND = /obj/item/organ/external/hand/left,
+ ORGAN_KEY_EXT_RIGHT_ARM = /obj/item/organ/external/arm/right,
+ ORGAN_KEY_EXT_RIGHT_HAND = /obj/item/organ/external/hand/right,
+ ORGAN_KEY_EXT_LEFT_LEG = /obj/item/organ/external/leg/left,
+ ORGAN_KEY_EXT_LEFT_FOOT = /obj/item/organ/external/foot/left,
+ ORGAN_KEY_EXT_RIGHT_LEG = /obj/item/organ/external/leg/right,
+ ORGAN_KEY_EXT_RIGHT_FOOT = /obj/item/organ/external/foot/right,
+ )
+ /// Default organ keys we should have.
+ ///
+ /// * Species may override this by key.
+ /// * Anything in this must be in [default_organ_mappings].
+ /// * `ORGAN_KEY_BRAIN` is implicitly in this list.
+ var/list/default_internal_organ_keys = list()
+ /// Half-legacy 'vital' organ key list.
+ ///
+ /// * Organ keys in this list are considered vital. Their removal, death, or destruction will
+ /// result in the death of the host.
+ /// * It's very possible and even sometimes needed to have nothing be vital.
+ /// As an example, in a synth, nothing but the brain is vital, and brain is already
+ /// implicitly vital.
+ var/list/vital_organ_keys = list()
+ #warn hook
+
+ //* Ticking *//
+
+ /// Requires life ticking on the mob's global biological life tick.
+ var/requires_mob_tick = FALSE
+ /// Requires life ticking on an organ's biological life tick.
+ var/requires_organ_tick = FALSE
+
+/**
+ * Called on organ Initialize, or biology change.
+ */
+/datum/biology/proc/on_organ_bind(obj/item/organ/organ, datum/biology_organ_state/state)
+ #warn impl
+
+/**
+ * Called on organ Destroy, or biology change.
+ */
+/datum/biology/proc/on_organ_unbind(obj/item/organ/organ, datum/biology_organ_state/state)
+ #warn impl
+
+/**
+ * Called when a mob receives us for the first time.
+ */
+/datum/biology/proc/on_mob_bind(mob/living/carbon/target, datum/biology_mob_state/state)
+ #warn impl
+
+/**
+ * Called when a mob has us removed; usually from the last organ with our biology being removed from them.
+ */
+/datum/biolgoy/proc/on_mob_unbind(mob/living/carbon/target, datum/biology_mob_state/state)
+ #warn impl
+
+/**
+ * Called when an organ is created in a mob or otherwise inserted into a mob with us.
+ *
+ * * This happens after we are added to the mob, and `on_mob_bind` runs.
+ */
+/datum/biology/proc/on_organ_insert(obj/item/organ/organ, mob/living/carbon/target, datum/biology_organ_state/organ_state, datum/biology_mob_state/target_state)
+ #warn impl
+
+/**
+ * Called when the last organ with us as its biology is removed from or destroyed for a given mob.
+ *
+ * * This happens before we are removed from the mob, and `on_mob_unbind` runs.
+ */
+/datum/biology/proc/on_organ_remove(obj/item/organ/organ, mob/living/carbon/target, datum/biology_organ_state/organ_state, datum/biology_mob_state/target_state)
+ #warn impl
+
+/**
+ * Master life tick hook for the mob.
+ *
+ * @params
+ * * dt - Time of tick in seconds.
+ * * notch - Arbitrary number that should increment by 1 per fire.
+ * This is not a high-precision number, and is only provided so you
+ * may do slow-update handling.
+ * * state - The `/datum/biology_mob_state` on this mob. You may typecast
+ * this to the value of `mob_state_holder_type`.
+ */
+/datum/biology/proc/mob_life_tick(dt, notch, datum/biology_mob_state/state)
+ #warn impl
+
+/**
+ * Master life tick hook for an organ.
+ *
+ * @params
+ * * dt - Time of tick in seconds.
+ * * notch - Arbitrary number that should increment by 1 per fire.
+ * This is not a high-precision number, and is only provided so you
+ * may do slow-update handling.
+ * * organ - The organ being ticked.
+ * * state - The `/datum/biology_organ_state` on this organ. You may typecast
+ * this to the value of `organ_state_holder_type`.
+ */
+/datum/biology/proc/organ_life_tick(dt, notch, obj/item/organ/organ, datum/biology_mob_state/state)
+ #warn impl
diff --git a/code/modules/biology/biology_mob_state.dm b/code/modules/biology/biology_mob_state.dm
new file mode 100644
index 000000000000..2b8e5c16c2fb
--- /dev/null
+++ b/code/modules/biology/biology_mob_state.dm
@@ -0,0 +1,9 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * Holds state for biologies on mob.
+ *
+ * Done this way to allow for more typecasting than a simple key-value list.
+ */
+/datum/biology_mob_state
diff --git a/code/modules/biology/biology_organ_state.dm b/code/modules/biology/biology_organ_state.dm
new file mode 100644
index 000000000000..8089364d31e8
--- /dev/null
+++ b/code/modules/biology/biology_organ_state.dm
@@ -0,0 +1,9 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * Holds state for biologies on a given organ.
+ *
+ * Done this way to allow for more typecasting than a simple key-value list.
+ */
+/datum/biology_organ_state
diff --git a/code/modules/biology/types/crystalline.dm b/code/modules/biology/types/crystalline.dm
new file mode 100644
index 000000000000..f94695ed3b05
--- /dev/null
+++ b/code/modules/biology/types/crystalline.dm
@@ -0,0 +1,29 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology_mob_state/crystalline
+
+/datum/biology_organ_state/crystalline
+
+/datum/biology/crystalline
+ biology_type = BIOLOGY_TYPE_CRYSTALLINE
+
+#warn impl
+
+/datum/biology/crystalline/adherent
+
+#warn impl all
+
+ // has_limbs = list(
+ // BP_TORSO = list("path" = /obj/item/organ/external/chest/crystal),
+ // BP_GROIN = list("path" = /obj/item/organ/external/groin/crystal),
+ // BP_HEAD = list("path" = /obj/item/organ/external/head/crystal),
+ // BP_L_ARM = list("path" = /obj/item/organ/external/arm/crystal),
+ // BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/crystal),
+ // BP_L_HAND = list("path" = /obj/item/organ/external/hand/crystal),
+ // BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/crystal),
+ // BP_L_LEG = list("path" = /obj/item/organ/external/leg/tendril),
+ // BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/tendril/),
+ // BP_L_FOOT = list("path" = /obj/item/organ/external/foot/tendril/),
+ // BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/tendril),
+ // )
diff --git a/code/modules/biology/types/organic.dm b/code/modules/biology/types/organic.dm
new file mode 100644
index 000000000000..074b14217357
--- /dev/null
+++ b/code/modules/biology/types/organic.dm
@@ -0,0 +1,26 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology_mob_state/organic
+
+/datum/biology_organ_state/organic
+
+/datum/biology/organic
+ biology_type = BIOLOGY_TYPE_HUMAN
+ default_organ_mappings = list(
+ )
+ default_internal_organ_keys = list(
+ )
+
+#warn impl + merge in below
+
+ // O_HEART = /obj/item/organ/internal/heart,
+ // O_LUNGS = /obj/item/organ/internal/lungs,
+ // O_VOICE = /obj/item/organ/internal/voicebox,
+ // O_LIVER = /obj/item/organ/internal/liver,
+ // O_KIDNEYS = /obj/item/organ/internal/kidneys,
+ // O_BRAIN = /obj/item/organ/internal/brain,
+ // O_APPENDIX = /obj/item/organ/internal/appendix,
+ // O_EYES = /obj/item/organ/internal/eyes,
+ // O_STOMACH = /obj/item/organ/internal/stomach,
+ // O_INTESTINE = /obj/item/organ/internal/intestine,
diff --git a/code/modules/biology/types/organic/chimeric.dm b/code/modules/biology/types/organic/chimeric.dm
new file mode 100644
index 000000000000..93245e55e9ec
--- /dev/null
+++ b/code/modules/biology/types/organic/chimeric.dm
@@ -0,0 +1,11 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology_mob_state/organic/chimeric
+
+/datum/biology_organ_state/organic/chimeric
+
+/datum/biology/organic/chimeric
+ biology_type = BIOLOGY_TYPE_CHIMERA
+
+#warn impl
diff --git a/code/modules/biology/types/organic/diona.dm b/code/modules/biology/types/organic/diona.dm
new file mode 100644
index 000000000000..0cd40f79efde
--- /dev/null
+++ b/code/modules/biology/types/organic/diona.dm
@@ -0,0 +1,11 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology_mob_state/organic/diona
+
+/datum/biology_organ_state/organic/diona
+
+/datum/biology/organic/diona
+ biology_type = BIOLOGY_TYPE_DIONA
+
+#warn impl
diff --git a/code/modules/biology/types/organic/phoronoid.dm b/code/modules/biology/types/organic/phoronoid.dm
new file mode 100644
index 000000000000..40f95573916c
--- /dev/null
+++ b/code/modules/biology/types/organic/phoronoid.dm
@@ -0,0 +1,18 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology/organic/phoronoid
+ default_organ_mappings = list(
+ )
+ default_internal_organ_keys = list(
+ )
+
+#warn impl + merge in below
+
+ // O_HEART = /obj/item/organ/internal/heart,
+ // O_LUNGS = /obj/item/organ/internal/lungs,
+ // O_VOICE = /obj/item/organ/internal/voicebox,
+ // O_LIVER = /obj/item/organ/internal/liver,
+ // O_KIDNEYS = /obj/item/organ/internal/kidneys,
+ // O_BRAIN = /obj/item/organ/internal/brain,
+ // O_EYES = /obj/item/organ/internal/eyes,
diff --git a/code/modules/biology/types/organic/plant.dm b/code/modules/biology/types/organic/plant.dm
new file mode 100644
index 000000000000..3366344e4d3d
--- /dev/null
+++ b/code/modules/biology/types/organic/plant.dm
@@ -0,0 +1,11 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology_mob_state/organic/plant
+
+/datum/biology_organ_state/organic/plant
+
+/datum/biology/organic/plant
+ biology_type = BIOLOGY_TYPE_PLANT
+
+#warn impl
diff --git a/code/modules/biology/types/organic/promethean.dm b/code/modules/biology/types/organic/promethean.dm
new file mode 100644
index 000000000000..00729c71dee5
--- /dev/null
+++ b/code/modules/biology/types/organic/promethean.dm
@@ -0,0 +1,11 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology_mob_state/organic/promethean
+
+/datum/biology_organ_state/organic/promethean
+
+/datum/biology/organic/promethean
+ biology_type = BIOLOGY_TYPE_SLIME
+
+#warn impl
diff --git a/code/modules/biology/types/organic/replicant.dm b/code/modules/biology/types/organic/replicant.dm
new file mode 100644
index 000000000000..c98749c9d691
--- /dev/null
+++ b/code/modules/biology/types/organic/replicant.dm
@@ -0,0 +1,28 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * Whereas vatborn are just cloned humans, replicants (not to be confused with Replikas from Signalis)
+ * are fake-people made out of alien tech that do not actually have anything in common with humans other
+ * than perhaps appearance.
+ */
+/datum/biology/organic/replicant
+ default_organ_mappings = list(
+ )
+ default_internal_organ_keys = list(
+ )
+
+#warn impl
+
+ // O_HEART = /obj/item/organ/internal/heart/replicant,
+ // O_LUNGS = /obj/item/organ/internal/lungs/replicant,
+ // O_VOICE = /obj/item/organ/internal/voicebox/replicant,
+ // O_LIVER = /obj/item/organ/internal/liver/replicant,
+ // O_KIDNEYS = /obj/item/organ/internal/kidneys/replicant,
+ // O_BRAIN = /obj/item/organ/internal/brain/replicant/torso,
+ // O_EYES = /obj/item/organ/internal/eyes/replicant,
+ // O_AREJECT = /obj/item/organ/internal/immunehub/replicant,
+ // O_VENTC = /obj/item/organ/internal/metamorphgland/replicant,
+ // O_VRLINK = /obj/item/organ/internal/brainmirror,
+ // O_STOMACH = /obj/item/organ/internal/stomach,
+ // O_INTESTINE = /obj/item/organ/internal/intestine,
diff --git a/code/modules/biology/types/organic/xenomorph.dm b/code/modules/biology/types/organic/xenomorph.dm
new file mode 100644
index 000000000000..95a09df48d67
--- /dev/null
+++ b/code/modules/biology/types/organic/xenomorph.dm
@@ -0,0 +1,18 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology/organic/xenomorph
+ default_organ_mappings = list(
+ )
+ default_internal_organ_keys = list(
+ )
+
+#warn impl + merge in below
+
+ // O_HEART = /obj/item/organ/internal/heart,
+ // O_LUNGS = /obj/item/organ/internal/lungs,
+ // O_VOICE = /obj/item/organ/internal/voicebox,
+ // O_LIVER = /obj/item/organ/internal/liver,
+ // O_KIDNEYS = /obj/item/organ/internal/kidneys,
+ // O_BRAIN = /obj/item/organ/internal/brain,
+ // O_EYES = /obj/item/organ/internal/eyes,
diff --git a/code/modules/biology/types/simple.dm b/code/modules/biology/types/simple.dm
new file mode 100644
index 000000000000..98a847805ee5
--- /dev/null
+++ b/code/modules/biology/types/simple.dm
@@ -0,0 +1,20 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * These basically make you work like a simplemob, and only
+ * just masquarade as certain other biologies for the purposes of healing.
+ */
+/datum/biology/simple
+
+/datum/biology/simple/pretend_organic
+ biology_type = BIOLOGY_TYPE_HUMAN
+
+/datum/biology/simple/pretend_synthetic
+ biology_type = BIOLOGY_TYPE_SYNTH
+
+/datum/biology/simple/pretend_nanites
+ biology_type = BIOLOGY_TYPE_NANITES
+
+/datum/biology/simple/pretend_slime
+ biology_type = BIOLOGY_TYPE_SLIME
diff --git a/code/modules/biology/types/synthetic.dm b/code/modules/biology/types/synthetic.dm
new file mode 100644
index 000000000000..ae535e2984b8
--- /dev/null
+++ b/code/modules/biology/types/synthetic.dm
@@ -0,0 +1,11 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology_mob_state/synthetic
+
+/datum/biology_organ_state/synthetic
+
+/datum/biology/synthetic
+ biology_type = BIOLOGY_TYPE_SYNTH
+
+#warn impl
diff --git a/code/modules/biology/types/synthetic/nanoswarm.dm b/code/modules/biology/types/synthetic/nanoswarm.dm
new file mode 100644
index 000000000000..ee6089e86ec3
--- /dev/null
+++ b/code/modules/biology/types/synthetic/nanoswarm.dm
@@ -0,0 +1,16 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/biology_mob_state/synthetic/nanoswarm
+
+/datum/biology_organ_state/synthetic/nanoswarm
+
+/datum/biology/synthetic/nanoswarm
+ biology_type = BIOLOGY_TYPE_NANITES
+
+ default_organ_mappings = list(
+ ORGAN_KEY_BRAIN = /obj/item/organ/internal/brain/positronic/nano,
+ )
+ #warn impl rest of mappings
+
+#warn impl
diff --git a/code/modules/detectivework/tools/sample_kits.dm b/code/modules/detectivework/tools/sample_kits.dm
index 5deb83bfa2e6..f60af8508090 100644
--- a/code/modules/detectivework/tools/sample_kits.dm
+++ b/code/modules/detectivework/tools/sample_kits.dm
@@ -98,15 +98,8 @@
user.visible_message("\The [user] tries to take prints from \the [H], but they move away.")
return
- if(user.zone_sel.selecting == "r_hand" || user.zone_sel.selecting == "l_hand")
- var/has_hand
- var/obj/item/organ/external/O = H.organs_by_name["r_hand"]
- if(istype(O) && !O.is_stump())
- has_hand = 1
- else
- O = H.organs_by_name["l_hand"]
- if(istype(O) && !O.is_stump())
- has_hand = 1
+ if(target_zone == "r_hand" || target_zone == "l_hand")
+ var/has_hand = H.get_non_stump_organ_for_zone(TARGET_ZONE_LEFT_HAND) || H.get_non_stump_organ_for_zone(TARGET_ZONE_RIGHT_HAND)
if(!has_hand)
to_chat(user, "They don't have any hands.")
return
diff --git a/code/modules/detectivework/tools/swabs.dm b/code/modules/detectivework/tools/swabs.dm
index cf875906d2c3..387f01cde317 100644
--- a/code/modules/detectivework/tools/swabs.dm
+++ b/code/modules/detectivework/tools/swabs.dm
@@ -28,7 +28,7 @@
return
if(user.zone_sel.selecting == O_MOUTH)
- if(!H.organs_by_name[BP_HEAD])
+ if(!H.get_organ_for_zone(TARGET_ZONE_HEAD))
to_chat(user, "They don't have a head.")
return
diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm
index 4992efb9a1ea..665542fe4c10 100644
--- a/code/modules/food/food/snacks.dm
+++ b/code/modules/food/food/snacks.dm
@@ -1891,7 +1891,7 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.visible_message("A screeching creature bursts out of [M]'s chest!")
- var/obj/item/organ/external/organ = H.get_organ(BP_TORSO)
+ var/obj/item/organ/external/organ = H.legacy_organ_by_zone(BP_TORSO)
organ?.inflict_bodypart_damage(
brute = 50,
weapon_descriptor = "bursting",
diff --git a/code/modules/food/machinery/appliance/fryer.dm b/code/modules/food/machinery/appliance/fryer.dm
index 03ee80157ae5..42c5a01f9020 100644
--- a/code/modules/food/machinery/appliance/fryer.dm
+++ b/code/modules/food/machinery/appliance/fryer.dm
@@ -167,7 +167,7 @@
var/nopain
if(ishuman(victim) && user.zone_sel.selecting != "groin" && user.zone_sel.selecting != "chest")
var/mob/living/carbon/human/H = victim
- E = H.get_organ(user.zone_sel.selecting)
+ E = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(!E || E.species.species_flags & NO_PAIN)
nopain = 2
else if(E.robotic >= ORGAN_ROBOT)
diff --git a/code/modules/genetics/side_effects.dm b/code/modules/genetics/side_effects.dm
index 0564c630fc96..1ece08bdfcb1 100644
--- a/code/modules/genetics/side_effects.dm
+++ b/code/modules/genetics/side_effects.dm
@@ -50,7 +50,7 @@
/datum/genetics/side_effect/genetic_burn/finish(mob/living/carbon/human/H)
if(!H.reagents.has_reagent("dexalin"))
for(var/organ_name in BP_ALL)
- var/obj/item/organ/external/E = H.get_organ(organ_name)
+ var/obj/item/organ/external/E = H.legacy_organ_by_zone(organ_name)
E.inflict_bodypart_damage(
burn = 5,
)
@@ -68,7 +68,7 @@
/datum/genetics/side_effect/bone_snap/finish(mob/living/carbon/human/H)
if(!H.reagents.has_reagent("bicaridine"))
var/organ_name = pick(BP_ALL)
- var/obj/item/organ/external/E = H.get_organ(organ_name)
+ var/obj/item/organ/external/E = H.legacy_organ_by_zone(organ_name)
E.inflict_bodypart_damage(
brute = 20,
)
diff --git a/code/modules/hardsuits/_rig.dm b/code/modules/hardsuits/_rig.dm
index 55f51f8b0877..a4ab8662cf18 100644
--- a/code/modules/hardsuits/_rig.dm
+++ b/code/modules/hardsuits/_rig.dm
@@ -1185,8 +1185,8 @@
return wearer.pulledby.relaymove(wearer, direction)
else if(istype(wearer.buckled, /obj/structure/bed/chair/wheelchair))
if(ishuman(wearer.buckled))
- var/obj/item/organ/external/l_hand = wearer.get_organ("l_hand")
- var/obj/item/organ/external/r_hand = wearer.get_organ("r_hand")
+ var/obj/item/organ/external/l_hand = wearer.legacy_organ_by_zone("l_hand")
+ var/obj/item/organ/external/r_hand = wearer.legacy_organ_by_zone("r_hand")
if((!l_hand || (l_hand.status & ORGAN_DESTROYED)) && (!r_hand || (r_hand.status & ORGAN_DESTROYED)))
return // No hands to drive your chair? Tough luck!
wearer_move_delay += 2
diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm
index d8caa2f378ff..0825b5695bec 100644
--- a/code/modules/holodeck/HolodeckObjects.dm
+++ b/code/modules/holodeck/HolodeckObjects.dm
@@ -143,7 +143,7 @@
playsound(target.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
target.visible_message("[user] has attempted to punch [target]!")
return TRUE
- var/obj/item/organ/external/affecting = target.get_organ(ran_zone(user.zone_sel.selecting))
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(ran_zone(user.zone_sel.selecting))
var/armor_block = target.run_armor_check(affecting, "melee")
var/armor_soak = target.get_armor_soak(affecting, "melee")
diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm
index 149a9f6bd38a..12799bc9a797 100644
--- a/code/modules/hydroponics/seed.dm
+++ b/code/modules/hydroponics/seed.dm
@@ -122,7 +122,7 @@
if(blocked >= 100)
return
- var/obj/item/organ/external/affecting = target.get_organ(target_limb)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(target_limb)
var/damage = 0
var/has_edge = 0
if(get_trait(TRAIT_CARNIVOROUS) >= 2)
diff --git a/code/modules/keybindings/keybind/human.dm b/code/modules/keybindings/keybind/human.dm
index 4de1ce6a37c3..e423d21d6da1 100644
--- a/code/modules/keybindings/keybind/human.dm
+++ b/code/modules/keybindings/keybind/human.dm
@@ -13,7 +13,7 @@
/datum/keybinding/human/quick_equip/down(client/user)
var/mob/living/carbon/human/H = user.mob
- H.quick_equip()
+ H.attempt_smart_equip()
return TRUE
/datum/keybinding/human/quick_equipbelt
diff --git a/code/modules/language/languages/antagonist/xenomorph.dm b/code/modules/language/languages/antagonist/xenomorph.dm
index 16d1da49ac22..bcb49e7edd9b 100644
--- a/code/modules/language/languages/antagonist/xenomorph.dm
+++ b/code/modules/language/languages/antagonist/xenomorph.dm
@@ -28,7 +28,7 @@
var/mob/living/carbon/M = other
if(!istype(M))
return 1
- if(locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
+ if(M.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
return 1
return 0
diff --git a/code/modules/materials/definitions/organic/resin.dm b/code/modules/materials/definitions/organic/resin.dm
index 63eed91c346a..3fc6026138df 100644
--- a/code/modules/materials/definitions/organic/resin.dm
+++ b/code/modules/materials/definitions/organic/resin.dm
@@ -56,13 +56,13 @@
/datum/prototype/material/resin/can_open_material_door(var/mob/living/user)
var/mob/living/carbon/M = user
- if(istype(M) && locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
+ if(istype(M) && M.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
return 1
return 0
/datum/prototype/material/resin/wall_touch_special(var/turf/simulated/wall/W, var/mob/living/L)
var/mob/living/carbon/M = L
- if(istype(M) && locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
+ if(istype(M) && M.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
to_chat(M, "\The [W] shudders under your touch, starting to become porous.")
playsound(W, 'sound/effects/attackblob.ogg', 50, 1)
if(do_after(L, 5 SECONDS))
diff --git a/code/modules/mob/_modifiers/unholy.dm b/code/modules/mob/_modifiers/unholy.dm
index b7cac38a01e6..c565b33c18de 100644
--- a/code/modules/mob/_modifiers/unholy.dm
+++ b/code/modules/mob/_modifiers/unholy.dm
@@ -127,13 +127,11 @@
if(O.damage <= 5 && O.organ_tag == O_EYES) // Fix eyes
H.remove_blindness_source(TRAIT_BLINDNESS_EYE_DMG)
- for(var/obj/item/organ/external/O in H.organs) // Fix limbs, no matter if they are Man or Machine.
+ for(var/obj/item/organ/external/O as anything in H.external_organs) // Fix limbs, no matter if they are Man or Machine.
O.heal_damage(rand(1,3), rand(1,3), internal = 1, robo_repair = 1)
// check limbs
- for(var/obj/item/organ/E in H.bad_external_organs)
- // Fix bones
- var/obj/item/organ/external/affected = E
+ for(var/obj/item/organ/external/affected in H.external_organs)
if((affected.damage < affected.min_broken_damage) && (affected.status & ORGAN_BROKEN))
affected.status &= ~ORGAN_BROKEN
// fix IB
diff --git a/code/modules/mob/grab.dm b/code/modules/mob/grab.dm
index 0ceb80369444..dcd3586e6874 100644
--- a/code/modules/mob/grab.dm
+++ b/code/modules/mob/grab.dm
@@ -511,7 +511,7 @@
/obj/item/grab/proc/inspect_organ(mob/living/carbon/human/H, mob/user, var/target_zone)
- var/obj/item/organ/external/E = H.get_organ(target_zone)
+ var/obj/item/organ/external/E = H.legacy_organ_by_zone(target_zone)
if(!E || E.is_stump())
to_chat(user, "[H] is missing that bodypart.")
@@ -556,7 +556,7 @@
to_chat(attacker, "You require a better grab to do this.")
return
- var/obj/item/organ/external/organ = target.get_organ(check_zone(target_zone))
+ var/obj/item/organ/external/organ = target.legacy_organ_by_zone(check_zone(target_zone))
if(!organ || organ.dislocated == -1)
return
diff --git a/code/modules/mob/inventory/inventory.dm b/code/modules/mob/inventory/inventory.dm
index e6f2c80548d4..03d975066d2f 100644
--- a/code/modules/mob/inventory/inventory.dm
+++ b/code/modules/mob/inventory/inventory.dm
@@ -78,14 +78,22 @@
/**
* returns list() of items with body_cover_flags
*/
-/datum/inventory/proc/items_that_cover(cover_flags)
- if(cover_flags == NONE)
+/datum/inventory/proc/query_body_cover_items(body_cover_flags)
+ if(body_cover_flags == NONE)
return list()
. = list()
for(var/obj/item/I as anything in owner.get_equipped_items())
- if(I.body_cover_flags & cover_flags)
+ if(I.body_cover_flags & body_cover_flags)
. += I
+/**
+ * gets all body_cover_flag's covered by clothing
+ */
+/datum/inventory/proc/query_body_cover()
+ . = NONE
+ for(var/obj/item/I as anything in owner.get_equipped_items())
+ . |= I.body_cover_flags
+
//* Slots *//
/**
diff --git a/code/modules/mob/inventory/inventory_slot.dm b/code/modules/mob/inventory/inventory_slot.dm
index a4afb326839e..066873dc0ce5 100644
--- a/code/modules/mob/inventory/inventory_slot.dm
+++ b/code/modules/mob/inventory/inventory_slot.dm
@@ -691,7 +691,7 @@ GLOBAL_LIST_EMPTY(inventory_slot_type_cache)
if((casted_human.wear_suit?.inv_hide_flags | casted_human.w_uniform?.inv_hide_flags) & HIDESHOES)
return FALSE
for(var/bodypart in list(BP_L_FOOT, BP_R_FOOT))
- var/obj/item/organ/external/foot/foot = casted_human.get_organ(bodypart)
+ var/obj/item/organ/external/foot/foot = casted_human.legacy_organ_by_zone(bodypart)
if(istype(foot) && foot.is_hidden_by_tail())
return FALSE
return ..()
diff --git a/code/modules/mob/life.dm b/code/modules/mob/life.dm
index 6b213871614c..5c9ace3e08a5 100644
--- a/code/modules/mob/life.dm
+++ b/code/modules/mob/life.dm
@@ -16,11 +16,17 @@
. = SEND_SIGNAL(src, COMSIG_MOB_ON_LIFE, seconds, times_fired)
+ var/tick_types = LIFE_TICK_BIOLOGICAL | LIFE_TICK_PHYSICAL
+
if(!(. & COMPONENT_INTERRUPT_PHYSICAL_LIFE))
PhysicalLife(seconds, times_fired)
+ tick_types &= ~LIFE_TICK_PHYSICAL
if(!(. & COMPONENT_INTERRUPT_BIOLOGICAL_LIFE))
BiologicalLife(seconds, times_fired)
+ tick_types &= ~LIFE_TICK_BIOLOGICAL
+
+ on_life_tick(seconds, times_fired, tick_types)
handle_modifiers(.) // Needs to be done even if in nullspace.
@@ -31,10 +37,18 @@
spell_master.update_spells(0, src)
ability_master?.update_abilities(0, src)
+/**
+ * Handles what should happen on a life tick.
+ */
+/mob/proc/on_life_tick(seconds, notch, tick_types)
+ return
+
/**
* processes physical life processes like being on fire
* return TRUE if deleted
*
+ * todo: deprecate
+ *
* always call parent and check for ..() at start - if nonzero is returned, we should halt as we got deleted or killed
*/
/mob/proc/PhysicalLife(seconds, times_fired)
@@ -45,6 +59,8 @@
* processes biological life processes like metabolism
* return TRUE if deleted
*
+ * todo: deprecate
+ *
* always call parent and check for ..() at start - if nonzero is returned, we should halt as we got deleted or killed
*/
/mob/proc/BiologicalLife(seconds, times_fired)
diff --git a/code/modules/mob/living/butchering.dm b/code/modules/mob/living/butchering.dm
index 923929519b0c..e5d93331b2ee 100644
--- a/code/modules/mob/living/butchering.dm
+++ b/code/modules/mob/living/butchering.dm
@@ -27,8 +27,6 @@
/// Does it gib when butchered?
var/gib_on_butchery = FALSE
- /// Does it drop or spawn in organs to drop when butchered?
- var/butchery_drops_organs = TRUE
/// Associated list, path = number.
var/list/butchery_loot
@@ -65,43 +63,6 @@
butchery_loot.Cut()
butchery_loot = null
- if(LAZYLEN(organs)&& butchery_drops_organs)
- organs_by_name.Cut()
-
- for(var/path in organs)
- if(ispath(path))
- var/obj/item/organ/external/neworg = new path(src)
- neworg.name = "[name] [neworg.name]"
- neworg.meat_type = meat_type
-
- if(istype(src, /mob/living/simple_mob))
- var/mob/living/simple_mob/SM = src
- if(SM.limb_icon)
- neworg.force_icon = SM.limb_icon
- neworg.force_icon_key = SM.limb_icon_key
-
- organs |= neworg
- organs -= path
-
- for(var/obj/item/organ/OR in organs)
- OR.removed()
- organs -= OR
-
- if(LAZYLEN(internal_organs)&& butchery_drops_organs)
- internal_organs_by_name.Cut()
-
- for(var/path in internal_organs)
- if(ispath(path))
- var/obj/item/organ/neworg = new path(src, TRUE)
- neworg.name = "[name] [neworg.name]"
- neworg.meat_type = meat_type
- internal_organs |= neworg
- internal_organs -= path
-
- for(var/obj/item/organ/OR in internal_organs)
- OR.removed()
- internal_organs -= OR
-
if(!ckey)
if(issmall(src))
user?.visible_message(SPAN_DANGER("[user] chops up \the [src]!"))
diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm
index 64741a5c14fc..8b1b884d4c7a 100644
--- a/code/modules/mob/living/carbon/alien/larva/larva.dm
+++ b/code/modules/mob/living/carbon/alien/larva/larva.dm
@@ -22,4 +22,4 @@
/mob/living/carbon/alien/larva/Initialize(mapload)
. = ..()
add_language(LANGUAGE_XENO) //Bonus language.
- internal_organs |= new /obj/item/organ/internal/xenos/hivenode(src)
+ internal_organs |= new /obj/item/organ/internal/xenomorph/hivenode(src)
diff --git a/code/modules/mob/living/carbon/carbon-death.dm b/code/modules/mob/living/carbon/carbon-death.dm
new file mode 100644
index 000000000000..70440cb8c6e7
--- /dev/null
+++ b/code/modules/mob/living/carbon/carbon-death.dm
@@ -0,0 +1,18 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/mob/living/carbon/gib()
+ var/turf/our_turf = get_turf(src)
+ if(our_turf)
+ for(var/obj/item/organ/organ as anything in get_organs())
+ // check if they should be obliterated with a horrific if-pyramid of doom
+ // todo: customizable dropping external organs?
+ if(!istype(organ, /obj/item/organ/external))
+ if(!organ.always_drop_on_gib)
+ if(!organ.always_drop_on_everything)
+ continue
+ #warn remove
+ // todo: customizable throwing for gib
+ var/list/possible_throw_turfs = RANGE_TURFS(3, our_turf)
+ var/turf/throw_turf = SAFEPICK(possible_throw_turfs)
+ organ.throw_at(throw_turf, 3, 1, THROW_AT_NEVER_HIT_PUSH)
diff --git a/code/modules/mob/living/carbon/carbon-defense.dm b/code/modules/mob/living/carbon/carbon-defense.dm
index 8471cf172b62..b96862a28379 100644
--- a/code/modules/mob/living/carbon/carbon-defense.dm
+++ b/code/modules/mob/living/carbon/carbon-defense.dm
@@ -10,7 +10,7 @@
// perform normal baymiss
. = get_zone_with_miss_chance(., src, -10, TRUE)
// check if we even have that organ; if not, they automatically miss
- if(!get_organ(.))
+ if(!legacy_organ_by_zone(.))
return null
//* Misc Effects *//
diff --git a/code/modules/mob/living/carbon/carbon-hands.dm b/code/modules/mob/living/carbon/carbon-hands.dm
index 2d6aa9f2d653..56fc3bd8dd7c 100644
--- a/code/modules/mob/living/carbon/carbon-hands.dm
+++ b/code/modules/mob/living/carbon/carbon-hands.dm
@@ -93,6 +93,6 @@
*
* * in mobs with no logical arm and only a hand, this returns the hand
*/
-/mob/living/carbon/proc/get_active_hand_organ(index)
+/mob/living/carbon/proc/get_active_hand_organ()
RETURN_TYPE(/obj/item/organ/external)
return get_hand_organ(active_hand)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/carbon-life.dm
similarity index 60%
rename from code/modules/mob/living/carbon/life.dm
rename to code/modules/mob/living/carbon/carbon-life.dm
index d4a8b928a1e0..f6af071e6b09 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/carbon-life.dm
@@ -1,5 +1,9 @@
//* This file is explicitly licensed under the MIT license. *//
-//* Copyright (c) 2024 silicons *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/mob/living/carbon/on_life_tick(seconds, notch, tick_types)
+ . = ..()
+ #warn biology
/mob/living/carbon/forced_metabolism(seconds)
. = ..()
diff --git a/code/modules/mob/living/carbon/carbon-organs.dm b/code/modules/mob/living/carbon/carbon-organs.dm
new file mode 100644
index 000000000000..cec27ffb0477
--- /dev/null
+++ b/code/modules/mob/living/carbon/carbon-organs.dm
@@ -0,0 +1,135 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+//* API - Get *//
+
+/**
+ * Get all organs.
+ */
+/mob/living/carbon/proc/get_organs()
+ return external_organs + internal_organs
+
+/**
+ * Get all internal organs.
+ */
+/mob/living/carbon/proc/get_internal_organs()
+ return internal_organs.Copy()
+
+/**
+ * Get all external organs
+ */
+/mob/living/carbon/proc/get_external_organs()
+ return external_organs.Copy()
+
+/**
+ * Get **an** organ of a key.
+ */
+/mob/living/carbon/proc/get_organ_by_key(key) as /obj/item/organ
+ RETURN_TYPE(/obj/item/organ)
+ return keyed_organs[key]
+
+/**
+ * Get **all** organs of a key.
+ */
+/mob/living/carbon/proc/get_organs_by_key(key) as /list
+ RETURN_TYPE(/list)
+ . = list()
+ if(keyed_organs[key])
+ . += keyed_organs[key]
+
+/**
+ * Get an external organ by target zone.
+ */
+/mob/living/carbon/proc/get_organ_for_zone(target_zone) as /obj/item/organ/external
+ var/static/list/target_zone_rewrites = list(
+ TARGET_ZONE_HEAD = ORGAN_KEY_EXT_HEAD,
+ TARGET_ZONE_EYES = ORGAN_KEY_EXT_HEAD,
+ TARGET_ZONE_MOUTH = ORGAN_KEY_EXT_HEAD,
+ TARGET_ZONE_LEFT_ARM = ORGAN_KEY_EXT_LEFT_ARM,
+ TARGET_ZONE_LEFT_HAND = ORGAN_KEY_EXT_LEFT_HAND,
+ TARGET_ZONE_RIGHT_ARM = ORGAN_KEY_EXT_RIGHT_ARM,
+ TARGET_ZONE_RIGHT_HAND = ORGAN_KEY_EXT_RIGHT_HAND,
+ TARGET_ZONE_GROIN = ORGAN_KEY_EXT_GROIN,
+ TARGET_ZONE_LEFT_LEG = ORGAN_KEY_EXT_LEFT_LEG,
+ TARGET_ZONE_LEFT_FOOT = ORGAN_KEY_EXT_LEFT_FOOT,
+ TARGET_ZONE_RIGHT_LEG = ORGAN_KEY_EXT_RIGHT_LEG,
+ TARGET_ZONE_RIGHT_FOOT = ORGAN_KEY_EXT_RIGHT_FOOT,
+ )
+ return keyed_organs[target_zone_rewrites[target_zone]]
+
+/**
+ * Get internal organs by target zone.
+ */
+/mob/living/carbon/proc/get_internal_organs_for_zone(target_zone) as /list
+ var/obj/item/organ/external/bodypart = get_organ_for_zone(target_zone)
+ return bodypart ? bodypart.get_internal_organs() : list()
+
+/**
+ * Get an external organ by target zone, if that organ is not a stump and is otherwise physically
+ * still that organ by shape.
+ */
+/mob/living/carbon/proc/get_non_stump_organ_for_zone(target_zone) as /obj/item/organ/external
+ var/static/list/target_zone_rewrites = list(
+ TARGET_ZONE_HEAD = ORGAN_KEY_EXT_HEAD,
+ TARGET_ZONE_EYES = ORGAN_KEY_EXT_HEAD,
+ TARGET_ZONE_MOUTH = ORGAN_KEY_EXT_HEAD,
+ TARGET_ZONE_LEFT_ARM = ORGAN_KEY_EXT_LEFT_ARM,
+ TARGET_ZONE_LEFT_HAND = ORGAN_KEY_EXT_LEFT_HAND,
+ TARGET_ZONE_RIGHT_ARM = ORGAN_KEY_EXT_RIGHT_ARM,
+ TARGET_ZONE_RIGHT_HAND = ORGAN_KEY_EXT_RIGHT_HAND,
+ TARGET_ZONE_GROIN = ORGAN_KEY_EXT_GROIN,
+ TARGET_ZONE_LEFT_LEG = ORGAN_KEY_EXT_LEFT_LEG,
+ TARGET_ZONE_LEFT_FOOT = ORGAN_KEY_EXT_LEFT_FOOT,
+ TARGET_ZONE_RIGHT_LEG = ORGAN_KEY_EXT_RIGHT_LEG,
+ TARGET_ZONE_RIGHT_FOOT = ORGAN_KEY_EXT_RIGHT_FOOT,
+ )
+ var/obj/item/organ/external/fetched = keyed_organs[target_zone_rewrites[target_zone]]
+ return (fetched && !fetched.is_stump()) ? fetched : null
+
+//* API - Insert / Remove *//
+
+/**
+ * called on organ insert
+ *
+ * @params
+ * * organ - the organ
+ * * from_init - we are performing initial setup in Initialize() after we've grabbed our organs and templates from species / persistence.
+ * this is not set in any other case.
+ */
+/mob/living/carbon/proc/on_organ_insert(obj/item/organ/organ, from_init)
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
+
+/**
+ * called on insert
+ *
+ * @params
+ * * organ - the organ
+ * * from_qdel - we and the organ are being qdeleted in the QDEL_LIST loop.
+ * this is not set in any other case, including on gib and set_species().
+ */
+/mob/living/carbon/proc/on_organ_remove(obj/item/organ/organ, from_qdel)
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
+
+#warn impl
+
+//! Usage of the below procs is heavily discouraged. They're just here to aid in transition. !//
+
+/**
+ * legacy: bodyzone to organ. technically works with internal organ keys too but please don't
+ */
+/mob/living/carbon/proc/legacy_organ_by_zone(what = BP_TORSO)
+ // you'll notice this proc is the same as get_organ_for_zone.
+ // it's because this proc doesn't have an assumption that we'll pass in only target zones.
+ var/static/list/target_zone_rewrites = list(
+ O_EYES = BP_HEAD,
+ O_MOUTH = BP_HEAD,
+ )
+ return keyed_organs[what]
+
+/**
+ * legacy: get organ of type. **DANGEROUS.**
+ */
+/mob/living/carbon/proc/legacy_organ_by_type(type)
+ return (locate(type) in internal_organs) || (locate(type) in external_organs)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 4e26578962f9..8b495a1d60f9 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -1,3 +1,54 @@
+/**
+ * ## Carbon Mobs
+ *
+ * One of the base-types of 'real' (living) mobs.
+ *
+ * ## Composition:
+ * * Organs: Comprises our internals, able to hook onto events, life processing, etc.
+ * Organs can be internal or external. External organs are bodyparts.
+ * All organs, minus root organs, have a parent organ.
+ * We can have one or many root organs.
+ * * Biologies: Our life handling. Organs can have separate biologies.
+ * See `code/modules/biology` for details.
+ * * Species: Our template. Determines what we start with and should have.
+ */
+/mob/living/carbon
+ //* Biologies *//
+ #warn impl
+
+ //* Organs *//
+ /// All /obj/item/organ/internal.
+ var/list/obj/item/organ/internal/internal_organs = list()
+ /// All /obj/item/organ/external.
+ var/list/obj/item/organ/external/external_organs = list()
+ /// Keyed organs.
+ ///
+ /// Things to keep in mind:
+ /// * An organ being in this list usually but not always means it's the only organ of that key in us.
+ /// This is why you shouldn't use this instead of helper procs; organ semnatics are complex and is definitely
+ /// handled by the organ itself. Global rules for what can/can't happen are rare.
+ ///
+ /// Allowed usages:
+ /// * Directly accessing an organ by key.
+ /// If you do this, you must know what the semantics of that key is. It doesn't necessarily
+ /// even need to be a single organ!
+ ///
+ /// Disallowed usages:
+ /// * Accessing an organ by **targeting zone.** Despite targeting zone being the same BP_* keys as
+ /// the ones we're using here, we do internal transforms and translations to translate from the
+ /// targeting doll to the real organ.
+ /// * Pretty much any other use case.
+ ///
+ /// If you're using it for some other reason, you should consider using or making a helper instead.
+ var/list/keyed_organs = list()
+ /// Same as `keyed_organs`, but also includes `legacy_organ_tag`.
+ ///
+ /// * This is so we don't have to rewrite the whole codebase, instead of gradually converting
+ /// organs over to keys once we verify their behavior and ensure that there's a point
+ /// to continuing to key said organ.
+ var/list/legacy_organ_by_tag = list()
+ #warn impl; make sure organ_key gets put in here anyways
+
/mob/living/carbon/Initialize(mapload)
. = ..()
//setup reagent holders
@@ -9,11 +60,17 @@
default_language = RSlanguages.legacy_resolve_language_name(species_language)
/mob/living/carbon/Destroy()
- qdel(ingested)
- qdel(touching)
+ QDEL_LIST(internal_organs)
+ QDEL_LIST(external_organs)
+ //! REMOVE THESE WHEN ORGANS ARE FULLY REFACTORED
+ if(!length(keyed_organs))
+ stack_trace("keyed organs wasn't cleared")
+ if(!length(legacy_organ_by_tag))
+ stack_trace("legacy organ lookup waasn't cleared")
+ //! END
+ QDEL_NULL(ingested)
+ QDEL_NULL(touching)
// We don't qdel(bloodstr) because it's the same as qdel(reagents)
- for(var/guts in internal_organs)
- qdel(guts)
for(var/food in stomach_contents)
qdel(food)
return ..()
@@ -26,16 +83,6 @@
if(species) // todo: sigh we need to talk about init order; this shouldn't be needed
inventory.set_inventory_slots(species.inventory_slots)
-/mob/living/carbon/BiologicalLife(seconds, times_fired)
- if((. = ..()))
- return
-
- handle_viruses()
-
- // Increase germ_level regularly
- if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level
- germ_level++
-
/mob/living/carbon/gib()
for(var/mob/M in src)
if(M in src.stomach_contents)
@@ -70,7 +117,7 @@
src.visible_message("[src] examines [T.himself].", \
SPAN_NOTICE("You check yourself for injuries."))
- for(var/obj/item/organ/external/org in H.organs)
+ for(var/obj/item/organ/external/org as anything in H.external_organs)
var/list/status = list()
var/brutedamage = org.brute_dam
var/burndamage = org.burn_dam
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index c0af887a5052..8c8239b8488e 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -1,3 +1,4 @@
+// todo: move all this to carbon.dm
/**
* The root type of complex mobs.
*
diff --git a/code/modules/mob/living/carbon/carbon_physiological_state.dm b/code/modules/mob/living/carbon/carbon_physiological_state.dm
new file mode 100644
index 000000000000..71970e1042bf
--- /dev/null
+++ b/code/modules/mob/living/carbon/carbon_physiological_state.dm
@@ -0,0 +1,12 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * A state holder available to **all** biologies on a carbon mob.
+ *
+ * * Use this to hold things like blood, which should naturally be accessible by all
+ * biologies.
+ */
+/datum/carbon_physiological_state
+
+#warn impl; hook into biologise
diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm
index e213076aa78f..57146aebed2c 100644
--- a/code/modules/mob/living/carbon/human/appearance.dm
+++ b/code/modules/mob/living/carbon/human/appearance.dm
@@ -204,7 +204,7 @@
/mob/living/carbon/human/proc/generate_valid_hairstyles(var/check_gender = 1)
var/use_species = species.get_bodytype_legacy(src)
- var/obj/item/organ/external/head/H = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/H = legacy_organ_by_zone(BP_HEAD)
if(H) use_species = H.species.get_bodytype_legacy(src)
var/list/valid_hairstyles = new()
@@ -226,7 +226,7 @@
/mob/living/carbon/human/proc/generate_valid_facial_hairstyles()
var/use_species = species.get_bodytype_legacy(src)
- var/obj/item/organ/external/head/H = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/H = legacy_organ_by_zone(BP_HEAD)
if(H) use_species = H.species.get_bodytype_legacy(src)
var/list/valid_facial_hairstyles = new()
diff --git a/code/modules/mob/living/carbon/human/chem_side_effects.dm b/code/modules/mob/living/carbon/human/chem_side_effects.dm
deleted file mode 100644
index 062f1369803b..000000000000
--- a/code/modules/mob/living/carbon/human/chem_side_effects.dm
+++ /dev/null
@@ -1,149 +0,0 @@
-// MEDICAL SIDE EFFECT BASE
-// ========================
-/datum/medical_effect
- var/name = "None"
- var/strength = 0
- var/start = 0
- var/list/triggers
- var/list/cures
- var/cure_message
-
-/datum/medical_effect/proc/manifest(mob/living/carbon/human/H)
- for(var/R in cures)
- if(H.reagents.has_reagent(R))
- return 0
- for(var/R in triggers)
- if(H.reagents.get_reagent_amount(R) >= triggers[R])
- return 1
- return 0
-
-/datum/medical_effect/proc/on_life(mob/living/carbon/human/H, strength)
- return
-
-/datum/medical_effect/proc/cure(mob/living/carbon/human/H)
- for(var/R in cures)
- if(H.reagents.has_reagent(R))
- if (cure_message)
- to_chat(H, "[cure_message]")
- return 1
- return 0
-
-
-// MOB HELPERS
-// ===========
-/mob/living/carbon/human/var/list/datum/medical_effect/side_effects = list()
-/mob/proc/add_side_effect(name, strength = 0)
-/mob/living/carbon/human/add_side_effect(name, strength = 0)
- for(var/datum/medical_effect/M in src.side_effects)
- if(M.name == name)
- M.strength = max(M.strength, 10)
- M.start = life_tick
- return
-
-
- var/T = side_effects[name]
- if (!T)
- return
-
- var/datum/medical_effect/M = new T
- if(M.name == name)
- M.strength = strength
- M.start = life_tick
- side_effects += M
-
-/mob/living/carbon/human/proc/handle_medical_side_effects()
- //Going to handle those things only every few ticks.
- if(life_tick % 15 != 0)
- return 0
-
- var/list/L = typesof(/datum/medical_effect)-/datum/medical_effect
- for(var/T in L)
- var/datum/medical_effect/M = new T
- if (M.manifest(src))
- src.add_side_effect(M.name)
-
- // One full cycle(in terms of strength) every 10 minutes
- for (var/datum/medical_effect/M in side_effects)
- if (!M) continue
- var/strength_percent = sin((life_tick - M.start) / 2)
-
- // Only do anything if the effect is currently strong enough
- if(strength_percent >= 0.4)
- if (M.cure(src) || M.strength > 50)
- side_effects -= M
- M = null
- else
- if(life_tick % 45 == 0)
- M.on_life(src, strength_percent*M.strength)
- // Effect slowly growing stronger
- M.strength+=0.08
-
-// HEADACHE
-// ========
-/datum/medical_effect/headache
- name = "Headache"
- triggers = list("cryoxadone" = 10, "bicaridine" = 15, "tricordrazine" = 15)
- cures = list("alkysine", "tramadol", "paracetamol", "oxycodone")
- cure_message = "Your head stops throbbing..."
-
-/datum/medical_effect/headache/on_life(mob/living/carbon/human/H, strength)
- switch(strength)
- if(1 to 10)
- H.custom_pain("You feel a light pain in your head.",0)
- if(11 to 30)
- H.custom_pain("You feel a throbbing pain in your head!",1)
- if(31 to INFINITY)
- H.custom_pain("You feel an excrutiating pain in your head!",1)
-
-// BAD STOMACH
-// ===========
-/datum/medical_effect/bad_stomach
- name = "Bad Stomach"
- triggers = list("kelotane" = 30, "dermaline" = 15)
- cures = list("anti_toxin")
- cure_message = "Your stomach feels a little better now..."
-
-/datum/medical_effect/bad_stomach/on_life(mob/living/carbon/human/H, strength)
- switch(strength)
- if(1 to 10)
- H.custom_pain("You feel a bit light around the stomach.",0)
- if(11 to 30)
- H.custom_pain("Your stomach hurts.",0)
- if(31 to INFINITY)
- H.custom_pain("You feel sick.",1)
-
-// CRAMPS
-// ======
-/datum/medical_effect/cramps
- name = "Cramps"
- triggers = list("anti_toxin" = 30, "tramadol" = 15)
- cures = list("inaprovaline")
- cure_message = "The cramps let up..."
-
-/datum/medical_effect/cramps/on_life(mob/living/carbon/human/H, strength)
- switch(strength)
- if(1 to 10)
- H.custom_pain("The muscles in your body hurt a little.",0)
- if(11 to 30)
- H.custom_pain("The muscles in your body cramp up painfully.",0)
- if(31 to INFINITY)
- H.emote("me",1,"flinches as all the muscles in their body cramp up.")
- H.custom_pain("There's pain all over your body.",1)
-
-// ITCH
-// ====
-/datum/medical_effect/itch
- name = "Itch"
- triggers = list("space_drugs" = 10)
- cures = list("inaprovaline")
- cure_message = "The itching stops..."
-
-/datum/medical_effect/itch/on_life(mob/living/carbon/human/H, strength)
- switch(strength)
- if(1 to 10)
- H.custom_pain("You feel a slight itch.",0)
- if(11 to 30)
- H.custom_pain("You want to scratch your itch badly.",0)
- if(31 to INFINITY)
- H.emote("me",1,"shivers slightly.")
- H.custom_pain("This itch makes it really hard to concentrate.",1)
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 3916f9920cef..03746a613d74 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -27,7 +27,7 @@
mirror.forceMove(drop_location())
mirror.throw_at_old(get_edge_target_turf(src,pick(GLOB.alldirs)), rand(1,3), round(30/mirror.w_class))
- for(var/obj/item/organ/external/E in src.organs)
+ for(var/obj/item/organ/external/E as anything in src.external_organs)
E.droplimb(0,DROPLIMB_EDGE,1)
sleep(1)
@@ -82,7 +82,7 @@
forbid_seeing_deadchat = TRUE
//Handle brain slugs.
- var/obj/item/organ/external/Hd = get_organ(BP_HEAD)
+ var/obj/item/organ/external/Hd = legacy_organ_by_zone(BP_HEAD)
var/mob/living/simple_mob/animal/borer/B
if(Hd)
diff --git a/code/modules/mob/living/carbon/human/defense.dm b/code/modules/mob/living/carbon/human/defense.dm
index f1035982f304..93edacfcbeaf 100644
--- a/code/modules/mob/living/carbon/human/defense.dm
+++ b/code/modules/mob/living/carbon/human/defense.dm
@@ -6,8 +6,8 @@
if(filter_zone)
// just one zone
- var/obj/item/organ/external/part = get_organ(filter_zone)
- for(var/obj/item/I as anything in inventory?.items_that_cover(part.body_part_flags))
+ var/obj/item/organ/external/part = legacy_organ_by_zone(filter_zone)
+ for(var/obj/item/I as anything in inventory?.query_body_cover_items(part.body_part_flags))
I.mob_armorcall(src, shieldcall_args, fake_attack)
if(shieldcall_args[SHIELDCALL_ARG_FLAGS] & SHIELDCALL_FLAG_TERMINATE)
break
@@ -23,7 +23,7 @@
continue
var/obj/item/organ/external/part = organs_by_name[key]
var/resultant = damage
- for(var/obj/item/I as anything in inventory?.items_that_cover(part.body_part_flags))
+ for(var/obj/item/I as anything in inventory?.query_body_cover_items(part.body_part_flags))
var/list/copied_args = args.Copy()
copied_args[SHIELDCALL_ARG_DAMAGE] = resultant
I.mob_armorcall(src, copied_args, fake_attack)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index e1b54ef03507..0bc11426d02c 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -961,8 +961,8 @@
if("aslap", "aslaps")
m_type = 1
var/mob/living/carbon/human/H = src
- var/obj/item/organ/external/L = H.get_organ("l_hand")
- var/obj/item/organ/external/R = H.get_organ("r_hand")
+ var/obj/item/organ/external/L = H.legacy_organ_by_zone("l_hand")
+ var/obj/item/organ/external/R = H.legacy_organ_by_zone("r_hand")
var/left_hand_good = 0
var/right_hand_good = 0
if(L && (!(L.status & ORGAN_DESTROYED)) && (!(L.splinted)) && (!(L.status & ORGAN_BROKEN)))
@@ -1035,8 +1035,8 @@
if("snap", "snaps")
m_type = 2
var/mob/living/carbon/human/H = src
- var/obj/item/organ/external/L = H.get_organ("l_hand")
- var/obj/item/organ/external/R = H.get_organ("r_hand")
+ var/obj/item/organ/external/L = H.legacy_organ_by_zone("l_hand")
+ var/obj/item/organ/external/R = H.legacy_organ_by_zone("r_hand")
var/left_hand_good = 0
var/right_hand_good = 0
if(L && (!(L.status & ORGAN_DESTROYED)) && (!(L.splinted)) && (!(L.status & ORGAN_BROKEN)))
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 8d423b44b084..2d2aa9f58707 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -282,7 +282,7 @@
//splints
for(var/organ in BP_ALL)
- var/obj/item/organ/external/o = get_organ(organ)
+ var/obj/item/organ/external/o = legacy_organ_by_zone(organ)
if(o && o.splinted && o.splinted.loc == o)
. += SPAN_WARNING("[T.He] [T.has] \a [FORMAT_TEXT_LOOKITEM(o.splinted)] on [T.his] [o.name]!")
diff --git a/code/modules/mob/living/carbon/human/human-damage-legacy.dm b/code/modules/mob/living/carbon/human/human-damage-legacy.dm
index 0f699869fc39..4ef4b3ac1798 100644
--- a/code/modules/mob/living/carbon/human/human-damage-legacy.dm
+++ b/code/modules/mob/living/carbon/human/human-damage-legacy.dm
@@ -7,7 +7,7 @@
var/total_burn = 0
var/total_brute = 0
- for(var/obj/item/organ/external/O in organs) //hardcoded to streamline things a bit
+ for(var/obj/item/organ/external/O in external_organs) //hardcoded to streamline things a bit
if(!O.vital)
if(O.robotic >= ORGAN_ROBOT)
continue //*non-vital* robot limbs don't count towards shock and crit
@@ -41,7 +41,7 @@
if(status_flags & STATUS_GODMODE) return 0 //godmode
if(should_have_organ("brain"))
- var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"]
+ var/obj/item/organ/internal/brain/sponge = keyed_organs[ORGAN_KEY_BRAIN]
if(sponge)
if(amount > 0)
sponge.take_damage(amount)
@@ -58,7 +58,7 @@
if(status_flags & STATUS_GODMODE) return 0 //godmode
if(should_have_organ("brain"))
- var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"]
+ var/obj/item/organ/internal/brain/sponge = keyed_organs[ORGAN_KEY_BRAIN]
if(sponge)
sponge.damage = clamp(amount, 0, sponge.max_damage)
sponge.update_health()
@@ -73,7 +73,7 @@
if(status_flags & STATUS_GODMODE) return 0 //godmode
if(should_have_organ("brain"))
- var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"]
+ var/obj/item/organ/internal/brain/sponge = keyed_organs[ORGAN_KEY_BRAIN]
if(sponge)
brainloss = sponge.damage
else
@@ -85,7 +85,7 @@
//These procs fetch a cumulative total damage from all organs
/mob/living/carbon/human/getBruteLoss()
var/amount = 0
- for(var/obj/item/organ/external/O in organs)
+ for(var/obj/item/organ/external/O in external_organs)
if(O.robotic >= ORGAN_ROBOT && !O.vital)
continue //*non-vital*robot limbs don't count towards death, or show up when scanned
amount += O.brute_dam
@@ -93,7 +93,7 @@
/mob/living/carbon/human/getShockBruteLoss()
var/amount = 0
- for(var/obj/item/organ/external/O in organs)
+ for(var/obj/item/organ/external/O in external_organs)
if(O.robotic >= ORGAN_ROBOT)
continue //robot limbs don't count towards shock and crit
amount += O.brute_dam
@@ -101,13 +101,13 @@
/mob/living/carbon/human/getActualBruteLoss()
var/amount = 0
- for(var/obj/item/organ/external/O in organs) // Unlike the above, robolimbs DO count.
+ for(var/obj/item/organ/external/O in external_organs) // Unlike the above, robolimbs DO count.
amount += O.brute_dam
return amount
/mob/living/carbon/human/getFireLoss()
var/amount = 0
- for(var/obj/item/organ/external/O in organs)
+ for(var/obj/item/organ/external/O in external_organs)
if(O.robotic >= ORGAN_ROBOT && !O.vital)
continue //*non-vital*robot limbs don't count towards death, or show up when scanned
amount += O.burn_dam
@@ -115,7 +115,7 @@
/mob/living/carbon/human/getShockFireLoss()
var/amount = 0
- for(var/obj/item/organ/external/O in organs)
+ for(var/obj/item/organ/external/O in external_organs)
if(O.robotic >= ORGAN_ROBOT)
continue //robot limbs don't count towards shock and crit
amount += O.burn_dam
@@ -123,7 +123,7 @@
/mob/living/carbon/human/getActualFireLoss()
var/amount = 0
- for(var/obj/item/organ/external/O in organs) // Unlike the above, robolimbs DO count.
+ for(var/obj/item/organ/external/O in external_organs) // Unlike the above, robolimbs DO count.
amount += O.burn_dam
return amount
@@ -283,7 +283,7 @@
//Returns a list of damaged organs
/mob/living/carbon/human/proc/get_damaged_organs(var/brute, var/burn)
var/list/obj/item/organ/external/parts = list()
- for(var/obj/item/organ/external/O in organs)
+ for(var/obj/item/organ/external/O in external_organs)
if((brute && O.brute_dam) || (burn && O.burn_dam))
parts += O
return parts
@@ -291,7 +291,7 @@
//Returns a list of damageable organs
/mob/living/carbon/human/proc/get_damageable_organs()
var/list/obj/item/organ/external/parts = list()
- for(var/obj/item/organ/external/O in organs)
+ for(var/obj/item/organ/external/O in external_organs)
if(O.is_damageable(TRUE))
parts += O
return parts
@@ -355,7 +355,7 @@ This function restores all organs.
organ = def_zone
else
if(!def_zone) def_zone = ran_zone(def_zone)
- organ = get_organ(check_zone(def_zone))
+ organ = legacy_organ_by_zone(check_zone(def_zone))
//Handle other types of damage
if((damagetype != DAMAGE_TYPE_BRUTE) && (damagetype != DAMAGE_TYPE_BURN))
diff --git a/code/modules/mob/living/carbon/human/human-defense-legacy.dm b/code/modules/mob/living/carbon/human/human-defense-legacy.dm
index 4d0e86fa83fb..930b5921f180 100644
--- a/code/modules/mob/living/carbon/human/human-defense-legacy.dm
+++ b/code/modules/mob/living/carbon/human/human-defense-legacy.dm
@@ -1,5 +1,5 @@
/mob/living/carbon/human/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone)
- var/obj/item/organ/external/affected = get_organ(check_zone(def_zone))
+ var/obj/item/organ/external/affected = legacy_organ_by_zone(check_zone(def_zone))
var/siemens_coeff = get_siemens_coefficient_organ(affected)
if(fire_stacks < 0) // Water makes you more conductive.
siemens_coeff *= 1.5
@@ -34,7 +34,7 @@
if(def_zone)
if(isorgan(def_zone))
return getarmor_organ(def_zone, type)
- var/obj/item/organ/external/affecting = get_organ(def_zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(def_zone)
if(affecting)
return getarmor_organ(affecting, type)
//If a specific bodypart is targetted, check how that bodypart is protected and return the value.
@@ -57,7 +57,7 @@
if(def_zone)
if(isorgan(def_zone))
return getsoak_organ(def_zone, type)
- var/obj/item/organ/external/affecting = get_organ(def_zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(def_zone)
if(affecting)
return getsoak_organ(affecting, type)
//If a specific bodypart is targetted, check how that bodypart is protected and return the value.
@@ -143,7 +143,7 @@
// Checked in borer code
/mob/living/carbon/human/proc/check_head_coverage()
- var/obj/item/organ/external/H = organs_by_name[BP_HEAD]
+ var/obj/item/organ/external/H = legacy_organ_by_zone(TARGET_ZONE_HEAD)
var/list/body_parts = H.get_covering_clothing(EYES)
if(LAZYLEN(body_parts))
return 1
@@ -151,7 +151,7 @@
//Used to check if they can be fed food/drinks/pills
/mob/living/carbon/human/proc/check_mouth_coverage()
- var/obj/item/organ/external/H = organs_by_name[BP_HEAD]
+ var/obj/item/organ/external/H = legacy_organ_by_zone(TARGET_ZONE_HEAD)
var/list/protective_gear = H.get_covering_clothing(FACE)
for(var/obj/item/gear in protective_gear)
if(istype(gear) && (gear.body_cover_flags & FACE) && !(gear.clothing_flags & FLEXIBLEMATERIAL))
@@ -159,7 +159,7 @@
return null
/mob/living/carbon/human/proc/check_mouth_coverage_survival()
- var/obj/item/organ/external/H = organs_by_name[BP_HEAD]
+ var/obj/item/organ/external/H = legacy_organ_by_zone(TARGET_ZONE_HEAD)
var/list/protective_gear = H.get_covering_clothing(FACE)
for(var/obj/item/gear in protective_gear)
if(istype(gear) && (gear.body_cover_flags & FACE) && !(gear.clothing_flags & FLEXIBLEMATERIAL) && !(gear.clothing_flags & ALLOW_SURVIVALFOOD))
@@ -184,7 +184,7 @@
if(shieldcall_results & SHIELDCALL_FLAGS_BLOCK_ATTACK)
return
- var/obj/item/organ/external/affecting = get_organ(hit_zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(hit_zone)
if (!affecting || affecting.is_stump())
to_chat(user, "They are missing that limb!")
return null
@@ -192,7 +192,7 @@
return hit_zone
/mob/living/carbon/human/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
- var/obj/item/organ/external/affecting = get_organ(hit_zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(hit_zone)
if(!affecting)
return //should be prevented by attacked_with_item() but for sanity.
@@ -205,7 +205,7 @@
return blocked
/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/soaked, var/hit_zone)
- var/obj/item/organ/external/affecting = get_organ(hit_zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(hit_zone)
if(!affecting)
return 0
@@ -289,7 +289,7 @@
return 0
/mob/living/carbon/human/emag_act(var/remaining_charges, mob/user, var/emag_source)
- var/obj/item/organ/external/affecting = get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(user.zone_sel.selecting)
if(!affecting || !(affecting.robotic >= ORGAN_ROBOT))
to_chat(user, "That limb isn't robotic.")
return -1
@@ -359,7 +359,7 @@
if(no_attack)
return force_pierce? COMPONENT_THROW_HIT_PIERCE | COMPONENT_THROW_HIT_NEVERMIND : NONE
- var/obj/item/organ/external/affecting = get_organ(zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(zone)
var/hit_area = affecting.name
src.visible_message("[src] has been hit in the [hit_area] by [O].")
@@ -425,9 +425,7 @@
// This does a prob check to catch the thing flying at you, with a minimum of 1%
/mob/living/carbon/human/proc/can_catch(var/obj/O)
if(!get_active_held_item()) // If active hand is empty
- var/obj/item/organ/external/temp = organs_by_name["r_hand"]
- if (active_hand % 2)
- temp = organs_by_name["l_hand"]
+ var/obj/item/organ/external/temp = get_active_hand_organ()
if(temp && !temp.is_usable())
return FALSE // The hand isn't working in the first place
@@ -453,7 +451,7 @@
/mob/living/carbon/human/embed(var/obj/O, var/def_zone=null)
if(!def_zone) ..()
- var/obj/item/organ/external/affecting = get_organ(def_zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(def_zone)
if(affecting)
affecting.embed(O)
@@ -551,7 +549,7 @@
var/organ_chance = 50
var/damage = shank_armor_helper(W, G, user)
- var/obj/item/organ/external/chest = get_organ(hit_zone)
+ var/obj/item/organ/external/chest = legacy_organ_by_zone(hit_zone)
if(W.damage_mode & DAMAGE_MODE_EDGE)
organ_chance = 75
diff --git a/code/modules/mob/living/carbon/human/human-defense.dm b/code/modules/mob/living/carbon/human/human-defense.dm
index dd8ec5289309..be835d6f0200 100644
--- a/code/modules/mob/living/carbon/human/human-defense.dm
+++ b/code/modules/mob/living/carbon/human/human-defense.dm
@@ -12,7 +12,7 @@
return
// todo: this shit shouldn't be here
- var/obj/item/organ/external/organ = get_organ()
+ var/obj/item/organ/external/organ = legacy_organ_by_zone()
if(!proj.nodamage)
organ.add_autopsy_data("[proj.name]", proj.damage_force)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/human-life-legacy.dm
similarity index 99%
rename from code/modules/mob/living/carbon/human/life.dm
rename to code/modules/mob/living/carbon/human/human-life-legacy.dm
index cfd9aec30caa..3245fbfb74fc 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/human-life-legacy.dm
@@ -67,10 +67,6 @@
voice = GetVoice()
-/mob/living/carbon/human/PhysicalLife(seconds, times_fired)
- if((. = ..()))
- return
-
fall() // Prevents people from floating
/mob/living/carbon/human/BiologicalLife(seconds, times_fired)
@@ -204,7 +200,7 @@
..()
if(!HAS_TRAIT_FROM(src, TRAIT_BLIND, TRAIT_BLINDNESS_SPECIES))
- var/obj/item/organ/vis = internal_organs_by_name[species.vision_organ]
+ var/obj/item/organ/vis = legacy_organ_by_tag[species.vision_organ]
if(!vis)
add_blindness_source( TRAIT_BLINDNESS_VIS_ORGAN_MISSING)
else if(HAS_TRAIT_FROM(src, TRAIT_BLIND, TRAIT_BLINDNESS_VIS_ORGAN_MISSING))
diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/human-login-legacy.dm
similarity index 100%
rename from code/modules/mob/living/carbon/human/login.dm
rename to code/modules/mob/living/carbon/human/human-login-legacy.dm
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index d471f5eaf9a2..425b3b8f341a 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -62,8 +62,6 @@
/mob/living/carbon/human/Destroy()
human_mob_list -= src
- for(var/organ in organs)
- qdel(organ)
QDEL_NULL(nif)
QDEL_LIST_NULL(vore_organs)
return ..()
@@ -86,7 +84,7 @@
STATPANEL_DATA_ENTRY("Tank Pressure", internal.air_contents.return_pressure())
STATPANEL_DATA_ENTRY("Distribution Pressure", internal.distribute_pressure)
- var/obj/item/organ/internal/xenos/plasmavessel/P = internal_organs_by_name[O_PLASMA] //Xenomorphs. Mech.
+ var/obj/item/organ/internal/xenomorph/plasmavessel/P = keyed_organs[ORGAN_KEY_XENOMORPH_PLASMA_VESSEL] //Xenomorphs. Mech.
if(P)
STATPANEL_DATA_LINE("Phoron Stored: [P.stored_plasma]/[P.max_plasma]")
@@ -154,7 +152,7 @@
// focus most of the blast on one organ
- var/obj/item/organ/external/take_blast = pick(organs)
+ var/obj/item/organ/external/take_blast = pick(external_organs)
take_blast.inflict_bodypart_damage(
brute = b_loss * 0.9,
burn = f_loss * 0.9,
@@ -165,7 +163,7 @@
b_loss *= 0.1
f_loss *= 0.1
- for(var/obj/item/organ/external/temp in organs)
+ for(var/obj/item/organ/external/temp in external_organs)
switch(temp.organ_tag)
if(BP_HEAD)
temp.inflict_bodypart_damage(
@@ -196,7 +194,7 @@
/mob/living/carbon/human/proc/is_loyalty_implanted()
for(var/L in src.contents)
if(istype(L, /obj/item/implant/loyalty))
- for(var/obj/item/organ/external/O in src.organs)
+ for(var/obj/item/organ/external/O as anything in src.external_organs)
if(L in O.implants)
return 1
return 0
@@ -281,7 +279,7 @@
//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable
/mob/living/carbon/human/proc/get_face_name()
- var/obj/item/organ/external/head = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head = legacy_organ_by_zone(BP_HEAD)
if(!head || head.disfigured || head.is_stump() || !real_name || (MUTATION_HUSK in mutations) ) //disfigured. use id-name if possible
return "Unknown"
return real_name
@@ -320,7 +318,7 @@
stored_shock_by_ref["\ref[src]"] = shock_damage
return
- var/obj/item/organ/external/affected_organ = get_organ(check_zone(def_zone))
+ var/obj/item/organ/external/affected_organ = legacy_organ_by_zone(check_zone(def_zone))
var/siemens_coeff = base_siemens_coeff * get_siemens_coefficient_organ(affected_organ)
if(fire_stacks < 0) // Water makes you more conductive.
siemens_coeff *= 1.5
@@ -640,8 +638,8 @@
var/obj/item/organ/internal/eyes/I
- if(internal_organs_by_name[O_EYES]) // Eyes are fucked, not a 'weak point'.
- I = internal_organs_by_name[O_EYES]
+ if(keyed_organs[ORGAN_KEY_EYES]) // Eyes are fucked, not a 'weak point'.
+ I = keyed_organs[ORGAN_KEY_EYES]
if(I.is_broken())
return FLASH_PROTECTION_MAJOR
else if(!species.dispersed_eyes) // They can't be flashed if they don't have eyes, or widespread sensing surfaces.
@@ -654,8 +652,8 @@
return number
/mob/living/carbon/human/flash_eyes(var/intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /atom/movable/screen/fullscreen/tiled/flash)
- if(internal_organs_by_name[O_EYES]) // Eyes are fucked, not a 'weak point'.
- var/obj/item/organ/internal/eyes/I = internal_organs_by_name[O_EYES]
+ if(keyed_organs[ORGAN_KEY_EYES]) // Eyes are fucked, not a 'weak point'.
+ var/obj/item/organ/internal/eyes/I = keyed_organs[ORGAN_KEY_EYES]
I.additional_flash_effects(intensity)
return ..()
@@ -688,7 +686,7 @@
return 0
//if the parent organ is significantly larger than the brain organ, then hitting it is not guaranteed
- var/obj/item/organ/parent = get_organ(target_zone)
+ var/obj/item/organ/parent = legacy_organ_by_zone(target_zone)
if(!parent)
return 0
@@ -751,7 +749,7 @@
/mob/living/carbon/human/check_has_mouth()
// Todo, check stomach organ when implemented.
- var/obj/item/organ/external/head/H = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/H = legacy_organ_by_zone(BP_HEAD)
if(!H || !H.can_intake_reagents)
return 0
return 1
@@ -909,54 +907,17 @@
/mob/living/carbon/human/proc/rupture_lung()
var/obj/item/organ/internal/lungs/L = internal_organs_by_name[O_LUNGS]
-
- if(L)
- L.rupture()
+ L?.rupture()
/mob/living/carbon/human/proc/asbestos_lung()
var/obj/item/organ/internal/lungs/L = internal_organs_by_name[O_LUNGS]
-
- if(L)
- L.damage_lung()
+ L?.damage_lung()
/mob/living/carbon/human/proc/heart_attack()
var/obj/item/organ/internal/heart/H = internal_organs_by_name[O_HEART]
+ H?.heart_attack()
- if(H)
- H.heart_attack()
-
-/*
-/mob/living/carbon/human/verb/simulate()
- set name = "sim"
- set background = 1
-
- var/damage = input("Wound damage","Wound damage") as num
-
- var/germs = 0
- var/tdamage = 0
- var/ticks = 0
- while (germs < 2501 && ticks < 100000 && round(damage/10)*20)
- log_misc("VIRUS TESTING: [ticks] : germs [germs] tdamage [tdamage] prob [round(damage/10)*20]")
- ticks++
- if (prob(round(damage/10)*20))
- germs++
- if (germs == 100)
- to_chat(world, "Reached stage 1 in [ticks] ticks")
- if (germs > 100)
- if (prob(10))
- damage++
- germs++
- if (germs == 1000)
- to_chat(world, "Reached stage 2 in [ticks] ticks")
- if (germs > 1000)
- damage++
- germs++
- if (germs == 2500)
- to_chat(world, "Reached stage 3 in [ticks] ticks")
- to_chat(world, "Mob took [tdamage] tox damage")
-*/
//returns 1 if made bloody, returns 0 otherwise
-
/mob/living/carbon/human/add_blood(mob/living/carbon/human/M as mob)
if (!..())
return 0
@@ -1003,7 +964,7 @@
/mob/living/carbon/human/get_visible_implants(var/class = 0)
var/list/visible_implants = list()
- for(var/obj/item/organ/external/organ in src.organs)
+ for(var/obj/item/organ/external/organ as anything in src.external_organs)
for(var/obj/item/O in organ.implants)
if(!istype(O,/obj/item/implant) && (O.w_class > class) && !istype(O,/obj/item/material/shard/shrapnel) && !istype(O, /obj/item/nif))
visible_implants += O
@@ -1011,7 +972,7 @@
return(visible_implants)
/mob/living/carbon/human/embedded_needs_process()
- for(var/obj/item/organ/external/organ in src.organs)
+ for(var/obj/item/organ/external/organ as anything in src.external_organs)
for(var/obj/item/O in organ.implants)
if(!istype(O, /obj/item/implant)) //implant type items do not cause embedding effects, see handle_embedded_objects()
return 1
@@ -1019,7 +980,7 @@
/mob/living/carbon/human/proc/handle_embedded_objects()
- for(var/obj/item/organ/external/organ in src.organs)
+ for(var/obj/item/organ/external/organ as anything in src.external_organs)
if(organ.splinted) //Splints prevent movement.
continue
for(var/obj/item/O in organ.implants)
@@ -1323,7 +1284,7 @@
else
target_zone = user.zone_sel.selecting
- var/obj/item/organ/external/affecting = get_organ(target_zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(target_zone)
var/fail_msg
if(!affecting)
. = 0
@@ -1405,15 +1366,11 @@
..()
/mob/living/carbon/human/has_brain()
- if(internal_organs_by_name[O_BRAIN])
- var/obj/item/organ/brain = internal_organs_by_name[O_BRAIN]
- if(brain && istype(brain))
- return 1
- return 0
+ return !!keyed_organs[ORGAN_KEY_BRAIN]
/mob/living/carbon/human/has_eyes()
- if(internal_organs_by_name[O_EYES])
- var/obj/item/organ/eyes = internal_organs_by_name[O_EYES]
+ if(keyed_organs[ORGAN_KEY_EYES])
+ var/obj/item/organ/eyes = keyed_organs[ORGAN_KEY_EYES]
if(eyes && istype(eyes) && !(eyes.status & ORGAN_CUT_AWAY))
return 1
return 0
@@ -1444,9 +1401,8 @@
self = 1 // Removing object from yourself.
var/list/limbs = list()
- for(var/limb in organs_by_name)
- var/obj/item/organ/external/current_limb = organs_by_name[limb]
- if(current_limb && current_limb.dislocated > 0 && !current_limb.is_parent_dislocated()) //if the parent is also dislocated you will have to relocate that first
+ for(var/obj/item/organ/external/current_limb in external_organs)
+ if(current_limb.dislocated > 0 && !current_limb.is_parent_dislocated()) //if the parent is also dislocated you will have to relocate that first
limbs |= current_limb
var/obj/item/organ/external/current_limb = input(usr,"Which joint do you wish to relocate?") as null|anything in limbs
@@ -1636,7 +1592,7 @@
nutrition = clamp(amount, 0, species.max_nutrition * 1.5)
/mob/living/carbon/human/get_bullet_impact_effect_type(var/def_zone)
- var/obj/item/organ/external/E = get_organ(def_zone)
+ var/obj/item/organ/external/E = legacy_organ_by_zone(def_zone)
if(!E || E.is_stump())
return BULLET_IMPACT_NONE
if(BP_IS_ROBOTIC(E))
diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index 5bf483f4fa42..a87751542635 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -121,7 +121,7 @@
var/block = 0
var/accurate = 0
var/hit_zone = H.zone_sel.selecting
- var/obj/item/organ/external/affecting = get_organ(hit_zone)
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(hit_zone)
if(!affecting || affecting.is_stump())
to_chat(L, "They are missing that limb!")
@@ -250,7 +250,7 @@
if(w_uniform)
w_uniform.add_fingerprint(L)
- var/obj/item/organ/external/affecting = get_organ(ran_zone(L.zone_sel.selecting))
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(ran_zone(L.zone_sel.selecting))
var/list/holding = list(get_active_held_item() = 40, get_inactive_held_item = 20)
@@ -324,7 +324,7 @@
user.do_attack_animation(src)
var/dam_zone = pick(organs_by_name)
- var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
+ var/obj/item/organ/external/affecting = legacy_organ_by_zone(ran_zone(dam_zone))
var/armor_block = run_armor_check(affecting, armor_type, armor_pen)
var/armor_soak = get_armor_soak(affecting, armor_type, armor_pen)
apply_damage(damage, DAMAGE_TYPE_BRUTE, affecting, armor_block, armor_soak, sharp = a_sharp, edge = a_edge)
@@ -340,7 +340,7 @@
var/target_zone = check_zone(def_zone)
if(!target_zone)
return FALSE
- var/obj/item/organ/external/organ = get_organ(check_zone(target_zone))
+ var/obj/item/organ/external/organ = legacy_organ_by_zone(check_zone(target_zone))
if(!organ || organ.dislocated > 0 || organ.dislocated == -1) //don't use is_dislocated() here, that checks parent
return FALSE
@@ -374,7 +374,7 @@
Changing targeted zones should also stop do_mob(), preventing you from applying pressure to more than one body part at once.
*/
/mob/living/carbon/human/proc/apply_pressure(mob/living/user, var/target_zone)
- var/obj/item/organ/external/organ = get_organ(target_zone)
+ var/obj/item/organ/external/organ = legacy_organ_by_zone(target_zone)
if(!organ || !(organ.status & ORGAN_BLEEDING) || (organ.robotic >= ORGAN_ROBOT))
return FALSE
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index a022d7d34574..c48eaaa03dec 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -32,26 +32,6 @@
return list(HUMAN_EATING_BLOCKED_MOUTH, blocked)
return list(HUMAN_EATING_NO_ISSUE)
-/mob/living/carbon/human/proc/get_coverage()
- var/list/coverage = list()
- for(var/obj/item/clothing/C in get_equipped_items())
- if(C.body_cover_flags & HEAD)
- coverage += list(organs_by_name[BP_HEAD])
- if(C.body_cover_flags & UPPER_TORSO)
- coverage += list(organs_by_name[BP_TORSO])
- if(C.body_cover_flags & LOWER_TORSO)
- coverage += list(organs_by_name[BP_GROIN])
- if(C.body_cover_flags & LEGS)
- coverage += list(organs_by_name[BP_L_LEG], organs_by_name[BP_R_LEG])
- if(C.body_cover_flags & ARMS)
- coverage += list(organs_by_name[BP_R_ARM], organs_by_name[BP_L_ARM])
- if(C.body_cover_flags & FEET)
- coverage += list(organs_by_name[BP_L_FOOT], organs_by_name[BP_R_FOOT])
- if(C.body_cover_flags & HANDS)
- coverage += list(organs_by_name[BP_L_HAND], organs_by_name[BP_R_HAND])
- return coverage
-
-
/// This is called when we want different types of 'cloaks' to stop working, e.g. when attacking.
/mob/living/carbon/human/break_cloak()
// Changeling visible camo.
diff --git a/code/modules/mob/living/carbon/human/human_modular_limbs.dm b/code/modules/mob/living/carbon/human/human_modular_limbs.dm
index d430cd66883b..81c7650b3083 100644
--- a/code/modules/mob/living/carbon/human/human_modular_limbs.dm
+++ b/code/modules/mob/living/carbon/human/human_modular_limbs.dm
@@ -24,7 +24,7 @@
if(bodypart_cat == MODULAR_BODYPART_CYBERNETIC)
if(!parent_organ)
return FALSE
- var/obj/item/organ/external/parent = user?.get_organ(parent_organ)
+ var/obj/item/organ/external/parent = user?.legacy_organ_by_zone(parent_organ)
if(!parent || parent.get_modular_limb_category(user) < MODULAR_BODYPART_CYBERNETIC)
return FALSE
. = (bodypart_cat != MODULAR_BODYPART_INVALID)
@@ -41,7 +41,7 @@
return FALSE
if(!parent_organ)
return FALSE
- var/obj/item/organ/external/parent = user?.get_organ(parent_organ)
+ var/obj/item/organ/external/parent = user?.legacy_organ_by_zone(parent_organ)
if(!parent)
return FALSE
if(!parent.can_attach_modular_limb_here(user))
@@ -100,13 +100,13 @@
to_chat(src, SPAN_WARNING("\The [E] cannot be attached by your own hand."))
return FALSE
var/install_to_zone = E.organ_tag
- if(!isnull(get_organ(install_to_zone)))
+ if(!isnull(legacy_organ_by_zone(install_to_zone)))
to_chat(src, SPAN_WARNING("There is already a limb attached at that part of your body."))
return FALSE
if(E.check_modular_limb_damage(src))
to_chat(src, SPAN_WARNING("\The [E] is too damaged to be attached."))
return FALSE
- var/obj/item/organ/external/parent = E.parent_organ && get_organ(E.parent_organ)
+ var/obj/item/organ/external/parent = E.parent_organ && legacy_organ_by_zone(E.parent_organ)
if(!parent)
to_chat(src, SPAN_WARNING("\The [E] needs an existing limb to be attached to."))
return FALSE
@@ -127,7 +127,7 @@
if(E.check_modular_limb_damage(src))
to_chat(src, SPAN_WARNING("That limb is too damaged to be removed!"))
return FALSE
- var/obj/item/organ/external/parent = E.parent_organ && get_organ(E.parent_organ)
+ var/obj/item/organ/external/parent = E.parent_organ && legacy_organ_by_zone(E.parent_organ)
if(!parent)
return FALSE
if(parent.check_modular_limb_damage(src))
diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm
index f529701c0e7d..52a0876d6679 100644
--- a/code/modules/mob/living/carbon/human/human_organs.dm
+++ b/code/modules/mob/living/carbon/human/human_organs.dm
@@ -5,27 +5,9 @@
var/obj/item/organ/external/O = organs_by_name[name]
return (O && !O.is_stump())
-/mob/living/carbon/human/proc/recheck_bad_external_organs()
- var/damage_this_tick = getToxLoss()
- for(var/obj/item/organ/external/O in organs)
- damage_this_tick += O.burn_dam + O.brute_dam
- if(O.germ_level)
- damage_this_tick += 1 //Just tap it if we have germs so we can process those
-
- if(damage_this_tick > last_dam)
- . = TRUE
- last_dam = damage_this_tick
-
+#warn /carbon-ize() this
// Takes care of organ related updates, such as broken and missing limbs
/mob/living/carbon/human/proc/handle_organs(dt)
-
- var/force_process = recheck_bad_external_organs()
-
- if(force_process)
- bad_external_organs.Cut()
- for(var/obj/item/organ/external/Ex in organs)
- bad_external_organs += Ex
-
//processing internal organs is pretty cheap, do that first.
if(STAT_IS_DEAD(stat))
//todo: internal organs list when zandario fixes it lmao
@@ -38,35 +20,25 @@
handle_stance()
handle_grasp()
- if(!force_process && !bad_external_organs.len)
- return
-
- wound_tally = 0 // You have to reduce this at some point...
- for(var/obj/item/organ/external/E in bad_external_organs)
- if(!E)
- continue
- if(!E.need_process())
- bad_external_organs -= E
- continue
+ for(var/obj/item/organ/external/E in external_organs)
+ if(STAT_IS_DEAD(stat))
+ E.tick_death(dt)
else
- if(STAT_IS_DEAD(stat))
- E.tick_death(dt)
- else
- E.tick_life(dt)
- wound_tally += E.wound_tally
-
- if (!lying && !buckled && world.time - l_move_time < 15)
- //Moving around with fractured ribs won't do you any good
- if (prob(10) && !stat && can_feel_pain() && chem_effects[CE_PAINKILLER] < 50 && E.is_broken() && E.internal_organs.len)
- custom_pain("Pain jolts through your broken [E.encased ? E.encased : E.name], staggering you!", 50)
- drop_active_held_item()
- afflict_stun(20 * 2)
-
- //Moving makes open wounds get infected much faster
- if (length(E.wounds))
- for(var/datum/wound/W as anything in E.wounds)
- if (W.infection_check())
- W.germ_level += 1
+ E.tick_life(dt)
+ wound_tally += E.wound_tally
+
+ if (!lying && !buckled && world.time - l_move_time < 15)
+ //Moving around with fractured ribs won't do you any good
+ if (prob(10) && !stat && can_feel_pain() && chem_effects[CE_PAINKILLER] < 50 && E.is_broken() && E.internal_organs.len)
+ custom_pain("Pain jolts through your broken [E.encased ? E.encased : E.name], staggering you!", 50)
+ drop_active_held_item()
+ afflict_stun(20 * 2)
+
+ //Moving makes open wounds get infected much faster
+ if (length(E.wounds))
+ for(var/datum/wound/W as anything in E.wounds)
+ if (W.infection_check())
+ W.germ_level += 1
/mob/living/carbon/human/proc/handle_stance()
// Don't need to process any of this if they aren't standing anyways
diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm
index 160f33a4df6f..0389db5f2b03 100644
--- a/code/modules/mob/living/carbon/human/human_powers.dm
+++ b/code/modules/mob/living/carbon/human/human_powers.dm
@@ -89,9 +89,8 @@
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
- M.loc = loc
+ M.forceMove(loc)
src.visible_message(SPAN_BOLDDANGER("[src] hurls out the contents of their stomach!"))
- return
/mob/living/carbon/human/proc/psychic_whisper(mob/M as mob in oview())
set name = "Psychic Whisper"
@@ -282,6 +281,7 @@
if(!E)
var/list/organ_data = src.species.has_limbs[limb_type]
var/limb_path = organ_data["path"]
+ #warn INSERT THIS PROPERLY
var/obj/item/organ/O = new limb_path(src)
organ_data["descriptor"] = O.name
to_chat(src, SPAN_NOTICE("You feel a slithering sensation as your [O.name] reform."))
@@ -292,6 +292,7 @@
for(var/organtype in species.has_organ) // Replace completely missing internal organs. -After- external ones, so they all should exist.
if(!src.internal_organs_by_name[organtype])
var/organpath = species.has_organ[organtype]
+ #warn INSERT THIS PROPERLY
var/obj/item/organ/Int = new organpath(src, TRUE)
Int.rejuvenate_legacy(TRUE)
diff --git a/code/modules/mob/living/carbon/human/inventory_legacy.dm b/code/modules/mob/living/carbon/human/inventory_legacy.dm
deleted file mode 100644
index 95ba4567a922..000000000000
--- a/code/modules/mob/living/carbon/human/inventory_legacy.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-//! old stuff below
-
-/mob/living/carbon/human/verb/quick_equip()
- set name = "quick-equip"
- set hidden = 1
-
- attempt_smart_equip()
diff --git a/code/modules/mob/living/carbon/human/logout.dm b/code/modules/mob/living/carbon/human/logout.dm
deleted file mode 100644
index 3d2f5e7ecd59..000000000000
--- a/code/modules/mob/living/carbon/human/logout.dm
+++ /dev/null
@@ -1,4 +0,0 @@
-/mob/living/carbon/human/Logout()
- ..()
- if(species) species.handle_logout_special(src)
- return
diff --git a/code/modules/mob/living/carbon/human/movement.dm b/code/modules/mob/living/carbon/human/movement.dm
index 4150e5a903dc..d0eee333acb8 100644
--- a/code/modules/mob/living/carbon/human/movement.dm
+++ b/code/modules/mob/living/carbon/human/movement.dm
@@ -46,7 +46,7 @@
if(istype(buckled, /obj/structure/bed/chair/wheelchair))
for(var/organ_name in list(BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM))
- var/obj/item/organ/external/E = get_organ(organ_name)
+ var/obj/item/organ/external/E = legacy_organ_by_zone(organ_name)
if(!E || E.is_stump())
tally += 4
else if(E.splinted && E.splinted.loc != E)
@@ -55,7 +55,7 @@
tally += 1.5
else
for(var/organ_name in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT))
- var/obj/item/organ/external/E = get_organ(organ_name)
+ var/obj/item/organ/external/E = legacy_organ_by_zone(organ_name)
if(!E || E.is_stump())
tally += 4
else if(E.splinted && E.splinted.loc != E)
diff --git a/code/modules/mob/living/carbon/human/pain.dm b/code/modules/mob/living/carbon/human/pain.dm
index 7ae816bd17c1..72ba995cb9bb 100644
--- a/code/modules/mob/living/carbon/human/pain.dm
+++ b/code/modules/mob/living/carbon/human/pain.dm
@@ -30,7 +30,7 @@
return
var/maxdam = 0
var/obj/item/organ/external/damaged_organ = null
- for(var/obj/item/organ/external/E in organs)
+ for(var/obj/item/organ/external/E in external_organs)
if(!E.organ_can_feel_pain())
continue
var/dam = E.get_damage()
@@ -64,7 +64,7 @@
continue
if(I.damage > 2)
if(prob(25) && painmsg)
- var/obj/item/organ/external/parent = get_organ(I.parent_organ)
+ var/obj/item/organ/external/parent = legacy_organ_by_zone(I.parent_organ)
src.custom_pain("You feel a sharp pain in your [parent.name]", 50)
if(prob(25) && painmsg)
diff --git a/code/modules/mob/living/carbon/human/rendering.dm b/code/modules/mob/living/carbon/human/rendering.dm
index 0fb48af7a4bd..143185792321 100644
--- a/code/modules/mob/living/carbon/human/rendering.dm
+++ b/code/modules/mob/living/carbon/human/rendering.dm
@@ -16,7 +16,7 @@
if(isnull(rendering))
remove_standing_overlay(HUMAN_OVERLAY_EARS)
return
- var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/head_organ = legacy_organ_by_zone(BP_HEAD)
if(!head_organ || head_organ.is_stump())
remove_standing_overlay(HUMAN_OVERLAY_EARS)
return
@@ -58,7 +58,7 @@
//! legacy code
remove_standing_overlay(HUMAN_OVERLAY_HORNS)
return
- var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/head_organ = legacy_organ_by_zone(BP_HEAD)
if(!head_organ || head_organ.is_stump())
remove_standing_overlay(HUMAN_OVERLAY_HORNS)
return
@@ -96,7 +96,7 @@
if(isnull(rendering))
remove_standing_overlay(HUMAN_OVERLAY_FACEHAIR)
return
- var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/head_organ = legacy_organ_by_zone(BP_HEAD)
if(!head_organ || head_organ.is_stump())
remove_standing_overlay(HUMAN_OVERLAY_FACEHAIR)
return
@@ -132,7 +132,7 @@
if(isnull(rendering))
remove_standing_overlay(HUMAN_OVERLAY_HAIR)
return
- var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/head_organ = legacy_organ_by_zone(BP_HEAD)
if(!head_organ || head_organ.is_stump())
remove_standing_overlay(HUMAN_OVERLAY_HAIR)
return
@@ -405,7 +405,7 @@
/mob/living/carbon/human/update_hair()
update_eyes() //Pirated out of here, for glowing eyes.
- var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/head_organ = legacy_organ_by_zone(BP_HEAD)
if(istype(head_organ,/obj/item/organ/external/head/vr))
var/obj/item/organ/external/head/vr/head_organ_vr = head_organ
head_spriteacc_offset = head_organ_vr.head_offset
@@ -423,7 +423,7 @@
// first check whether something actually changed about damage appearance
var/damage_appearance = ""
- for(var/obj/item/organ/external/O in organs)
+ for(var/obj/item/organ/external/O in external_organs)
if(isnull(O) || O.is_stump())
continue
damage_appearance += O.damage_state
@@ -488,7 +488,7 @@
icon_key += "[lip_style]"
else
icon_key += "nolips"
- var/obj/item/organ/internal/eyes/eyes = internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/eyes = keyed_organs[ORGAN_KEY_EYES]
if(eyes)
icon_key += "[rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3])]"
else
@@ -543,7 +543,7 @@
base_icon = GLOB.human_icon_cache[icon_key]
else
//BEGIN CACHED ICON GENERATION.
- var/obj/item/organ/external/chest = get_organ(BP_TORSO)
+ var/obj/item/organ/external/chest = legacy_organ_by_zone(BP_TORSO)
base_icon = chest.get_icon()
for(var/obj/item/organ/external/part in organs)
@@ -654,7 +654,7 @@
set_standing_overlay(HUMAN_OVERLAY_UNDERWEAR, setting)
/mob/living/carbon/human/update_eyes()
- var/obj/item/organ/internal/eyes/eyes = internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/eyes = keyed_organs[ORGAN_KEY_EYES]
if(eyes)
eyes.update_colour()
update_icons_body()
@@ -672,7 +672,7 @@
return
//Get the head, we'll need it later.
- var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/head_organ = legacy_organ_by_zone(BP_HEAD)
if(!head_organ || head_organ.is_stump() )
remove_standing_overlay(HUMAN_OVERLAY_EYES)
return
diff --git a/code/modules/mob/living/carbon/human/traits/negative.dm b/code/modules/mob/living/carbon/human/traits/negative.dm
index 54c3fa4abbb7..2d6947514857 100644
--- a/code/modules/mob/living/carbon/human/traits/negative.dm
+++ b/code/modules/mob/living/carbon/human/traits/negative.dm
@@ -195,7 +195,7 @@
/datum/trait/negative/hollow/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..(S,H)
- for(var/obj/item/organ/external/O in H.organs)
+ for(var/obj/item/organ/external/O as anything in H.external_organs)
O.min_broken_damage *= 0.75
O.min_bruised_damage *= 0.75
@@ -211,7 +211,7 @@
/datum/trait/negative/hollow_plus/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..(S,H)
- for(var/obj/item/organ/external/O in H.organs)
+ for(var/obj/item/organ/external/O as anything in H.external_organs)
O.min_broken_damage *= 0.5
O.min_bruised_damage *= 0.5
diff --git a/code/modules/mob/living/carbon/human/traits/positive.dm b/code/modules/mob/living/carbon/human/traits/positive.dm
index a419edb7377c..972a887504ce 100644
--- a/code/modules/mob/living/carbon/human/traits/positive.dm
+++ b/code/modules/mob/living/carbon/human/traits/positive.dm
@@ -208,7 +208,7 @@
/datum/trait/positive/reinforced/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..(S,H)
- for(var/obj/item/organ/external/O in H.organs)
+ for(var/obj/item/organ/external/O as anything in H.external_organs)
O.min_broken_damage *= 1.25
O.min_bruised_damage *= 1.25
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index 8256d60a3e13..c98eeb8e7188 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -54,18 +54,18 @@
/mob/living/carbon/carry_weight_to_penalty(amount)
// https://www.desmos.com/calculator/5o2cx7grbo
- var/carry_strength = physiology.carry_strength + physiology.carry_weight_add
+ var/carry_strength = global_physiology.carry_strength + global_physiology.carry_weight_add
if(amount < carry_strength)
return 1
- var/carry_factor = physiology.carry_factor * physiology.carry_weight_factor
+ var/carry_factor = global_physiology.carry_factor * global_physiology.carry_weight_factor
return (1 / (1 + NUM_E ** (carry_factor * (CARRY_WEIGHT_SCALING / carry_strength) * (amount - carry_strength + CARRY_WEIGHT_BIAS * carry_strength) - 5))) * (1 - CARRY_WEIGHT_ASYMPTOTE) + CARRY_WEIGHT_ASYMPTOTE
/mob/living/carbon/carry_encumbrance_to_penalty(amount)
// https://www.desmos.com/calculator/5o2cx7grbo
- var/carry_strength = physiology.carry_strength
+ var/carry_strength = global_physiology.carry_strength
if(amount < carry_strength)
return 1
- var/carry_factor = physiology.carry_factor
+ var/carry_factor = global_physiology.carry_factor
return (1 / (1 + NUM_E ** (carry_factor * (CARRY_WEIGHT_SCALING / carry_strength) * (amount - carry_strength + CARRY_WEIGHT_BIAS * carry_strength) - 5))) * (1 - CARRY_WEIGHT_ASYMPTOTE) + CARRY_WEIGHT_ASYMPTOTE
/mob/living/carbon/get_item_slowdown()
diff --git a/code/modules/mob/living/carbon/lick_wounds.dm b/code/modules/mob/living/carbon/lick_wounds.dm
index 9b3718c9196d..6f66720795f8 100644
--- a/code/modules/mob/living/carbon/lick_wounds.dm
+++ b/code/modules/mob/living/carbon/lick_wounds.dm
@@ -14,7 +14,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(src.zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(src.zone_sel.selecting)
if(!affecting)
to_chat(src, "No body part there to work on!")
diff --git a/code/modules/mob/living/carbon/organs.dm b/code/modules/mob/living/carbon/organs.dm
deleted file mode 100644
index b22c1e0c3a1f..000000000000
--- a/code/modules/mob/living/carbon/organs.dm
+++ /dev/null
@@ -1,26 +0,0 @@
-//* This file is explicitly licensed under the MIT license. *//
-//* Copyright (c) 2023 Citadel Station developers. *//
-
-/**
- * get organ for body zone
- */
-/mob/living/carbon/proc/get_bodypart_for_zone(body_zone)
- return organs_by_name[body_zone]
-
-/**
- * get external organs
- */
-/mob/living/carbon/proc/get_external_organs()
- . = list()
- for(var/obj/item/organ/external/E in organs)
- . += E
-
-/**
- * get external organs that are targetable
- */
-/mob/living/carbon/proc/get_damageable_external_organs(check_damage_cap)
- . = list()
- for(var/obj/item/organ/external/E in organs)
- if(!E.is_damageable(check_damage_cap))
- continue
- . += E
diff --git a/code/modules/mob/living/carbon/shock.dm b/code/modules/mob/living/carbon/shock.dm
index b0c935321942..4f6714567170 100644
--- a/code/modules/mob/living/carbon/shock.dm
+++ b/code/modules/mob/living/carbon/shock.dm
@@ -23,7 +23,7 @@
// broken or ripped off organs will add quite a bit of pain
if(istype(src,/mob/living/carbon/human))
var/mob/living/carbon/human/M = src
- for(var/obj/item/organ/external/organ in M.organs)
+ for(var/obj/item/organ/external/organ as anything in M.external_organs)
if(organ.is_broken() || organ.open)
src.traumatic_shock += 30
else if(organ.is_dislocated())
diff --git a/code/modules/mob/living/living-physiology.dm b/code/modules/mob/living/living-physiology.dm
new file mode 100644
index 000000000000..25c76a1bf479
--- /dev/null
+++ b/code/modules/mob/living/living-physiology.dm
@@ -0,0 +1,93 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * initializes physiology modifiers
+ * paths in physiology modifier are converted to the cached instances in globals.
+ */
+/mob/living/proc/init_physiology()
+ for(var/i in 1 to length(physiology_modifiers))
+ if(ispath(physiology_modifiers[i]))
+ physiology_modifiers[i] = cached_physiology_modifier(physiology_modifiers[i])
+ rebuild_physiology()
+
+/**
+ * adds a modifier to physiology
+ * you are responsible for not double-adding
+ * paths are allowed; if modifier is a path, it'll be the globally cached modifier of that type.
+ */
+/mob/living/proc/add_physiology_modifier(datum/physiology_modifier/modifier)
+ if(ispath(modifier))
+ modifier = cached_physiology_modifier(modifier)
+ ASSERT(!(modifier in physiology_modifiers))
+ LAZYADD(physiology_modifiers, modifier)
+ global_physiology.apply(modifier)
+ return TRUE
+
+/**
+ * removes a modifier from physiology
+ * you are responsible for not double-adding
+ * paths are allowed
+ */
+/mob/living/proc/remove_physiology_modifier(datum/physiology_modifier/modifier)
+ if(ispath(modifier))
+ modifier = cached_physiology_modifier(modifier)
+ ASSERT(modifier in physiology_modifiers)
+ LAZYREMOVE(physiology_modifiers, modifier)
+ if(!global_physiology.revert(modifier))
+ // todo: optimize with reset().
+ rebuild_physiology()
+ return TRUE
+
+/**
+ * completely rebuilds physiology from our modifiers
+ */
+/mob/living/proc/rebuild_physiology()
+ physiology = new
+ for(var/datum/physiology_modifier/modifier as anything in physiology_modifiers)
+ if(!istype(modifier))
+ physiology_modifiers -= modifier
+ continue
+ global_physiology.apply(modifier)
+
+// i'm not going to fucking support vv without automated backreferences and macros, holy shit.
+// /mob/living/proc/get_varedit_physiology_modifier()
+// RETURN_TYPE(/datum/physiology_modifier)
+// . = locate(/datum/physiology_modifier/varedit) in physiology_modifiers
+// if(!isnull(.))
+// return
+// var/datum/physiology_modifier/varedit/new_holder = new
+// add_physiology_modifier(new_holder)
+// return new_holder
+
+// todo: you can tell from the proc name that this needs to be kicked somewhere eles later.
+/proc/ask_admin_for_a_physiology_modifier(mob/user)
+ var/datum/tgui_dynamic_query/query = new
+ query.string("name", "Name", "Name your modifier.", 64, FALSE, "Custom Modifier")
+ query.number("g_carry_strength_add", "Carry Strength - Add", "Modify the person's base carry strength. Higher is better.", default = 0)
+ query.number("g_carry_strength_factor", "Carry Factor - Multiply", "Multiply the person's carry weight/encumbrance to slowdown effect when carrying over their limit. Lower is better.", default = 1)
+ query.number("g_carry_strength_bias", "Carry Bias - Multiply", "Multiply the person's carry weight/encumbrance to slowdown bias when carrying over their limit. Lower is better.", default = 1)
+ query.number("g_carry_weight_add", "Carry Weight - Add", "Modify the person's base carry weight. Higher is better. This only applies to weight, not encumbrance.", default = 0)
+ query.number("g_carry_weight_factor", "Carry Weight - Multiply", "Multiply the person's weight to slowdown effect when carrying over their limit. Lower is better. This only applies to weight, not encumbrance.", default = 1)
+ query.number("g_carry_weight_bias", "Carry Weight - Bias", "Multiply the person's weight to slowdown calculation bias; lower is better.", default = 1)
+
+ var/list/choices = tgui_dynamic_input(user, "Add a physiology modifier", "Add Physiology Modifier", query)
+
+ if(isnull(choices))
+ return
+
+ var/datum/physiology_modifier/modifier = new
+
+ // we manually deserialize because we might have custom datatypes
+ // in the future that won't be serialized by the ui necessarily in the same way
+ // we would serialize it via json.
+
+ modifier.name = choices["name"]
+ modifier.g_carry_strength_add = choices["g_carry_strength_add"]
+ modifier.g_carry_strength_factor = choices["g_carry_strength_factor"]
+ modifier.g_carry_strength_bias = choices["g_carry_strength_bias"]
+ modifier.g_carry_weight_add = choices["g_carry_weight_add"]
+ modifier.g_carry_weight_factor = choices["g_carry_weight_factor"]
+ modifier.g_carry_weight_bias = choices["g_carry_weight_bias"]
+
+ return modifier
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b01ba32341a6..19e6135523cc 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1,13 +1,34 @@
+/**
+ * Living mobs.
+ *
+ * This is called 'living' but in reality it's just any real lifeform in the world.
+ *
+ * Contains normalized health system simulation and all that.
+ *
+ * ## Composition:
+ * * Global Physiology: Mob-wide physiology modification.
+ * * Local Physiology: Limb-wide (or mob-wide for non-carbons) physiology modification.
+ */
TYPE_REGISTER_SPATIAL_GRID(/mob/living, SSspatial_grids.living)
+/mob/living
+ //* Physiology *//
+ /// overall physiology - see physiology.dm
+ var/datum/global_physiology/global_physiology
+ /// physiology modifiers - see physiology.dm; set to list of paths at init to initialize into instances.
+ var/list/datum/physiology_modifier/physiology_modifiers
+
/mob/living/Initialize(mapload)
. = ..()
+ // physiology
+ init_physiology()
// make radiation sensitive
AddComponent(/datum/component/radiation_listener)
AddElement(/datum/element/z_radiation_listener)
-
+ // init AI
if(ai_holder_type && !ai_holder)
ai_holder = new ai_holder_type(src)
+ // todo: what the hell is this? this shouldn't be here!
selected_image = image(icon = 'icons/mob/screen1.dmi', loc = src, icon_state = "centermarker")
/mob/living/Destroy()
@@ -23,22 +44,7 @@ TYPE_REGISTER_SPATIAL_GRID(/mob/living, SSspatial_grids.living)
buckled.unbuckle_mob(src, TRUE)
if(selected_image)
QDEL_NULL(selected_image)
-
- // this all needs to be Cut and not null
- // TODO: fix whatever is accessing these lists after qdel
- // it should never happen.
- organs_by_name.Cut()
- internal_organs_by_name.Cut()
- for(var/obj/item/organ/O in organs)
- if(!QDELETED(O))
- qdel(O)
- organs.Cut()
- for(var/obj/item/organ/O in internal_organs)
- if(!QDELETED(O))
- qdel(O)
- internal_organs.Cut()
profile = null
-
return ..()
//mob verbs are faster than object verbs. See mob/verb/examine.
@@ -109,7 +115,7 @@ default behaviour is:
var/mob/living/carbon/human/H = src //make this damage method divide the damage to be done among all the body parts, then burn each body part for that much damage. will have better effect then just randomly picking a body part
var/divided_damage = (burn_amount)/(H.organs.len)
var/extradam = 0 //added to when organ is at max dam
- for(var/obj/item/organ/external/affecting in H.organs)
+ for(var/obj/item/organ/external/affecting as anything in H.external_organs)
affecting.inflict_bodypart_damage(
burn = divided_damage + extradam,
)
diff --git a/code/modules/mob/living/organs.dm b/code/modules/mob/living/organs.dm
deleted file mode 100644
index 24a8df7690ce..000000000000
--- a/code/modules/mob/living/organs.dm
+++ /dev/null
@@ -1,42 +0,0 @@
-/mob/living
- var/list/internal_organs = list()
- var/list/organs = list()
- /// Map organ names to organs
- var/list/organs_by_name = list()
- /// So internal organs have less ickiness too
- var/list/internal_organs_by_name = list()
- /// Organs we check until they are good.
- var/list/bad_external_organs = list()
-
-/mob/living/proc/get_bodypart_name(zone)
- var/obj/item/organ/external/E = get_organ(zone)
- if(E)
- . = E.name
-
-/mob/living/proc/get_organ(zone)
- if(!zone)
- zone = BP_TORSO
- else if (zone in list( O_EYES, O_MOUTH ))
- zone = BP_HEAD
- return organs_by_name[zone]
-
-/mob/living/gib()
- if(butchery_drops_organs)
- for(var/path in internal_organs)
- if(ispath(path))
- var/obj/item/organ/neworg = new path(src, TRUE)
- internal_organs -= path
- neworg.name = "[name] [neworg.name]"
- neworg.meat_type = meat_type
- internal_organs |= neworg
-
- for(var/obj/item/organ/I in internal_organs)
- I.removed()
- // Some organs qdel themselves or other things when removed.
- if(isturf(I?.loc))
- I.throw_at_old(get_edge_target_turf(src, pick(GLOB.alldirs)), rand(1,3), 30)
-
- for(var/obj/item/organ/external/E in src.organs)
- if(!ispath(E))
- E.droplimb(FALSE, DROPLIMB_EDGE, TRUE)
- ..()
diff --git a/code/modules/mob/living/physiology/global_physiology.dm b/code/modules/mob/living/physiology/global_physiology.dm
new file mode 100644
index 000000000000..673ae73f7cd9
--- /dev/null
+++ b/code/modules/mob/living/physiology/global_physiology.dm
@@ -0,0 +1,65 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * physiology holder for mob-wide physiology
+ *
+ * todo: on biologies update, we might need to lazy-cache this, and have different physiologies for each biology.
+ */
+/datum/global_physiology
+ /// carry baseline modify
+ var/carry_strength = CARRY_STRENGTH_BASELINE
+ /// carry penalty modifier
+ var/carry_factor = CARRY_FACTOR_BASELINE
+ /// carry bias modify
+ var/carry_bias = 1
+ /// carry weight add - added to carry_strength for carry weight only, not encumbrance.
+ var/carry_weight_add = 0
+ /// carry weight factor - multiplied to carry_factor for carry weight only, not encumbrance.
+ var/carry_weight_factor = 1
+ /// carry weight bias - multipled to carry_bias for carry weight only, not encumbrance
+ var/carry_weight_bias = 1
+
+/datum/global_physiology/proc/reset()
+ carry_strength = initial(carry_strength)
+ carry_factor = initial(carry_factor)
+ carry_weight_add = initial(carry_weight_add)
+ carry_weight_factor = initial(carry_weight_factor)
+ carry_bias = initial(carry_bias)
+ carry_weight_bias = initial(carry_weight_bias)
+
+/datum/global_physiology/proc/apply(datum/physiology_modifier/modifier)
+ // todo: check for identity relation before actually modifying variables.
+ // 'isnull' is not a good check here.
+ if(!isnull(modifier.g_carry_strength_add))
+ carry_strength += modifier.g_carry_strength_add
+ if(!isnull(modifier.g_carry_strength_factor))
+ carry_factor *= modifier.g_carry_strength_factor
+ if(!isnull(modifier.g_carry_weight_add))
+ carry_weight_add += modifier.g_carry_weight_add
+ if(!isnull(modifier.g_carry_weight_factor))
+ carry_weight_factor *= modifier.g_carry_weight_factor
+ if(!isnull(modifier.g_carry_strength_bias))
+ carry_bias *= modifier.g_carry_strength_bias
+ if(!isnull(modifier.g_carry_weight_bias))
+ carry_weight_bias *= modifier.g_carry_weight_bias
+
+/**
+ * return FALSE if we need to reset due to non-canonical operations
+ */
+/datum/global_physiology/proc/revert(datum/physiology_modifier/modifier)
+ . = TRUE
+ // todo: check for identity relation before actually modifying variables.
+ // 'isnull' is not a good check here.
+ if(!isnull(modifier.g_carry_strength_add))
+ carry_strength -= modifier.g_carry_strength_add
+ if(!isnull(modifier.g_carry_strength_factor))
+ carry_factor /= modifier.g_carry_strength_factor
+ if(!isnull(modifier.g_carry_weight_add))
+ carry_weight_add -= modifier.g_carry_weight_add
+ if(!isnull(modifier.g_carry_weight_factor))
+ carry_weight_factor /= modifier.g_carry_weight_factor
+ if(!isnull(modifier.g_carry_strength_bias))
+ carry_bias /= modifier.g_carry_strength_bias
+ if(!isnull(modifier.g_carry_weight_bias))
+ carry_weight_bias /= modifier.g_carry_weight_bias
diff --git a/code/modules/mob/living/physiology/local_physiology.dm b/code/modules/mob/living/physiology/local_physiology.dm
new file mode 100644
index 000000000000..2e2b107cedfa
--- /dev/null
+++ b/code/modules/mob/living/physiology/local_physiology.dm
@@ -0,0 +1,43 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * Physiology holder for localized physiology.
+ *
+ * * On simplemobs, only one of these exists and will affect the whole mob,
+ * as simplemobs don't have external organs/bodypart simulation.
+ */
+/datum/local_physiology
+ /// multiply all incoming **damage** by this much
+ var/inbound_brute_mod
+ /// multiply all incoming **damage** by this much
+ var/inbound_burn_mod
+ /// multiply fracture threshold by this much
+ var/bone_fracture_threshold_mod
+
+ #warn hook all
+
+/datum/local_physiology/proc/reset()
+ inbound_brute_mod = initial(initial_brute_mod)
+ inbound_burn_mod = initial(inbound_burn_mod)
+ bone_fracture_threshold_mod = initial(bone_fracture_threshold_mod)
+
+/datum/local_physiology/proc/apply(datum/physiology_modifier/modifier)
+ if(modifier.l_inbound_brute_mod != 1)
+ inbound_brute_mod *= modifier.l_inbound_brute_mod
+ if(modifier.l_inbound_burnte_mod != 1)
+ inbound_burn_mod *= modifier.l_inbound_burn_mod
+ if(modifier.l_bone_fracture_threshold_mod != 1)
+ bone_fracture_threshold_mod *= modifier.l_bone_fracture_threshold_mod
+
+/**
+ * return FALSE if we need to reset due to non-canonical operations
+ */
+/datum/local_physiology/proc/revert(datum/physiology_modifier/modifier)
+ . = TRUE
+ if(modifier.l_inbound_brute_mod != 1)
+ inbound_brute_mod /= modifier.l_inbound_brute_mod
+ if(modifier.l_inbound_burnte_mod != 1)
+ inbound_burn_mod /= modifier.l_inbound_burn_mod
+ if(modifier.l_bone_fracture_threshold_mod != 1)
+ bone_fracture_threshold_mod /= modifier.l_bone_fracture_threshold_mod
diff --git a/code/modules/mob/living/physiology/physiology_modifier.dm b/code/modules/mob/living/physiology/physiology_modifier.dm
new file mode 100644
index 000000000000..c5c9f0184dd7
--- /dev/null
+++ b/code/modules/mob/living/physiology/physiology_modifier.dm
@@ -0,0 +1,87 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * physiology modifier
+ */
+/datum/physiology_modifier
+ abstract_type = /datum/physiology_modifier
+
+ /// our name
+ var/name = "Some Modifier"
+ /// is this a globally cached modifier?
+ var/is_globally_cached = FALSE
+ /// biologies this applies to, for limb-specific modifiers
+ var/biology_types = BIOLOGY_TYPES_ALL
+
+ //* -- global modifiers -- *//
+
+ //* carry strength / weight *//
+ var/g_carry_strength_add = 0
+ var/g_carry_strength_factor = 1
+ var/g_carry_strength_bias = 1
+ var/g_carry_weight_add = 0
+ var/g_carry_weight_factor = 1
+ var/g_carry_weight_bias = 1
+
+ //* -- local modifiers -- *//
+
+ //* inbound damage multiply *//
+ var/l_inbound_brute_mod = 1
+ var/l_inbound_burn_mod = 1
+
+ //* wound thresholds *//
+ var/l_bone_fracture_threshold_mod = 1
+
+ #warn add to admin interface & serialize & deserialize
+
+/datum/physiology_modifier/serialize()
+ . = ..()
+ if(name != initial(name))
+ .["name"] = name
+ if(g_carry_strength_add != initial(g_carry_strength_add))
+ .["g_carry_strength_add"] = g_carry_strength_add
+ if(g_carry_strength_factor != initial(g_carry_strength_factor))
+ .["g_carry_strength_factor"] = g_carry_strength_factor
+
+/datum/physiology_modifier/deserialize(list/data)
+ . = ..()
+ if(istext(data["name"]))
+ name = data["name"]
+ if(isnum(data["g_carry_strength_add"]))
+ g_carry_strength_add = data["g_carry_strength_add"]
+ if(isnum(data["g_carry_strength_factor"]))
+ g_carry_strength_factor = data["g_carry_strength_factor"]
+ if(isnum(data["g_carry_strength_bias"]))
+ g_carry_strength_bias = data["g_carry_strength_bias"]
+ if(isnum(data["g_carry_weight_add"]))
+ g_carry_weight_add = data["g_carry_weight_add"]
+ if(isnum(data["g_carry_weight_factor"]))
+ g_carry_weight_factor = data["g_carry_weight_factor"]
+ if(isnum(data["g_carry_weight_bias"]))
+ g_carry_weight_bias = data["g_carry_weight_bias"]
+
+/**
+ * subtype for hardcoded physiology modifiers
+ */
+/datum/physiology_modifier/intrinsic
+ abstract_type = /datum/physiology_modifier/intrinsic
+
+/**
+ * subtype for admin varedit tracking
+ */
+/datum/physiology_modifier/varedit
+ name = "Admin Varedits"
+
+GLOBAL_LIST_EMPTY(cached_physiology_modifiers)
+
+/proc/cached_physiology_modifier(datum/physiology_modifier/path)
+ ASSERT(ispath(path, /datum/physiology_modifier))
+ ASSERT(initial(path.abstract_type) != path)
+ // if it already exists, set default return value to it and return
+ if((. = GLOB.cached_physiology_modifiers[path]))
+ return
+ var/datum/physiology_modifier/modifier = new path
+ modifier.is_globally_cached = TRUE
+ GLOB.cached_physiology_modifiers[path] = modifier
+ return modifier
diff --git a/code/modules/mob/living/silicon/pai/mobility.dm b/code/modules/mob/living/silicon/pai/mobility.dm
index 42350a53da04..f0003ef987fd 100644
--- a/code/modules/mob/living/silicon/pai/mobility.dm
+++ b/code/modules/mob/living/silicon/pai/mobility.dm
@@ -69,7 +69,7 @@
return FALSE
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
- for(var/obj/item/organ/external/affecting in H.organs)
+ for(var/obj/item/organ/external/affecting as anything in H.external_organs)
if(shell in affecting.implants)
affecting.inflict_bodypart_damage(
brute = rand(30, 50),
diff --git a/code/modules/mob/living/silicon/robot/analyzer.dm b/code/modules/mob/living/silicon/robot/analyzer.dm
index 71c786ce795e..cef897f9aa95 100644
--- a/code/modules/mob/living/silicon/robot/analyzer.dm
+++ b/code/modules/mob/living/silicon/robot/analyzer.dm
@@ -74,7 +74,7 @@
to_chat(user, "External prosthetics:")
var/organ_found
if(H.internal_organs.len)
- for(var/obj/item/organ/external/E in H.organs)
+ for(var/obj/item/organ/external/E as anything in H.external_organs)
if(!(E.robotic >= ORGAN_ROBOT))
continue
organ_found = 1
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
index 10cfdb456d18..9ac9f3bbb246 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
@@ -130,11 +130,6 @@
//PRETTIER TOOL LIST.
/mob/living/silicon/robot/drone/installed_modules()
-
- if(weapon_lock)
- to_chat(src, "Weapon lock active, unable to use modules! Count:[weaponlock_time]")
- return
-
if(!module)
module = new /obj/item/robot_module/drone(src)
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index 26d0982af592..592625d16819 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -14,8 +14,6 @@
update_items()
if (src.stat != DEAD) //still using power
use_power()
- process_killswitch()
- process_locks()
process_queued_alarms()
/mob/living/silicon/robot/proc/clamp_values()
@@ -239,26 +237,6 @@
src.module_state_3:screen_loc = ui_inv3
updateicon()
-/mob/living/silicon/robot/proc/process_killswitch()
- if(killswitch)
- killswitch_time --
- if(killswitch_time <= 0)
- if(src.client)
- to_chat(src, "Killswitch Activated")
- killswitch = 0
- spawn(5)
- gib()
-
-/mob/living/silicon/robot/proc/process_locks()
- if(weapon_lock)
- uneq_all()
- weaponlock_time --
- if(weaponlock_time <= 0)
- if(src.client)
- to_chat(src, "Weapon Lock Timed Out!")
- weapon_lock = 0
- weaponlock_time = 120
-
// todo: better way
/mob/living/silicon/robot/update_mobility()
. = ..()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index c1e3f9dccd26..09208af5057c 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -133,10 +133,6 @@
var/datum/effect_system/ion_trail_follow/ion_trail = null
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
var/jeton = FALSE
- var/killswitch = FALSE
- var/killswitch_time = 60
- var/weapon_lock = FALSE
- var/weaponlock_time = 120
/// Cyborgs will sync their laws with their AI by default
var/lawupdate = TRUE
/// Used when looking to see if a borg is locked down.
@@ -987,10 +983,6 @@
add_overlay("wreck-overlay")
/mob/living/silicon/robot/proc/installed_modules()
- if(weapon_lock)
- to_chat(src, "Weapon lock active, unable to use modules! Count:[weaponlock_time]")
- return
-
if(!module)
pick_module()
return
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 5503d984d817..a35c4cfa504f 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -94,6 +94,7 @@
handle_light()
handle_regular_hud_updates()
handle_vision()
+ handle_instability()
/mob/living/silicon/handle_regular_hud_updates()
. = ..()
diff --git a/code/modules/mob/living/simple_mob/life.dm b/code/modules/mob/living/simple_mob/life.dm
index 565252fa8792..d992e21d7a73 100644
--- a/code/modules/mob/living/simple_mob/life.dm
+++ b/code/modules/mob/living/simple_mob/life.dm
@@ -142,15 +142,6 @@
oxygen.icon_state = "oxy0"
adjustOxyLoss(-unsuitable_atoms_damage)
-/mob/living/simple_mob/proc/handle_guts(dt)
- switch(stat)
- if(DEAD)
- for(var/obj/item/organ/O in organs)
- O.tick_death(dt)
- else
- for(var/obj/item/organ/O in organs)
- O.tick_life(dt)
-
/mob/living/simple_mob/proc/handle_supernatural()
if(purge)
purge -= 1
diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm
index ad4d7794dfb5..817f8b5c232d 100644
--- a/code/modules/mob/living/simple_mob/simple_mob.dm
+++ b/code/modules/mob/living/simple_mob/simple_mob.dm
@@ -245,8 +245,10 @@
/// legacy armor, applied on init
var/list/armor_legacy_mob
- ///Does the simple mob drop organs when butchered?
- butchery_drops_organs = FALSE
+ //* Physiology *//
+ /// Our whole-body local physiology
+ var/datum/local_physiology/local_physiology
+ #warn hook
/mob/living/simple_mob/Initialize(mapload)
if(armor_legacy_mob)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/animal.dm b/code/modules/mob/living/simple_mob/subtypes/animal/animal.dm
index 1deea1493273..dbaac5a9f52d 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/animal.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/animal.dm
@@ -11,15 +11,6 @@
ai_holder_type = /datum/ai_holder/polaris/simple_mob/melee
- internal_organs = list(\
- /obj/item/organ/internal/brain,\
- /obj/item/organ/internal/heart,\
- /obj/item/organ/internal/liver,\
- /obj/item/organ/internal/stomach,\
- /obj/item/organ/internal/intestine,\
- /obj/item/organ/internal/lungs\
- )
-
- butchery_loot = list(\
- /obj/item/stack/animalhide = 3\
- )
+ butchery_loot = list(
+ /obj/item/stack/animalhide = 3,
+ )
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
index 238b1f97a3d6..5f00836914b5 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
@@ -115,7 +115,7 @@
if(istype(host, /mob/living/carbon/human))
var/mob/living/carbon/human/H = host
- var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/head = H.legacy_organ_by_zone(BP_HEAD)
if(head)
head.implants -= src
@@ -177,7 +177,7 @@
if(istype(host, /mob/living/carbon/human))
var/mob/living/carbon/human/H = host
- var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/head = H.legacy_organ_by_zone(BP_HEAD)
if(head)
head.implants -= src
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_powers.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_powers.dm
index 2e93362e0c7c..2225a370521b 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_powers.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_powers.dm
@@ -112,12 +112,12 @@
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/I = H.internal_organs_by_name["brain"]
+ var/obj/item/organ/I = H.keyed_organs[ORGAN_KEY_BRAIN]
if(!I) // No brain organ, so the borer moves in and replaces it permanently.
replace_brain()
else
// If they're in normally, implant removal can get them out.
- var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/head = H.legacy_organ_by_zone(BP_HEAD)
head.implants += src
return
@@ -180,11 +180,12 @@
H.ChangeToHusk()
+ #warn INSERT THIS PROPERLY
var/obj/item/organ/internal/borer/B = new(H)
H.internal_organs_by_name["brain"] = B
H.internal_organs |= B
- var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(BP_HEAD)
affecting.implants -= src
var/s2h_id = src.computer_id
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm
index 73cf4d0e7dd6..48824c1606e6 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm
@@ -59,7 +59,7 @@
..() // Inject the stoxin here.
if(ishuman(L) && prob(egg_inject_chance))
var/mob/living/carbon/human/H = L
- var/obj/item/organ/external/O = H.get_organ(target_zone)
+ var/obj/item/organ/external/O = H.legacy_organ_by_zone(target_zone)
if(O)
var/eggcount = 0
for(var/obj/effect/spider/eggcluster/E in O.implants)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm
index 1306b7868f26..77ce2d944f22 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm
@@ -301,7 +301,7 @@
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- host_bodypart = H.get_organ(infest_target)
+ host_bodypart = H.legacy_organ_by_zone(infest_target)
host_bodypart.implants |= src
return
diff --git a/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/subtypes.dm b/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/subtypes.dm
index 4f6526c96aa0..6ccdb627607b 100644
--- a/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/subtypes.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/subtypes.dm
@@ -564,7 +564,7 @@
if(ishuman(holder)) // Robolimbs need this code sadly.
var/mob/living/carbon/human/H = holder
- for(var/obj/item/organ/external/E in H.organs)
+ for(var/obj/item/organ/external/E as anything in H.external_organs)
var/obj/item/organ/external/O = E
O.heal_damage(2, 2, 0, 1)
else
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 2dfb74a08761..7055ee15d98e 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -19,8 +19,6 @@
// actions
actions_controlled = new /datum/action_holder/mob_actor(src)
actions_innate = new /datum/action_holder/mob_actor(src)
- // physiology
- init_physiology()
// atom HUDs
prepare_huds()
set_key_focus(src)
@@ -855,7 +853,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/affected
- for(var/obj/item/organ/external/organ in H.organs) //Grab the organ holding the implant.
+ for(var/obj/item/organ/external/organ as anything in H.external_organs) //Grab the organ holding the implant.
for(var/obj/item/O in organ.implants)
if(O == selection)
affected = organ
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 93d40d40da3f..fa64e311e458 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -85,12 +85,6 @@
/// Tracks if we have gravity from environment right now.
var/in_gravity
- //? Physiology
- /// overall physiology - see physiology.dm
- var/datum/global_physiology/physiology
- /// physiology modifiers - see physiology.dm; set to list of paths at init to initialize into instances.
- var/list/datum/physiology_modifier/physiology_modifiers
-
//? Actionspeed
/// List of action speed modifiers applying to this mob
var/list/actionspeed_modification //Lazy list, see mob_movespeed.dm
@@ -239,8 +233,10 @@
var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas.
var/unacidable = 0
/// List of things pinning this creature to walls. (see living_defense.dm)
+ // todo: /living
var/list/pinned = list()
/// Embedded items, since simple mobs don't have organs.
+ // todo: /living
var/list/embedded = list()
/// For speaking/listening.
var/list/languages = list()
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 889e85b4b709..a6153307ae56 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -2,7 +2,7 @@
/proc/isxenomorph(A)
if(istype(A, /mob/living/carbon/human))
var/mob/living/carbon/human/H = A
- return istype(H.species, /datum/species/xenos)
+ return istype(H.species, /datum/species/xenomorph)
return 0
/proc/issmall(A)
diff --git a/code/modules/mob/movement.dm b/code/modules/mob/movement.dm
index 94a139bb449d..a8b608d426d8 100644
--- a/code/modules/mob/movement.dm
+++ b/code/modules/mob/movement.dm
@@ -250,8 +250,8 @@
else if(istype(mob.buckled, /obj/structure/bed/chair/wheelchair))
if(ishuman(mob))
var/mob/living/carbon/human/driver = mob
- var/obj/item/organ/external/l_hand = driver.get_organ("l_hand")
- var/obj/item/organ/external/r_hand = driver.get_organ("r_hand")
+ var/obj/item/organ/external/l_hand = driver.legacy_organ_by_zone("l_hand")
+ var/obj/item/organ/external/r_hand = driver.legacy_organ_by_zone("r_hand")
if((!l_hand || l_hand.is_stump()) && (!r_hand || r_hand.is_stump()))
return // No hands to drive your chair? Tough luck!
//drunk wheelchair driving
diff --git a/code/modules/mob/physiology.dm b/code/modules/mob/physiology.dm
deleted file mode 100644
index d8f62a1bd31e..000000000000
--- a/code/modules/mob/physiology.dm
+++ /dev/null
@@ -1,238 +0,0 @@
-//* This file is explicitly licensed under the MIT license. *//
-//* Copyright (c) 2023 Citadel Station developers. *//
-
-/**
- * physiology holder
- *
- * todo: on biologies update, we might need to lazy-cache this, and have different physiologies for each biology.
- */
-/datum/global_physiology
- /// carry baseline modify
- var/carry_strength = CARRY_STRENGTH_BASELINE
- /// carry penalty modifier
- var/carry_factor = CARRY_FACTOR_BASELINE
- /// carry bias modify
- var/carry_bias = 1
- /// carry weight add - added to carry_strength for carry weight only, not encumbrance.
- var/carry_weight_add = 0
- /// carry weight factor - multiplied to carry_factor for carry weight only, not encumbrance.
- var/carry_weight_factor = 1
- /// carry weight bias - multipled to carry_bias for carry weight only, not encumbrance
- var/carry_weight_bias = 1
-
-/datum/global_physiology/proc/reset()
- carry_strength = initial(carry_strength)
- carry_factor = initial(carry_factor)
- carry_weight_add = initial(carry_weight_add)
- carry_weight_factor = initial(carry_weight_factor)
- carry_bias = initial(carry_bias)
- carry_weight_bias = initial(carry_weight_bias)
- return TRUE
-
-/datum/global_physiology/proc/apply(datum/physiology_modifier/modifier)
- if(!isnull(modifier.carry_strength_add))
- carry_strength += modifier.carry_strength_add
- if(!isnull(modifier.carry_strength_factor))
- carry_factor *= modifier.carry_strength_factor
- if(!isnull(modifier.carry_weight_add))
- carry_weight_add += modifier.carry_weight_add
- if(!isnull(modifier.carry_weight_factor))
- carry_weight_factor *= modifier.carry_weight_factor
- if(!isnull(modifier.carry_strength_bias))
- carry_bias *= modifier.carry_strength_bias
- if(!isnull(modifier.carry_weight_bias))
- carry_weight_bias *= modifier.carry_weight_bias
-
-/**
- * return FALSE if we need to reset due to non-canonical operations
- */
-/datum/global_physiology/proc/revert(datum/physiology_modifier/modifier)
- . = TRUE
- if(!isnull(modifier.carry_strength_add))
- carry_strength -= modifier.carry_strength_add
- if(!isnull(modifier.carry_strength_factor))
- carry_factor /= modifier.carry_strength_factor
- if(!isnull(modifier.carry_weight_add))
- carry_weight_add -= modifier.carry_weight_add
- if(!isnull(modifier.carry_weight_factor))
- carry_weight_factor /= modifier.carry_weight_factor
- if(!isnull(modifier.carry_strength_bias))
- carry_bias /= modifier.carry_strength_bias
- if(!isnull(modifier.carry_weight_bias))
- carry_weight_bias /= modifier.carry_weight_bias
-
-/datum/local_physiology
-
-/datum/local_physiology/proc/reset()
- return TRUE
-
-/datum/local_physiology/proc/apply(datum/physiology_modifier/modifier)
- return TRUE
-
-/datum/local_physiology/proc/revert(datum/physiology_modifier/modifier)
- return TRUE
-
-/**
- * physiology modifier
- */
-/datum/physiology_modifier
- abstract_type = /datum/physiology_modifier
-
- /// our name
- var/name = "Some Modifier"
- /// is this a globally cached modifier?
- var/is_globally_cached = FALSE
- /// biologies this applies to, for limb-specific modifiers
- var/biology_types = BIOLOGY_TYPES_ALL
-
- //* -- global modifiers -- *//
-
- //* carry strength / weight *//
- var/carry_strength_add = 0
- var/carry_strength_factor = 1
- var/carry_strength_bias = 1
- var/carry_weight_add = 0
- var/carry_weight_factor = 1
- var/carry_weight_bias = 1
-
-/datum/physiology_modifier/serialize()
- . = ..()
- if(name != initial(name))
- .["name"] = name
- if(carry_strength_add != initial(carry_strength_add))
- .["carry_strength_add"] = carry_strength_add
- if(carry_strength_factor != initial(carry_strength_factor))
- .["carry_strength_factor"] = carry_strength_factor
-
-/datum/physiology_modifier/deserialize(list/data)
- . = ..()
- if(istext(data["name"]))
- name = data["name"]
- if(isnum(data["carry_strength_add"]))
- carry_strength_add = data["carry_strength_add"]
- if(isnum(data["carry_strength_factor"]))
- carry_strength_factor = data["carry_strength_factor"]
- if(isnum(data["carry_strength_bias"]))
- carry_strength_bias = data["carry_strength_bias"]
- if(isnum(data["carry_weight_add"]))
- carry_weight_add = data["carry_weight_add"]
- if(isnum(data["carry_weight_factor"]))
- carry_weight_factor = data["carry_weight_factor"]
- if(isnum(data["carry_weight_bias"]))
- carry_weight_bias = data["carry_weight_bias"]
-
-/**
- * subtype for hardcoded physiology modifiers
- */
-/datum/physiology_modifier/intrinsic
- abstract_type = /datum/physiology_modifier/intrinsic
-
-/**
- * subtype for admin varedit tracking
- */
-/datum/physiology_modifier/varedit
- name = "Admin Varedits"
-
-GLOBAL_LIST_EMPTY(cached_physiology_modifiers)
-
-/proc/cached_physiology_modifier(datum/physiology_modifier/path)
- ASSERT(ispath(path, /datum/physiology_modifier))
- ASSERT(initial(path.abstract_type) != path)
- // if it already exists, set default return value to it and return
- if((. = GLOB.cached_physiology_modifiers[path]))
- return
- var/datum/physiology_modifier/modifier = new path
- modifier.is_globally_cached = TRUE
- GLOB.cached_physiology_modifiers[path] = modifier
- return modifier
-
-/**
- * initializes physiology modifiers
- * paths in physiology modifier are converted to the cached instances in globals.
- */
-/mob/proc/init_physiology()
- for(var/i in 1 to length(physiology_modifiers))
- if(ispath(physiology_modifiers[i]))
- physiology_modifiers[i] = cached_physiology_modifier(physiology_modifiers[i])
- rebuild_physiology()
-
-/**
- * adds a modifier to physiology
- * you are responsible for not double-adding
- * paths are allowed; if modifier is a path, it'll be the globally cached modifier of that type.
- */
-/mob/proc/add_physiology_modifier(datum/physiology_modifier/modifier)
- if(ispath(modifier))
- modifier = cached_physiology_modifier(modifier)
- ASSERT(!(modifier in physiology_modifiers))
- LAZYADD(physiology_modifiers, modifier)
- physiology.apply(modifier)
- return TRUE
-
-/**
- * removes a modifier from physiology
- * you are responsible for not double-adding
- * paths are allowed
- */
-/mob/proc/remove_physiology_modifier(datum/physiology_modifier/modifier)
- if(ispath(modifier))
- modifier = cached_physiology_modifier(modifier)
- ASSERT(modifier in physiology_modifiers)
- LAZYREMOVE(physiology_modifiers, modifier)
- if(!physiology.revert(modifier))
- // todo: optimize with reset().
- rebuild_physiology()
- return TRUE
-
-/**
- * completely rebuilds physiology from our modifiers
- */
-/mob/proc/rebuild_physiology()
- physiology = new
- for(var/datum/physiology_modifier/modifier as anything in physiology_modifiers)
- if(!istype(modifier))
- physiology_modifiers -= modifier
- continue
- physiology.apply(modifier)
-
-// i'm not going to fucking support vv without automated backreferences and macros, holy shit.
-// /mob/proc/get_varedit_physiology_modifier()
-// RETURN_TYPE(/datum/physiology_modifier)
-// . = locate(/datum/physiology_modifier/varedit) in physiology_modifiers
-// if(!isnull(.))
-// return
-// var/datum/physiology_modifier/varedit/new_holder = new
-// add_physiology_modifier(new_holder)
-// return new_holder
-
-// todo: you can tell from the proc name that this needs to be kicked somewhere eles later.
-/proc/ask_admin_for_a_physiology_modifier(mob/user)
- var/datum/tgui_dynamic_query/query = new
- query.string("name", "Name", "Name your modifier.", 64, FALSE, "Custom Modifier")
- query.number("carry_strength_add", "Carry Strength - Add", "Modify the person's base carry strength. Higher is better.", default = 0)
- query.number("carry_strength_factor", "Carry Factor - Multiply", "Multiply the person's carry weight/encumbrance to slowdown effect when carrying over their limit. Lower is better.", default = 1)
- query.number("carry_strength_bias", "Carry Bias - Multiply", "Multiply the person's carry weight/encumbrance to slowdown bias when carrying over their limit. Lower is better.", default = 1)
- query.number("carry_weight_add", "Carry Weight - Add", "Modify the person's base carry weight. Higher is better. This only applies to weight, not encumbrance.", default = 0)
- query.number("carry_weight_factor", "Carry Weight - Multiply", "Multiply the person's weight to slowdown effect when carrying over their limit. Lower is better. This only applies to weight, not encumbrance.", default = 1)
- query.number("carry_weight_bias", "Carry Weight - Bias", "Multiply the person's weight to slowdown calculation bias; lower is better.", default = 1)
-
- var/list/choices = tgui_dynamic_input(user, "Add a physiology modifier", "Add Physiology Modifier", query)
-
- if(isnull(choices))
- return
-
- var/datum/physiology_modifier/modifier = new
-
- // we manually deserialize because we might have custom datatypes
- // in the future that won't be serialized by the ui necessarily in the same way
- // we would serialize it via json.
-
- modifier.name = choices["name"]
- modifier.carry_strength_add = choices["carry_strength_add"]
- modifier.carry_strength_factor = choices["carry_strength_factor"]
- modifier.carry_strength_bias = choices["carry_strength_bias"]
- modifier.carry_weight_add = choices["carry_weight_add"]
- modifier.carry_weight_factor = choices["carry_weight_factor"]
- modifier.carry_weight_bias = choices["carry_weight_bias"]
-
- return modifier
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 1eea2c19674b..8735057837c1 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -7,8 +7,6 @@
update_mobility()
icon = null
invisibility = 101
- for(var/t in organs)
- qdel(t)
var/atom/movable/overlay/animation = new /atom/movable/overlay( loc )
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
@@ -31,7 +29,6 @@
to_chat(src, "You are now [species.name]. ")
qdel(animation)
-
return src
/mob/new_player/AIize()
@@ -41,8 +38,6 @@
/mob/living/carbon/human/AIize(move=1) // 'move' argument needs defining here too because BYOND is dumb
if (transforming)
return
- for(var/t in organs)
- qdel(t)
return ..(move)
@@ -91,8 +86,7 @@
O.rename_self("ai")
// Mobs still instantly del themselves, thus we need to spawn or O will never be returned.
- spawn(0)
- qdel(src)
+ qdel(src)
return O
/// Human -> Robot
@@ -105,9 +99,6 @@
update_mobility()
icon = null
invisibility = 101
- for(var/t in organs)
- qdel(t)
-
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot( loc )
// cyborgs produced by Robotize get an automatic power cell
@@ -162,8 +153,6 @@
update_mobility()
icon = null
invisibility = 101
- for(var/t in organs)
- qdel(t)
var/alien_caste = pick("Hunter","Sentinel","Drone")
var/mob/living/carbon/human/new_xeno = create_new_xenomorph(alien_caste,loc)
@@ -185,8 +174,6 @@
update_mobility()
icon = null
invisibility = 101
- for(var/t in organs) //this really should not be necessary
- qdel(t)
var/mob/living/simple_mob/animal/passive/dog/corgi/new_corgi = new /mob/living/simple_mob/animal/passive/dog/corgi (loc)
new_corgi.a_intent = INTENT_HARM
@@ -216,9 +203,6 @@
icon = null
invisibility = 101
- for(var/t in organs)
- qdel(t)
-
var/mob/new_mob = new mobpath(src.loc)
transfer_client_to(new_mob)
diff --git a/code/modules/nifsoft/nif.dm b/code/modules/nifsoft/nif.dm
index 5636e2af6a15..ed848435e1e9 100644
--- a/code/modules/nifsoft/nif.dm
+++ b/code/modules/nifsoft/nif.dm
@@ -137,7 +137,7 @@ GLOBAL_LIST_INIT(nif_id_lookup, init_nif_id_lookup())
if(istype(brain))
should_be_in = brain.parent_organ
- if(istype(H) && !H.nif && H.species && (loc == H.get_organ(should_be_in)))
+ if(istype(H) && !H.nif && H.species && (loc == H.legacy_organ_by_zone(should_be_in)))
if(!bioadap && (H.species.species_flags & NO_SCAN)) //NO_SCAN is the default 'too complicated' flag
return FALSE
@@ -163,7 +163,7 @@ GLOBAL_LIST_INIT(nif_id_lookup, init_nif_id_lookup())
if(istype(brain))
should_be_in = brain.parent_organ
- parent = H.get_organ(should_be_in)
+ parent = H.legacy_organ_by_zone(should_be_in)
//Ok, nevermind then!
if(!istype(parent))
return FALSE
@@ -361,7 +361,7 @@ GLOBAL_LIST_INIT(nif_id_lookup, init_nif_id_lookup())
//Called each life() tick on the mob
/obj/item/nif/proc/on_life()
- if(!human || loc != human.get_organ(should_be_in))
+ if(!human || loc != human.legacy_organ_by_zone(should_be_in))
unimplant(human)
return FALSE
@@ -675,7 +675,7 @@ GLOBAL_LIST_INIT(nif_id_lookup, init_nif_id_lookup())
if(T.w_uniform || T.wear_suit)
to_chat(user,"Remove any clothing they have on, as it might interfere!")
return
- var/obj/item/organ/external/eo = T.get_organ(BP_TORSO)
+ var/obj/item/organ/external/eo = T.legacy_organ_by_zone(BP_TORSO)
if(!T)
to_chat(user,"They should probably regrow their torso first.")
return
diff --git a/code/modules/organs/external/external-wound.dm b/code/modules/organs/external/external-wound.dm
new file mode 100644
index 000000000000..8184aa40b52a
--- /dev/null
+++ b/code/modules/organs/external/external-wound.dm
@@ -0,0 +1,145 @@
+/**
+ * Creates a wound on this organ.
+ *
+ * todo: better documentation
+ */
+/obj/item/organ/external/proc/create_wound(var/type = WOUND_TYPE_CUT, var/damage)
+ if(damage == 0)
+ return
+
+ //moved this before the open_wound check so that having many small wounds for example doesn't somehow protect you from taking internal damage (because of the return)
+ //Possibly trigger an internal wound, too.
+ var/local_damage = brute_dam + burn_dam + damage
+ if((damage > 15) && (type != WOUND_TYPE_BURN) && (local_damage > 30) && prob(damage) && (robotic < ORGAN_ROBOT) && !(species.species_flags & NO_BLOOD))
+ create_specific_wound(/datum/wound/internal_bleeding, min(damage - 15, 15))
+ owner.custom_pain("You feel something rip in your [name]!", 50)
+
+//Burn damage can cause fluid loss due to blistering and cook-off
+
+ if((damage > 5 || damage + burn_dam >= 15) && type == WOUND_TYPE_BURN && (robotic < ORGAN_ROBOT) && !(species.species_flags & NO_BLOOD))
+ var/fluid_loss = 0.4 * (damage/(owner.getMaxHealth() - config_legacy.health_threshold_dead)) * owner.species.blood_volume*(1 - owner.species.blood_level_fatal)
+ owner.remove_blood(fluid_loss)
+
+ // first check whether we can widen an existing wound
+ if(length(wounds) > 0 && prob(max(50+(wound_tally-1)*10,90)))
+ if((type == WOUND_TYPE_CUT || type == WOUND_TYPE_BRUISE) && damage >= 5)
+ //we need to make sure that the wound we are going to worsen is compatible with the type of damage...
+ var/list/compatible_wounds = list()
+ for (var/datum/wound/W as anything in wounds)
+ if (W.can_worsen(type, damage))
+ compatible_wounds += W
+
+ if(compatible_wounds.len)
+ var/datum/wound/W = pick(compatible_wounds)
+ W.open_wound(damage)
+ if(prob(25))
+ if(robotic >= ORGAN_ROBOT)
+ owner.visible_message("The damage to [owner.name]'s [name] worsens.",\
+ "The damage to your [name] worsens.",\
+ "You hear the screech of abused metal.")
+ else
+ owner.visible_message("The wound on [owner.name]'s [name] widens with a nasty ripping noise.",\
+ "The wound on your [name] widens with a nasty ripping noise.",\
+ "You hear a nasty ripping noise, as if flesh is being torn apart.")
+ return
+
+ //Creating wound
+ var/wound_type = get_wound_type(type, damage)
+
+ if(wound_type)
+ var/datum/wound/W = new wound_type(damage)
+
+ //Check whether we can add the wound to an existing wound
+ for(var/datum/wound/other as anything in wounds)
+ if(other.can_merge(W))
+ other.merge_wound(W)
+ W = null // to signify that the wound was added
+ break
+ if(W)
+ LAZYADD(wounds, W)
+
+/**
+ * Creates a specific kind of wound on this organ.
+ *
+ * This only creates the wound, it does not do damage side effects,
+ * like vaporizing blood with burns, etc
+ *
+ * Such side effects should not be in the procs for making wounds!
+ *
+ * If you need to modify variables other than "damage", grab the returned wound.
+ *
+ * @params
+ * * path - typepath of /datum/wound to create.
+ * * damage - amount of damage it should have.
+ * * updating - update damages?
+ *
+ * @return the /datum/wound created, *or* the /datum/wound merged, *or* null if it was rejected.
+ */
+/obj/item/organ/external/proc/create_specific_wound(path, damage, updating = TRUE)
+ ASSERT(ispath(path, /datum/wound))
+
+ var/datum/wound/creating = new path(damage)
+ var/datum/wound/merged
+
+ for(var/datum/wound/other as anything in wounds)
+ if(other.can_merge(creating))
+ other.merge_wound(creating)
+ merged = other
+ break
+
+ if(isnull(merged))
+ // didn't merge, add
+ LAZYADD(wounds, creating)
+ . = creating
+ else
+ // merged, return merged
+ // we don't manually qdel creating - hopefully no one actually does something
+ // deranged down the line like making wounds reference externally!
+ . = merged
+
+ if(updating)
+ update_damages()
+
+/**
+ * Immediately cures a specific typepath of wound, or a specific instance of wound
+ *
+ * @params
+ * * path - path of wound to cure, all subtypes count!
+ * * all - cure all instances, or just one?
+ * * updating - update damages?
+ *
+ * @return TRUE / FALSE based on if anything was removed.
+ */
+/obj/item/organ/external/proc/cure_specific_wound(datum/wound/path_or_instance, all = FALSE, updating = TRUE)
+ . = FALSE
+ // todo: remove the assert / is in check, free performance, only here to prevent accidental misuse for now.
+ ASSERT(ispath(path_or_instance, /datum/wound))
+ for(var/datum/wound/W in wounds)
+ if(istype(W, path_or_instance))
+ wounds -= W
+ . = TRUE
+ if(all)
+ break
+
+ if(!.)
+ return
+
+ if(updating)
+ update_damages()
+
+/**
+ * Immediately cures a wound instance.
+ *
+ * Use this proc from within loops over the wounds list.
+ *
+ * Warning: We do not check if the wound exists.s
+ *
+ * @params
+ * * wound - the wound to cure
+ * * updating - update damages?
+ */
+/obj/item/organ/external/proc/cure_exact_wound(datum/wound/wound, updating = TRUE)
+ wounds -= wound
+
+ if(updating)
+ update_damages()
diff --git a/code/modules/organs/external/external.dm b/code/modules/organs/external/external.dm
index e6507bcfb7a3..0f99c8b5ffd7 100644
--- a/code/modules/organs/external/external.dm
+++ b/code/modules/organs/external/external.dm
@@ -1,4 +1,5 @@
/obj/item/organ/external
+ abstract_type = /obj/item/organ/external
name = "external"
max_damage = 0
min_broken_damage = 30
@@ -168,14 +169,6 @@
if(splinted && splinted.loc == src)
qdel(splinted)
splinted = null
-
- if(istype(owner))
- owner.organs -= src
- owner.organs_by_name[organ_tag] = null
- owner.organs_by_name -= organ_tag
- while(null in owner.organs)
- owner.organs -= null
-
implants.Cut() // Remove these too!
return ..()
@@ -289,7 +282,7 @@
owner.shock_stage += 20
//check to see if we still need the verb
- for(var/obj/item/organ/external/limb in owner.organs)
+ for(var/obj/item/organ/external/limb as anything in owner.external_organs)
if(limb.dislocated == 1)
return
remove_verb(owner, /mob/living/carbon/human/proc/relocate)
@@ -611,20 +604,6 @@
robotize()
owner.update_health()
-/obj/item/organ/external/remove_rejuv()
- if(owner)
- owner.organs -= src
- owner.organs_by_name[organ_tag] = null
- owner.organs_by_name -= organ_tag
- while(null in owner.organs) owner.organs -= null
- if(children && children.len)
- for(var/obj/item/organ/external/E in children)
- E.remove_rejuv()
- children.Cut()
- for(var/obj/item/organ/internal/I in internal_organs)
- I.remove_rejuv()
- ..()
-
/****************************************************
PROCESSING & UPDATING
****************************************************/
@@ -953,6 +932,7 @@ Note that amputating the affected organ does in fact remove the infection from t
LAZYDISTINCTADD(parent_organ.wounds, W)
parent_organ.update_damages()
else
+ #warn INSERT THIS PROPERLY
var/obj/item/organ/external/stump/stump = new (victim, 0, src)
if(robotic >= ORGAN_ROBOT)
stump.robotize()
@@ -1496,12 +1476,37 @@ Note that amputating the affected organ does in fact remove the infection from t
if(!istype(I,/obj/item/implant) && !istype(I,/obj/item/nif))
return TRUE
+//* Contains *//
+
+/obj/item/organ/external/proc/get_internal_organs() as /list
+ . = list()
+#warn impl
+
//* Hand Integration *//
// todo: some kind of API for querying what hands this organ provides
// this will require organs be composition instead of inheritance,
// as defining this on every left / right hand would be satanic.
+//* Insert / Remove *//
+
+/obj/item/organ/external/register(mob/living/carbon/target)
+ target.external_organs += src
+ if(organ_key)
+ target.keyed_organs[organ_key] = src
+ target.keyed_organs[organ_tag] = src
+ if(organ_tag)
+ target.legacy_organ_by_tag[organ_tag] = src
+
+/obj/item/organ/external/unregister(mob/living/carbon/target)
+ target.external_organs -= src
+ if(organ_key && target.keyed_organs[organ_key] == src)
+ target.keyed_organs -= organ_key
+ if(organ_key && target.legacy_organ_by_tag[organ_key] == src)
+ target.legacy_organ_by_tag -= organ_key
+ if(organ_tag && target.legacy_organ_by_tag[organ_tag] == src)
+ target.legacy_organ_by_tag -= organ_tag
+
//* Environmentals *//
// todo: limb specific
diff --git a/code/modules/organs/external/external_icons.dm b/code/modules/organs/external/external_icons.dm
index a421cd26de5d..61a581bdf5ba 100644
--- a/code/modules/organs/external/external_icons.dm
+++ b/code/modules/organs/external/external_icons.dm
@@ -47,7 +47,7 @@ GLOBAL_LIST_EMPTY(limb_icon_cache)
/obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/human)
..()
- var/obj/item/organ/internal/eyes/eyes = owner.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/eyes = owner.keyed_organs[ORGAN_KEY_EYES]
if(eyes) eyes.update_colour()
/obj/item/organ/external/head/get_icon()
@@ -67,7 +67,7 @@ GLOBAL_LIST_EMPTY(limb_icon_cache)
var/should_have_eyes = owner.should_have_organ(O_EYES)
var/has_eye_color = owner.species.species_appearance_flags & HAS_EYE_COLOR
if((should_have_eyes || has_eye_color) && eye_icon)
- var/obj/item/organ/internal/eyes/eyes = owner.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/eyes = owner.keyed_organs[ORGAN_KEY_EYES]
var/icon/eyes_icon = new/icon(eye_icon_location, eye_icon)
//Should have eyes
if(should_have_eyes)
diff --git a/code/modules/organs/external/species/naramadi.dm b/code/modules/organs/external/species/naramadi.dm
new file mode 100644
index 000000000000..fcdc86a7f190
--- /dev/null
+++ b/code/modules/organs/external/species/naramadi.dm
@@ -0,0 +1,2 @@
+/obj/item/organ/external/head/vr/sergal
+ eye_icon_vr = "eyes_sergal"
diff --git a/code/modules/organs/external/species/shadekin.dm b/code/modules/organs/external/species/shadekin.dm
index d4fe19dfdcd4..cbbdad2132d7 100644
--- a/code/modules/organs/external/species/shadekin.dm
+++ b/code/modules/organs/external/species/shadekin.dm
@@ -1,37 +1,7 @@
-//! Blackeyed limbs.
-
-/obj/item/organ/external/chest/crewkin
- min_broken_damage = 31 // Original 20, raised to 31 to be at 0.9 of default
-
-/obj/item/organ/external/groin/crewkin
- min_broken_damage = 31 // Original 20, raised to 31 to be at 0.9 of default
+/obj/item/organ/external/head/vr/shadekin
+ eye_icons_vr = 'icons/mob/human_face_vr.dmi'
+ eye_icon_vr = "eyes_shadekin"
/obj/item/organ/external/head/vr/crewkin
- min_broken_damage = 31 // Original 15, raised to 31 to be at 0.9 of default
-
eye_icons_vr = 'icons/mob/human_face_vr.dmi'
eye_icon_vr = "eyes_shadekin_station"
-
-/obj/item/organ/external/arm/crewkin
- min_broken_damage = 27 // Original 15, raised to 27 to be at 0.9 of default
-
-/obj/item/organ/external/arm/right/crewkin
- min_broken_damage = 27 // Original 15, raised to 27 to be at 0.9 of default
-
-/obj/item/organ/external/leg/crewkin
- min_broken_damage = 27 // Original 15, raised to 27 to be at 0.9 of default
-
-/obj/item/organ/external/leg/right/crewkin
- min_broken_damage = 27 // Original 15, raised to 27 to be at 0.9 of default
-
-/obj/item/organ/external/foot/crewkin
- min_broken_damage = 13 // Original 7, raised to 13 to be at 0.9 of default
-
-/obj/item/organ/external/foot/right/crewkin
- min_broken_damage = 13 // Original 7, raised to 13 to be at 0.9 of default
-
-/obj/item/organ/external/hand/crewkin
- min_broken_damage = 13 // Original 7, raised to 13 to be at 0.9 of default
-
-/obj/item/organ/external/hand/right/crewkin
- min_broken_damage = 13 // Original 7, raised to 13 to be at 0.9 of default
diff --git a/code/modules/organs/external/species/teshari.dm b/code/modules/organs/external/species/teshari.dm
index 286d418a08a7..b818a38d0b17 100644
--- a/code/modules/organs/external/species/teshari.dm
+++ b/code/modules/organs/external/species/teshari.dm
@@ -2,13 +2,13 @@
eye_icon = "eyes"
eye_icon_location = 'icons/mob/species/teshari/eyes.dmi'
-/obj/item/organ/external/foot/teshari
+/obj/item/organ/external/foot/left/teshari
body_hair = "feathers"
/obj/item/organ/external/foot/right/teshari
body_hair = "feathers"
-/obj/item/organ/external/hand/teshari
+/obj/item/organ/external/hand/left/teshari
body_hair = "feathers"
/obj/item/organ/external/hand/right/teshari
diff --git a/code/modules/organs/external/species/werebeast.dm b/code/modules/organs/external/species/werebeast.dm
new file mode 100644
index 000000000000..727ecad93fa2
--- /dev/null
+++ b/code/modules/organs/external/species/werebeast.dm
@@ -0,0 +1,4 @@
+/obj/item/organ/external/head/vr/werebeast
+ eye_icons_vr = 'icons/mob/werebeast_face_vr.dmi'
+ eye_icon_vr = "werebeast_eyes"
+ head_offset = 6
diff --git a/code/modules/organs/external/subtypes/standard-arm.dm b/code/modules/organs/external/subtypes/standard-arm.dm
new file mode 100644
index 000000000000..44639a28c1b7
--- /dev/null
+++ b/code/modules/organs/external/subtypes/standard-arm.dm
@@ -0,0 +1,41 @@
+/obj/item/organ/external/arm
+ organ_tag = BP_L_ARM
+ name = "left arm"
+ icon_name = "l_arm"
+ max_damage = 80
+ min_broken_damage = 30
+ w_class = WEIGHT_CLASS_NORMAL
+ body_part_flags = ARM_LEFT
+ parent_organ = BP_TORSO
+ joint = "left elbow"
+ amputation_point = "left shoulder"
+ can_grasp = TRUE
+ damage_force = 7
+ throw_force = 10
+
+/obj/item/organ/external/arm/handle_germ_effects()
+ . = ..() //Should return an infection level
+ if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
+
+ //Staph infection symptoms for ARM
+ if (. >= 1)
+ if(prob(.))
+ owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
+
+ if (. >= 2)
+ if(prob(.))
+ owner.custom_pain("A jolt of pain surges through your [name]!",1)
+ if(organ_tag == BP_L_ARM) //Specific level 2 'feature
+ owner.drop_held_index(1)
+ else if(organ_tag == BP_R_ARM)
+ owner.drop_held_index(2)
+
+/obj/item/organ/external/arm/left
+
+/obj/item/organ/external/arm/right
+ organ_tag = BP_R_ARM
+ name = "right arm"
+ icon_name = "r_arm"
+ body_part_flags = ARM_RIGHT
+ joint = "right elbow"
+ amputation_point = "right shoulder"
diff --git a/code/modules/organs/external/subtypes/standard-chest.dm b/code/modules/organs/external/subtypes/standard-chest.dm
new file mode 100644
index 000000000000..fcd345539c5b
--- /dev/null
+++ b/code/modules/organs/external/subtypes/standard-chest.dm
@@ -0,0 +1,41 @@
+/obj/item/organ/external/chest
+ name = "upper body"
+ organ_tag = BP_TORSO
+ icon_name = "torso"
+ max_damage = 100
+ min_broken_damage = 35
+ w_class = WEIGHT_CLASS_HUGE
+ body_part_flags = UPPER_TORSO
+ vital = TRUE
+ amputation_point = "spine"
+ joint = "neck"
+ dislocated = -1
+ gendered_icon = TRUE
+ cannot_amputate = TRUE
+ parent_organ = null
+ encased = "ribcage"
+ organ_rel_size = 70
+ base_miss_chance = 10
+
+/obj/item/organ/external/chest/robotize()
+ if(..() && robotic != ORGAN_NANOFORM)
+ // Give them fancy new organs.
+ owner.internal_organs_by_name[O_CELL] = new /obj/item/organ/internal/cell(owner,1)
+ owner.internal_organs_by_name[O_VOICE] = new /obj/item/organ/internal/voicebox/robot(owner, 1)
+ owner.internal_organs_by_name[O_PUMP] = new /obj/item/organ/internal/heart/machine(owner,1)
+ owner.internal_organs_by_name[O_CYCLER] = new /obj/item/organ/internal/stomach/machine(owner,1)
+ owner.internal_organs_by_name[O_HEATSINK] = new /obj/item/organ/internal/robotic/heatsink(owner,1)
+ owner.internal_organs_by_name[O_DIAGNOSTIC] = new /obj/item/organ/internal/robotic/diagnostic(owner,1)
+
+/obj/item/organ/external/chest/handle_germ_effects()
+ . = ..() //Should return an infection level
+ if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
+
+ //Staph infection symptoms for CHEST
+ if (. >= 1)
+ if(prob(.))
+ owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
+
+ if (. >= 2)
+ if(prob(.))
+ owner.custom_pain("A jolt of pain surges through your [name]!",1)
diff --git a/code/modules/organs/external/subtypes/standard-foot.dm b/code/modules/organs/external/subtypes/standard-foot.dm
new file mode 100644
index 000000000000..2cd853a2bec4
--- /dev/null
+++ b/code/modules/organs/external/subtypes/standard-foot.dm
@@ -0,0 +1,41 @@
+/obj/item/organ/external/foot
+ organ_tag = BP_L_FOOT
+ name = "left foot"
+ icon_name = "l_foot"
+ max_damage = 50
+ min_broken_damage = 15
+ w_class = WEIGHT_CLASS_SMALL
+ body_part_flags = FOOT_LEFT
+ icon_position = LEFT
+ parent_organ = BP_L_LEG
+ joint = "left ankle"
+ amputation_point = "left ankle"
+ can_stand = TRUE
+ damage_force = 3
+ throw_force = 6
+
+/obj/item/organ/external/foot/handle_germ_effects()
+ . = ..() //Should return an infection level
+ if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
+
+ //Staph infection symptoms for FOOT
+ if (. >= 1)
+ if(prob(.))
+ owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
+
+ if (. >= 2)
+ if(prob(.))
+ owner.custom_pain("A jolt of pain surges through your [name]!",1)
+ owner.afflict_paralyze(20 * 5)
+
+/obj/item/organ/external/foot/left
+
+/obj/item/organ/external/foot/right
+ organ_tag = BP_R_FOOT
+ name = "right foot"
+ icon_name = "r_foot"
+ body_part_flags = FOOT_RIGHT
+ icon_position = RIGHT
+ parent_organ = BP_R_LEG
+ joint = "right ankle"
+ amputation_point = "right ankle"
diff --git a/code/modules/organs/external/subtypes/standard-groin.dm b/code/modules/organs/external/subtypes/standard-groin.dm
new file mode 100644
index 000000000000..1215bcf344cd
--- /dev/null
+++ b/code/modules/organs/external/subtypes/standard-groin.dm
@@ -0,0 +1,29 @@
+/obj/item/organ/external/groin
+ name = "lower body"
+ organ_tag = BP_GROIN
+ icon_name = "groin"
+ max_damage = 100
+ min_broken_damage = 35
+ w_class = WEIGHT_CLASS_BULKY
+ body_part_flags = LOWER_TORSO
+ vital = TRUE
+ parent_organ = BP_TORSO
+ amputation_point = "lumbar"
+ joint = "hip"
+ dislocated = -1
+ gendered_icon = TRUE
+ cannot_amputate = TRUE
+ organ_rel_size = 30
+
+/obj/item/organ/external/groin/handle_germ_effects()
+ . = ..() //Should return an infection level
+ if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
+
+ //Staph infection symptoms for GROIN
+ if (. >= 1)
+ if(prob(.))
+ owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
+
+ if (. >= 2)
+ if(prob(.))
+ owner.custom_pain("A jolt of pain surges through your [name]!",1)
diff --git a/code/modules/organs/external/subtypes/standard-hand.dm b/code/modules/organs/external/subtypes/standard-hand.dm
new file mode 100644
index 000000000000..e8aa7b168274
--- /dev/null
+++ b/code/modules/organs/external/subtypes/standard-hand.dm
@@ -0,0 +1,52 @@
+/obj/item/organ/external/hand
+ organ_tag = BP_L_HAND
+ name = "left hand"
+ icon_name = "l_hand"
+ max_damage = 50
+ min_broken_damage = 15
+ w_class = WEIGHT_CLASS_SMALL
+ body_part_flags = HAND_LEFT
+ parent_organ = BP_L_ARM
+ joint = "left wrist"
+ amputation_point = "left wrist"
+ can_grasp = TRUE
+ organ_rel_size = 10
+ base_miss_chance = 50
+ damage_force = 3
+ throw_force = 5
+
+/obj/item/organ/external/hand/handle_germ_effects()
+ . = ..() //Should return an infection level
+ if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
+
+ //Staph infection symptoms for HAND
+ if (. >= 1)
+ if(prob(.))
+ owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
+
+ if (. >= 2)
+ if(prob(.))
+ owner.custom_pain("A jolt of pain surges through your [name]!",1)
+ if(organ_tag == BP_L_HAND) //Specific level 2 'feature
+ // sequentially drop the first left-held-item
+ for(var/i in 1 to length(owner.inventory?.held_items) step 2)
+ if(isnull(owner.inventory.held_items[i]))
+ continue
+ owner.drop_held_index(i)
+ else if(organ_tag == BP_R_HAND)
+ // sequentially drop the first left-right-item
+ for(var/i in 2 to length(owner.inventory?.held_items) step 2)
+ if(isnull(owner.inventory.held_items[i]))
+ continue
+ owner.drop_held_index(i)
+
+/obj/item/organ/external/hand/left
+
+/obj/item/organ/external/hand/right
+ organ_tag = BP_R_HAND
+ name = "right hand"
+ icon_name = "r_hand"
+ body_part_flags = HAND_RIGHT
+ parent_organ = BP_R_ARM
+ joint = "right wrist"
+ amputation_point = "right wrist"
diff --git a/code/modules/organs/external/subtypes/standard_vr.dm b/code/modules/organs/external/subtypes/standard-head.dm
similarity index 55%
rename from code/modules/organs/external/subtypes/standard_vr.dm
rename to code/modules/organs/external/subtypes/standard-head.dm
index da6c65e433ba..b0611868b8da 100644
--- a/code/modules/organs/external/subtypes/standard_vr.dm
+++ b/code/modules/organs/external/subtypes/standard-head.dm
@@ -1,4 +1,76 @@
-//! ## Leave everything here as it is for now since this is using unique behavior.
+/obj/item/organ/external/head
+ organ_tag = BP_HEAD
+ icon_name = "head"
+ name = "head"
+ slot_flags = SLOT_BELT
+ max_damage = 75
+ min_broken_damage = 35
+ w_class = WEIGHT_CLASS_NORMAL
+ body_part_flags = HEAD
+ vital = TRUE
+ parent_organ = BP_TORSO
+ joint = "jaw"
+ amputation_point = "neck"
+ gendered_icon = TRUE
+ cannot_gib = TRUE
+ encased = "skull"
+ base_miss_chance = 40
+ damage_force = 3
+ throw_force = 7
+
+ var/hair_opacity = 255
+ var/can_intake_reagents = TRUE
+ var/eyes_over_markings = FALSE
+ var/eye_icon = "eyes_s"
+ var/eye_icon_location = 'icons/mob/human_face.dmi'
+
+/obj/item/organ/external/head/Initialize(mapload)
+ if(config_legacy.allow_headgibs)
+ cannot_gib = FALSE
+ return ..()
+
+/obj/item/organ/external/head/robotize(company, skip_prosthetics, keep_organs, force)
+ return ..(company, skip_prosthetics, 1, force)
+
+/obj/item/organ/external/head/removed()
+ if(owner)
+ if(iscarbon(owner))
+ name = "[owner.real_name]'s head"
+ owner.update_hair()
+ get_icon()
+ ..()
+
+/obj/item/organ/external/head/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list(), permutation = 0)
+ . = ..()
+ if (!disfigured)
+ if (brute_dam > 40)
+ if (prob(50))
+ disfigure("brute")
+ if (burn_dam > 40)
+ disfigure("burn")
+
+/obj/item/organ/external/head/handle_germ_effects()
+ . = ..() //Should return an infection level
+ if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
+
+ //Staph infection symptoms for HEAD
+ if (. >= 1)
+ if(prob(.))
+ owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
+
+ if (. >= 2)
+ if(prob(.))
+ owner.custom_pain("A jolt of pain surges through your [name]!",1)
+ owner.eye_blurry += 20 //Specific level 2 'feature
+
+/obj/item/organ/external/head/attackby(obj/item/I as obj, mob/user as mob)
+ if(istype(I, /obj/item/toy/plushie) || istype(I, /obj/item/organ/external/head))
+ user.visible_message("[user] makes \the [I] kiss \the [src]!.", \
+ "You make \the [I] kiss \the [src]!.")
+ return ..()
+
+/obj/item/organ/external/head/no_eyes
+ eye_icon = "blank_eyes"
/// For custom heads with custom parts since the base code is restricted to a single icon file.
/obj/item/organ/external/head/vr/get_icon()
@@ -18,7 +90,7 @@
icon_cache_key += "[M][markings[M]["color"]]"
if(owner.should_have_organ(O_EYES))//Moved on top of markings.
- var/obj/item/organ/internal/eyes/eyes = owner.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/eyes = owner.keyed_organs[ORGAN_KEY_EYES]
if(eye_icon)
var/icon/eyes_icon = new/icon(eye_icons_vr, eye_icon_vr)
if(eyes)
@@ -59,18 +131,3 @@
var/eye_icon_vr = "blank_eyes"
var/head_offset = 0
eye_icon = "blank_eyes"
-
-/obj/item/organ/external/head/vr/sergal
- eye_icon_vr = "eyes_sergal"
-
-/obj/item/organ/external/head/vr/werebeast
- eye_icons_vr = 'icons/mob/werebeast_face_vr.dmi'
- eye_icon_vr = "werebeast_eyes"
- head_offset = 6
-
-/obj/item/organ/external/head/vr/shadekin
- cannot_gib = 1
- cannot_amputate = 1
-
- eye_icons_vr = 'icons/mob/human_face_vr.dmi'
- eye_icon_vr = "eyes_shadekin"
diff --git a/code/modules/organs/external/subtypes/standard-leg.dm b/code/modules/organs/external/subtypes/standard-leg.dm
new file mode 100644
index 000000000000..988546d07a48
--- /dev/null
+++ b/code/modules/organs/external/subtypes/standard-leg.dm
@@ -0,0 +1,38 @@
+/obj/item/organ/external/leg
+ organ_tag = BP_L_LEG
+ name = "left leg"
+ icon_name = "l_leg"
+ max_damage = 80
+ min_broken_damage = 30
+ w_class = WEIGHT_CLASS_NORMAL
+ body_part_flags = LEG_LEFT
+ icon_position = LEFT
+ parent_organ = BP_GROIN
+ joint = "left knee"
+ amputation_point = "left hip"
+ can_stand = TRUE
+ damage_force = 10
+ throw_force = 12
+
+/obj/item/organ/external/leg/handle_germ_effects()
+ . = ..() //Should return an infection level
+ if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
+
+ //Staph infection symptoms for LEG
+ if (. >= 1)
+ if(prob(.))
+ owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
+
+ if (. >= 2)
+ if(prob(.))
+ owner.custom_pain("A jolt of pain surges through your [name]!",1)
+ owner.afflict_paralyze(20 * 5)
+
+/obj/item/organ/external/leg/right
+ organ_tag = BP_R_LEG
+ name = "right leg"
+ icon_name = "r_leg"
+ body_part_flags = LEG_RIGHT
+ icon_position = RIGHT
+ joint = "right knee"
+ amputation_point = "right hip"
diff --git a/code/modules/organs/external/subtypes/standard.dm b/code/modules/organs/external/subtypes/standard.dm
deleted file mode 100644
index 6fcd310eb1af..000000000000
--- a/code/modules/organs/external/subtypes/standard.dm
+++ /dev/null
@@ -1,321 +0,0 @@
-/****************************************************
- ORGAN DEFINES
-****************************************************/
-
-//Make sure that w_class is set as if the parent mob was medium sized! This is because w_class is adjusted automatically for mob_size in New()
-
-/obj/item/organ/external/chest
- name = "upper body"
- organ_tag = BP_TORSO
- icon_name = "torso"
- max_damage = 100
- min_broken_damage = 35
- w_class = WEIGHT_CLASS_HUGE
- body_part_flags = UPPER_TORSO
- vital = TRUE
- amputation_point = "spine"
- joint = "neck"
- dislocated = -1
- gendered_icon = TRUE
- cannot_amputate = TRUE
- parent_organ = null
- encased = "ribcage"
- organ_rel_size = 70
- base_miss_chance = 10
-
-/obj/item/organ/external/chest/robotize()
- if(..() && robotic != ORGAN_NANOFORM)
- // Give them fancy new organs.
- owner.internal_organs_by_name[O_CELL] = new /obj/item/organ/internal/cell(owner,1)
- owner.internal_organs_by_name[O_VOICE] = new /obj/item/organ/internal/voicebox/robot(owner, 1)
- owner.internal_organs_by_name[O_PUMP] = new /obj/item/organ/internal/heart/machine(owner,1)
- owner.internal_organs_by_name[O_CYCLER] = new /obj/item/organ/internal/stomach/machine(owner,1)
- owner.internal_organs_by_name[O_HEATSINK] = new /obj/item/organ/internal/robotic/heatsink(owner,1)
- owner.internal_organs_by_name[O_DIAGNOSTIC] = new /obj/item/organ/internal/robotic/diagnostic(owner,1)
-
-/obj/item/organ/external/chest/handle_germ_effects()
- . = ..() //Should return an infection level
- if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
-
- //Staph infection symptoms for CHEST
- if (. >= 1)
- if(prob(.))
- owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
-
- if (. >= 2)
- if(prob(.))
- owner.custom_pain("A jolt of pain surges through your [name]!",1)
-
-/obj/item/organ/external/groin
- name = "lower body"
- organ_tag = BP_GROIN
- icon_name = "groin"
- max_damage = 100
- min_broken_damage = 35
- w_class = WEIGHT_CLASS_BULKY
- body_part_flags = LOWER_TORSO
- vital = TRUE
- parent_organ = BP_TORSO
- amputation_point = "lumbar"
- joint = "hip"
- dislocated = -1
- gendered_icon = TRUE
- cannot_amputate = TRUE
- organ_rel_size = 30
-
-/obj/item/organ/external/groin/handle_germ_effects()
- . = ..() //Should return an infection level
- if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
-
- //Staph infection symptoms for GROIN
- if (. >= 1)
- if(prob(.))
- owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
-
- if (. >= 2)
- if(prob(.))
- owner.custom_pain("A jolt of pain surges through your [name]!",1)
-
-/obj/item/organ/external/arm
- organ_tag = BP_L_ARM
- name = "left arm"
- icon_name = "l_arm"
- max_damage = 80
- min_broken_damage = 30
- w_class = WEIGHT_CLASS_NORMAL
- body_part_flags = ARM_LEFT
- parent_organ = BP_TORSO
- joint = "left elbow"
- amputation_point = "left shoulder"
- can_grasp = TRUE
- damage_force = 7
- throw_force = 10
-
-/obj/item/organ/external/arm/handle_germ_effects()
- . = ..() //Should return an infection level
- if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
-
- //Staph infection symptoms for ARM
- if (. >= 1)
- if(prob(.))
- owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
-
- if (. >= 2)
- if(prob(.))
- owner.custom_pain("A jolt of pain surges through your [name]!",1)
- if(organ_tag == BP_L_ARM) //Specific level 2 'feature
- owner.drop_held_index(1)
- else if(organ_tag == BP_R_ARM)
- owner.drop_held_index(2)
-
-/obj/item/organ/external/arm/right
- organ_tag = BP_R_ARM
- name = "right arm"
- icon_name = "r_arm"
- body_part_flags = ARM_RIGHT
- joint = "right elbow"
- amputation_point = "right shoulder"
-
-/obj/item/organ/external/leg
- organ_tag = BP_L_LEG
- name = "left leg"
- icon_name = "l_leg"
- max_damage = 80
- min_broken_damage = 30
- w_class = WEIGHT_CLASS_NORMAL
- body_part_flags = LEG_LEFT
- icon_position = LEFT
- parent_organ = BP_GROIN
- joint = "left knee"
- amputation_point = "left hip"
- can_stand = TRUE
- damage_force = 10
- throw_force = 12
-
-/obj/item/organ/external/leg/handle_germ_effects()
- . = ..() //Should return an infection level
- if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
-
- //Staph infection symptoms for LEG
- if (. >= 1)
- if(prob(.))
- owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
-
- if (. >= 2)
- if(prob(.))
- owner.custom_pain("A jolt of pain surges through your [name]!",1)
- owner.afflict_paralyze(20 * 5)
-
-/obj/item/organ/external/leg/right
- organ_tag = BP_R_LEG
- name = "right leg"
- icon_name = "r_leg"
- body_part_flags = LEG_RIGHT
- icon_position = RIGHT
- joint = "right knee"
- amputation_point = "right hip"
-
-/obj/item/organ/external/foot
- organ_tag = BP_L_FOOT
- name = "left foot"
- icon_name = "l_foot"
- max_damage = 50
- min_broken_damage = 15
- w_class = WEIGHT_CLASS_SMALL
- body_part_flags = FOOT_LEFT
- icon_position = LEFT
- parent_organ = BP_L_LEG
- joint = "left ankle"
- amputation_point = "left ankle"
- can_stand = TRUE
- damage_force = 3
- throw_force = 6
-
-/obj/item/organ/external/foot/handle_germ_effects()
- . = ..() //Should return an infection level
- if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
-
- //Staph infection symptoms for FOOT
- if (. >= 1)
- if(prob(.))
- owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
-
- if (. >= 2)
- if(prob(.))
- owner.custom_pain("A jolt of pain surges through your [name]!",1)
- owner.afflict_paralyze(20 * 5)
-
-/obj/item/organ/external/foot/right
- organ_tag = BP_R_FOOT
- name = "right foot"
- icon_name = "r_foot"
- body_part_flags = FOOT_RIGHT
- icon_position = RIGHT
- parent_organ = BP_R_LEG
- joint = "right ankle"
- amputation_point = "right ankle"
-
-/obj/item/organ/external/hand
- organ_tag = BP_L_HAND
- name = "left hand"
- icon_name = "l_hand"
- max_damage = 50
- min_broken_damage = 15
- w_class = WEIGHT_CLASS_SMALL
- body_part_flags = HAND_LEFT
- parent_organ = BP_L_ARM
- joint = "left wrist"
- amputation_point = "left wrist"
- can_grasp = TRUE
- organ_rel_size = 10
- base_miss_chance = 50
- damage_force = 3
- throw_force = 5
-
-/obj/item/organ/external/hand/handle_germ_effects()
- . = ..() //Should return an infection level
- if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
-
- //Staph infection symptoms for HAND
- if (. >= 1)
- if(prob(.))
- owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
-
- if (. >= 2)
- if(prob(.))
- owner.custom_pain("A jolt of pain surges through your [name]!",1)
- if(organ_tag == BP_L_HAND) //Specific level 2 'feature
- // sequentially drop the first left-held-item
- for(var/i in 1 to length(owner.inventory?.held_items) step 2)
- if(isnull(owner.inventory.held_items[i]))
- continue
- owner.drop_held_index(i)
- else if(organ_tag == BP_R_HAND)
- // sequentially drop the first left-right-item
- for(var/i in 2 to length(owner.inventory?.held_items) step 2)
- if(isnull(owner.inventory.held_items[i]))
- continue
- owner.drop_held_index(i)
-
-/obj/item/organ/external/hand/right
- organ_tag = BP_R_HAND
- name = "right hand"
- icon_name = "r_hand"
- body_part_flags = HAND_RIGHT
- parent_organ = BP_R_ARM
- joint = "right wrist"
- amputation_point = "right wrist"
-
-/obj/item/organ/external/head
- organ_tag = BP_HEAD
- icon_name = "head"
- name = "head"
- slot_flags = SLOT_BELT
- max_damage = 75
- min_broken_damage = 35
- w_class = WEIGHT_CLASS_NORMAL
- body_part_flags = HEAD
- vital = TRUE
- parent_organ = BP_TORSO
- joint = "jaw"
- amputation_point = "neck"
- gendered_icon = TRUE
- cannot_gib = TRUE
- encased = "skull"
- base_miss_chance = 40
- damage_force = 3
- throw_force = 7
-
- var/hair_opacity = 255
- var/can_intake_reagents = TRUE
- var/eyes_over_markings = FALSE
- var/eye_icon = "eyes_s"
- var/eye_icon_location = 'icons/mob/human_face.dmi'
-
-/obj/item/organ/external/head/Initialize(mapload)
- if(config_legacy.allow_headgibs)
- cannot_gib = FALSE
- return ..()
-
-/obj/item/organ/external/head/robotize(company, skip_prosthetics, keep_organs, force)
- return ..(company, skip_prosthetics, 1, force)
-
-/obj/item/organ/external/head/removed()
- if(owner)
- if(iscarbon(owner))
- name = "[owner.real_name]'s head"
- owner.update_hair()
- get_icon()
- ..()
-
-/obj/item/organ/external/head/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list(), permutation = 0)
- . = ..()
- if (!disfigured)
- if (brute_dam > 40)
- if (prob(50))
- disfigure("brute")
- if (burn_dam > 40)
- disfigure("burn")
-
-/obj/item/organ/external/head/handle_germ_effects()
- . = ..() //Should return an infection level
- if(!. || (status & ORGAN_DEAD)) return //If it's already above 2, it's become necrotic and we can just not worry about it.
-
- //Staph infection symptoms for HEAD
- if (. >= 1)
- if(prob(.))
- owner.custom_pain("Your [name] [pick("aches","itches","throbs")]!",0)
-
- if (. >= 2)
- if(prob(.))
- owner.custom_pain("A jolt of pain surges through your [name]!",1)
- owner.eye_blurry += 20 //Specific level 2 'feature
-
-/obj/item/organ/external/head/attackby(obj/item/I as obj, mob/user as mob)
- if(istype(I, /obj/item/toy/plushie) || istype(I, /obj/item/organ/external/head))
- user.visible_message("[user] makes \the [I] kiss \the [src]!.", \
- "You make \the [I] kiss \the [src]!.")
- return ..()
-
-/obj/item/organ/external/head/no_eyes
- eye_icon = "blank_eyes"
diff --git a/code/modules/organs/external/wound.dm b/code/modules/organs/external/wound.dm
index a56c1f153e98..e746559446bf 100644
--- a/code/modules/organs/external/wound.dm
+++ b/code/modules/organs/external/wound.dm
@@ -1,148 +1,3 @@
-/**
- * Creates a wound on this organ.
- *
- * todo: better documentation
- */
-/obj/item/organ/external/proc/create_wound(var/type = WOUND_TYPE_CUT, var/damage)
- if(damage == 0)
- return
-
- //moved this before the open_wound check so that having many small wounds for example doesn't somehow protect you from taking internal damage (because of the return)
- //Possibly trigger an internal wound, too.
- var/local_damage = brute_dam + burn_dam + damage
- if((damage > 15) && (type != WOUND_TYPE_BURN) && (local_damage > 30) && prob(damage) && (robotic < ORGAN_ROBOT) && !(species.species_flags & NO_BLOOD))
- create_specific_wound(/datum/wound/internal_bleeding, min(damage - 15, 15))
- owner.custom_pain("You feel something rip in your [name]!", 50)
-
-//Burn damage can cause fluid loss due to blistering and cook-off
-
- if((damage > 5 || damage + burn_dam >= 15) && type == WOUND_TYPE_BURN && (robotic < ORGAN_ROBOT) && !(species.species_flags & NO_BLOOD))
- var/fluid_loss = 0.4 * (damage/(owner.getMaxHealth() - config_legacy.health_threshold_dead)) * owner.species.blood_volume*(1 - owner.species.blood_level_fatal)
- owner.remove_blood(fluid_loss)
-
- // first check whether we can widen an existing wound
- if(length(wounds) > 0 && prob(max(50+(wound_tally-1)*10,90)))
- if((type == WOUND_TYPE_CUT || type == WOUND_TYPE_BRUISE) && damage >= 5)
- //we need to make sure that the wound we are going to worsen is compatible with the type of damage...
- var/list/compatible_wounds = list()
- for (var/datum/wound/W as anything in wounds)
- if (W.can_worsen(type, damage))
- compatible_wounds += W
-
- if(compatible_wounds.len)
- var/datum/wound/W = pick(compatible_wounds)
- W.open_wound(damage)
- if(prob(25))
- if(robotic >= ORGAN_ROBOT)
- owner.visible_message("The damage to [owner.name]'s [name] worsens.",\
- "The damage to your [name] worsens.",\
- "You hear the screech of abused metal.")
- else
- owner.visible_message("The wound on [owner.name]'s [name] widens with a nasty ripping noise.",\
- "The wound on your [name] widens with a nasty ripping noise.",\
- "You hear a nasty ripping noise, as if flesh is being torn apart.")
- return
-
- //Creating wound
- var/wound_type = get_wound_type(type, damage)
-
- if(wound_type)
- var/datum/wound/W = new wound_type(damage)
-
- //Check whether we can add the wound to an existing wound
- for(var/datum/wound/other as anything in wounds)
- if(other.can_merge(W))
- other.merge_wound(W)
- W = null // to signify that the wound was added
- break
- if(W)
- LAZYADD(wounds, W)
-
-/**
- * Creates a specific kind of wound on this organ.
- *
- * This only creates the wound, it does not do damage side effects,
- * like vaporizing blood with burns, etc
- *
- * Such side effects should not be in the procs for making wounds!
- *
- * If you need to modify variables other than "damage", grab the returned wound.
- *
- * @params
- * * path - typepath of /datum/wound to create.
- * * damage - amount of damage it should have.
- * * updating - update damages?
- *
- * @return the /datum/wound created, *or* the /datum/wound merged, *or* null if it was rejected.
- */
-/obj/item/organ/external/proc/create_specific_wound(path, damage, updating = TRUE)
- ASSERT(ispath(path, /datum/wound))
-
- var/datum/wound/creating = new path(damage)
- var/datum/wound/merged
-
- for(var/datum/wound/other as anything in wounds)
- if(other.can_merge(creating))
- other.merge_wound(creating)
- merged = other
- break
-
- if(isnull(merged))
- // didn't merge, add
- LAZYADD(wounds, creating)
- . = creating
- else
- // merged, return merged
- // we don't manually qdel creating - hopefully no one actually does something
- // deranged down the line like making wounds reference externally!
- . = merged
-
- if(updating)
- update_damages()
-
-/**
- * Immediately cures a specific typepath of wound, or a specific instance of wound
- *
- * @params
- * * path - path of wound to cure, all subtypes count!
- * * all - cure all instances, or just one?
- * * updating - update damages?
- *
- * @return TRUE / FALSE based on if anything was removed.
- */
-/obj/item/organ/external/proc/cure_specific_wound(datum/wound/path_or_instance, all = FALSE, updating = TRUE)
- . = FALSE
- // todo: remove the assert / is in check, free performance, only here to prevent accidental misuse for now.
- ASSERT(ispath(path_or_instance, /datum/wound))
- for(var/datum/wound/W in wounds)
- if(istype(W, path_or_instance))
- wounds -= W
- . = TRUE
- if(all)
- break
-
- if(!.)
- return
-
- if(updating)
- update_damages()
-
-/**
- * Immediately cures a wound instance.
- *
- * Use this proc from within loops over the wounds list.
- *
- * Warning: We do not check if the wound exists.s
- *
- * @params
- * * wound - the wound to cure
- * * updating - update damages?
- */
-/obj/item/organ/external/proc/cure_exact_wound(datum/wound/wound, updating = TRUE)
- wounds -= wound
-
- if(updating)
- update_damages()
/**
* Wound datums
diff --git a/code/modules/organs/internal/internal.dm b/code/modules/organs/internal/internal.dm
index 1b520655d824..67f93d44dc94 100644
--- a/code/modules/organs/internal/internal.dm
+++ b/code/modules/organs/internal/internal.dm
@@ -2,20 +2,15 @@
INTERNAL ORGANS DEFINES
****************************************************/
/obj/item/organ/internal
+ abstract_type = /obj/item/organ/internal
/// Icon to use when the organ has died.
var/dead_icon
-// Yep... That's it. - @Zandario
-
/obj/item/organ/internal/Destroy()
if(owner)
- owner.internal_organs.Remove(src)
- owner.internal_organs_by_name[organ_tag] = null
- owner.internal_organs_by_name -= organ_tag
- while(null in owner.internal_organs)
- owner.internal_organs -= null
var/obj/item/organ/external/E = owner.organs_by_name[parent_organ]
- if(istype(E)) E.internal_organs -= src
+ if(istype(E))
+ E.internal_organs -= src
return ..()
/obj/item/organ/internal/on_die()
@@ -28,17 +23,6 @@
if(dead_icon)
icon_state = initial(icon_state)
-/obj/item/organ/internal/remove_rejuv()
- if(owner)
- owner.internal_organs -= src
- owner.internal_organs_by_name[organ_tag] = null
- owner.internal_organs_by_name -= organ_tag
- while(null in owner.internal_organs)
- owner.internal_organs -= null
- var/obj/item/organ/external/E = owner.organs_by_name[parent_organ]
- if(istype(E)) E.internal_organs -= src
- ..()
-
/obj/item/organ/internal/robotize()
..()
name = "prosthetic [initial(name)]"
@@ -80,3 +64,22 @@
take_damage(rand(1, 4))
if (4)
take_damage(rand(0, 2))
+
+//* Insert / Remove *//
+
+/obj/item/organ/internal/register(mob/living/carbon/target)
+ target.internal_organs += src
+ if(organ_key)
+ target.keyed_organs[organ_key] = src
+ target.keyed_organs[organ_tag] = src
+ if(organ_tag)
+ target.legacy_organ_by_tag[organ_tag] = src
+
+/obj/item/organ/internal/unregister(mob/living/carbon/target)
+ target.internal_organs -= src
+ if(organ_key && target.keyed_organs[organ_key] == src)
+ target.keyed_organs -= organ_key
+ if(organ_key && target.legacy_organ_by_tag[organ_key] == src)
+ target.legacy_organ_by_tag -= organ_key
+ if(organ_tag && target.legacy_organ_by_tag[organ_tag] == src)
+ target.legacy_organ_by_tag -= organ_tag
diff --git a/code/modules/organs/internal/robotic/heatsink.dm b/code/modules/organs/internal/robotic/heatsink.dm
index 163fb6ed8748..c5c63da5702d 100644
--- a/code/modules/organs/internal/robotic/heatsink.dm
+++ b/code/modules/organs/internal/robotic/heatsink.dm
@@ -31,8 +31,6 @@
owner.adjustToxLoss(2 * damage / max_damage)
take_damage(max(0.5,round(damage / max_damage, 0.1)))
- return
-
/obj/item/organ/internal/robotic/heatsink/proc/get_environment_temperature()
if(istype(owner.loc, /obj/vehicle/sealed/mecha))
var/obj/vehicle/sealed/mecha/M = owner.loc
diff --git a/code/modules/organs/internal/species/adherent.dm b/code/modules/organs/internal/species/adherent.dm
index 3d2ee4e227a0..5a41b14f66ce 100644
--- a/code/modules/organs/internal/species/adherent.dm
+++ b/code/modules/organs/internal/species/adherent.dm
@@ -27,7 +27,7 @@
owner.adjust_nutrition(-maintenance_cost)
active = FALSE
to_chat(owner, SPAN_DANGER("Your [name] [gender == PLURAL ? "are" : "is"] out of power!"))
- refresh_action_button()
+ update_action_buttons()
/obj/item/organ/internal/powered/update_action_buttons()
if(istype(organ_actions, /datum/action))
@@ -48,8 +48,7 @@
else
active = !active
to_chat(owner, SPAN_NOTICE("You are [active ? "now" : "no longer"] using your [name] to [use_descriptor]."))
- refresh_action_button()
-
+ update_action_buttons()
/obj/item/organ/internal/powered/jets
name = "maneuvering jets"
diff --git a/code/modules/organs/internal/species/alraune.dm b/code/modules/organs/internal/species/alraune.dm
index 3341b4f4caa5..6f1b63ecef18 100644
--- a/code/modules/organs/internal/species/alraune.dm
+++ b/code/modules/organs/internal/species/alraune.dm
@@ -49,7 +49,7 @@
/obj/item/organ/internal/fruitgland/tick_life(dt)
. = ..()
- var/obj/item/organ/external/parent = owner.get_organ(parent_organ)
+ var/obj/item/organ/external/parent = owner.legacy_organ_by_zone(parent_organ)
var/before_gen
if(parent && generated_reagents && owner) //Is it in the chest/an organ, has reagents, and is 'activated'
before_gen = reagents.total_volume
diff --git a/code/modules/organs/internal/species/replicant.dm b/code/modules/organs/internal/species/replicant.dm
index 51605ab098d7..0c799a080f7b 100644
--- a/code/modules/organs/internal/species/replicant.dm
+++ b/code/modules/organs/internal/species/replicant.dm
@@ -47,19 +47,19 @@
can_reject = FALSE
icon_state = "kidneys_grey"
-/obj/item/organ/internal/xenos/plasmavessel/replicant
+/obj/item/organ/internal/xenomorph/plasmavessel/replicant
name = "replicant phorogenic sac"
desc = "A bulbous rubbery mass that converts nutrients from the host into a biological compound eerily similar to phoron."
can_reject = FALSE
icon_state = "plasma_grey"
-/obj/item/organ/internal/xenos/acidgland/replicant
+/obj/item/organ/internal/xenomorph/acidgland/replicant
name = "replicant aerosol tubule"
desc = "A long, rubbery tube that ends in a hard plastic-like bulb."
can_reject = FALSE
icon_state = "acidgland_grey"
-/obj/item/organ/internal/xenos/resinspinner/replicant
+/obj/item/organ/internal/xenomorph/resinspinner/replicant
name = "replicant biomesh spinner"
desc = "A rubbery mass with protrusions for molding organic material."
can_reject = FALSE
diff --git a/code/modules/organs/internal/species/shadekin.dm b/code/modules/organs/internal/species/shadekin.dm
deleted file mode 100644
index 0cfe9e48c2ef..000000000000
--- a/code/modules/organs/internal/species/shadekin.dm
+++ /dev/null
@@ -1,52 +0,0 @@
-/obj/item/organ/internal/brain/shadekin
- can_assist = FALSE
-
- var/dark_energy = 100
- var/max_dark_energy = 100
- var/dark_energy_infinite = FALSE
-
- organ_actions = list(
- /datum/action/organ_action/shadekin_storage,
- )
-
-/datum/action/organ_action/shadekin_storage
- name = "Access Storage"
- desc = "Access your dimensional pocket."
-
-/obj/item/organ/internal/brain/shadekin/Initialize(mapload)
- . = ..()
- obj_storage = new /datum/object_system/storage/shadekin(src)
- obj_storage.indirect(src)
-
-/obj/item/organ/internal/brain/shadekin/on_insert(mob/owner, initializing)
- . = ..()
- RegisterSignal(owner, COMSIG_ATOM_REACHABILITY_DIRECTACCESS, PROC_REF(handle_storage_reachability))
-
-/obj/item/organ/internal/brain/shadekin/on_remove(mob/owner)
- . = ..()
- UnregisterSignal(owner, COMSIG_ATOM_REACHABILITY_DIRECTACCESS)
-
-/obj/item/organ/internal/brain/shadekin/proc/handle_storage_reachability(atom/source, list/direct_access)
- var/atom/movable/storage_indirection/indirection = locate() in contents
- if(!indirection)
- return
- direct_access += indirection
-
-/obj/item/organ/internal/brain/shadekin/ui_action_click(datum/action/action, datum/event_args/actor/actor)
- obj_storage.show(actor.performer)
-
-/datum/object_system/storage/shadekin
- max_single_weight_class = WEIGHT_CLASS_SMALL
- max_items = 7
-
-/obj/item/organ/internal/brain/shadekin/crewkin
- dark_energy = 50
- max_dark_energy = 50
-
-/obj/item/organ/internal/brain/shadekin/crewkin/damaged
- dark_energy = 25
- max_dark_energy = 25
-
-/obj/item/organ/internal/brain/shadekin/crewkin/heavilydamaged
- dark_energy = 0
- max_dark_energy = 0
diff --git a/code/modules/organs/internal/species/xenos.dm b/code/modules/organs/internal/species/xenos.dm
index 3739c4301780..3f146b5da55b 100644
--- a/code/modules/organs/internal/species/xenos.dm
+++ b/code/modules/organs/internal/species/xenos.dm
@@ -1,32 +1,34 @@
//XENOMORPH ORGANS
-/obj/item/organ/internal/xenos
+/obj/item/organ/internal/xenomorph
+ abstract_type = /obj/item/organ/internal/xenomorph
name = "xeno organ"
icon = 'icons/obj/surgery.dmi'
desc = "It smells like an accident in a chemical factory."
-/obj/item/organ/internal/xenos/eggsac
+/obj/item/organ/internal/xenomorph/eggsac
name = "egg sac"
parent_organ = BP_GROIN
icon_state = "sac"
organ_tag = O_EGG
-/obj/item/organ/internal/xenos/eggsac/grey
+/obj/item/organ/internal/xenomorph/eggsac/grey
icon_state = "sac_grey"
-/obj/item/organ/internal/xenos/eggsac/grey/colormatch/Initialize(mapload)
+/obj/item/organ/internal/xenomorph/eggsac/grey/colormatch/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(sync_color)), 15)
-/obj/item/organ/internal/xenos/eggsac/grey/colormatch/proc/sync_color()
+/obj/item/organ/internal/xenomorph/eggsac/grey/colormatch/proc/sync_color()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.species.blood_color)
add_atom_colour(H.species.blood_color, FIXED_COLOUR_PRIORITY)
-/obj/item/organ/internal/xenos/plasmavessel
+/obj/item/organ/internal/xenomorph/plasmavessel
name = "plasma vessel"
parent_organ = BP_TORSO
icon_state = "plasma"
+ organ_key = ORGAN_KEY_XENOMORPH_PLASMA_VESSEL
organ_tag = O_PLASMA
var/stored_plasma = 0
var/max_plasma = 500
@@ -35,7 +37,7 @@
/mob/living/carbon/human/proc/transfer_plasma
)
-/obj/item/organ/internal/xenos/plasmavessel/handle_organ_proc_special()
+/obj/item/organ/internal/xenomorph/plasmavessel/handle_organ_proc_special()
if(!istype(owner))
return
@@ -49,38 +51,38 @@
adjust_plasma(1)
-/obj/item/organ/internal/xenos/plasmavessel/proc/adjust_plasma(var/amount = 0)
+/obj/item/organ/internal/xenomorph/plasmavessel/proc/adjust_plasma(var/amount = 0)
stored_plasma = clamp(stored_plasma + amount, 0, max_plasma)
-/obj/item/organ/internal/xenos/plasmavessel/grey
+/obj/item/organ/internal/xenomorph/plasmavessel/grey
icon_state = "plasma_grey"
stored_plasma = 200
-/obj/item/organ/internal/xenos/plasmavessel/grey/colormatch/Initialize(mapload)
+/obj/item/organ/internal/xenomorph/plasmavessel/grey/colormatch/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(sync_color)), 15)
-/obj/item/organ/internal/xenos/plasmavessel/grey/colormatch/proc/sync_color()
+/obj/item/organ/internal/xenomorph/plasmavessel/grey/colormatch/proc/sync_color()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.species.blood_color)
add_atom_colour(H.species.blood_color, FIXED_COLOUR_PRIORITY)
-/obj/item/organ/internal/xenos/plasmavessel/queen
+/obj/item/organ/internal/xenomorph/plasmavessel/queen
name = "bloated plasma vessel"
stored_plasma = 200
max_plasma = 500
-/obj/item/organ/internal/xenos/plasmavessel/sentinel
+/obj/item/organ/internal/xenomorph/plasmavessel/sentinel
stored_plasma = 100
max_plasma = 250
-/obj/item/organ/internal/xenos/plasmavessel/hunter
+/obj/item/organ/internal/xenomorph/plasmavessel/hunter
name = "tiny plasma vessel"
stored_plasma = 100
max_plasma = 150
-/obj/item/organ/internal/xenos/acidgland
+/obj/item/organ/internal/xenomorph/acidgland
name = "acid gland"
parent_organ = BP_HEAD
icon_state = "acidgland"
@@ -92,39 +94,39 @@
/mob/living/carbon/human/proc/acidspit
)
-/obj/item/organ/internal/xenos/acidgland/grey
+/obj/item/organ/internal/xenomorph/acidgland/grey
icon_state = "acidgland_grey"
-/obj/item/organ/internal/xenos/acidgland/grey/colormatch/Initialize(mapload)
+/obj/item/organ/internal/xenomorph/acidgland/grey/colormatch/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(sync_color)), 15)
-/obj/item/organ/internal/xenos/acidgland/grey/colormatch/proc/sync_color()
+/obj/item/organ/internal/xenomorph/acidgland/grey/colormatch/proc/sync_color()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.species.blood_color)
add_atom_colour(H.species.blood_color, FIXED_COLOUR_PRIORITY)
-/obj/item/organ/internal/xenos/hivenode
+/obj/item/organ/internal/xenomorph/hivenode
name = "hive node"
parent_organ = BP_TORSO
icon_state = "xenode"
organ_tag = O_HIVE
-/obj/item/organ/internal/xenos/hivenode/grey
+/obj/item/organ/internal/xenomorph/hivenode/grey
icon_state = "xenode_grey"
-/obj/item/organ/internal/xenos/hivenode/grey/colormatch/Initialize(mapload)
+/obj/item/organ/internal/xenomorph/hivenode/grey/colormatch/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(sync_color)), 15)
-/obj/item/organ/internal/xenos/hivenode/grey/colormatch/proc/sync_color()
+/obj/item/organ/internal/xenomorph/hivenode/grey/colormatch/proc/sync_color()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.species.blood_color)
add_atom_colour(H.species.blood_color, FIXED_COLOUR_PRIORITY)
-/obj/item/organ/internal/xenos/resinspinner
+/obj/item/organ/internal/xenomorph/resinspinner
name = "resin spinner"
parent_organ = BP_HEAD
icon_state = "xenode"
@@ -135,21 +137,21 @@
/mob/living/carbon/human/proc/plant
)
-/obj/item/organ/internal/xenos/resinspinner/hybrid
+/obj/item/organ/internal/xenomorph/resinspinner/hybrid
name = "weakend resinspinner"
organ_verbs = list(
/mob/living/carbon/human/proc/hybrid_resin,
/mob/living/carbon/human/proc/hybrid_plant//replaced from the normal weed node to place a singular weed
)
-/obj/item/organ/internal/xenos/resinspinner/grey
+/obj/item/organ/internal/xenomorph/resinspinner/grey
icon_state = "xenode_grey"
-/obj/item/organ/internal/xenos/resinspinner/grey/colormatch/Initialize(mapload)
+/obj/item/organ/internal/xenomorph/resinspinner/grey/colormatch/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(sync_color)), 15)
-/obj/item/organ/internal/xenos/resinspinner/grey/colormatch/proc/sync_color()
+/obj/item/organ/internal/xenomorph/resinspinner/grey/colormatch/proc/sync_color()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.species.blood_color)
diff --git a/code/modules/organs/internal/subtypes/appendix.dm b/code/modules/organs/internal/subtypes/appendix.dm
index 327320f38ea9..95104e3697ad 100644
--- a/code/modules/organs/internal/subtypes/appendix.dm
+++ b/code/modules/organs/internal/subtypes/appendix.dm
@@ -43,7 +43,7 @@
to_chat(owner, "Your abdomen is a world of pain!")
owner.afflict_paralyze(20 * 10)
- var/obj/item/organ/external/groin = owner.get_organ(BP_GROIN)
+ var/obj/item/organ/external/groin = owner.legacy_organ_by_zone(BP_GROIN)
groin.create_specific_wound(/datum/wound/internal_bleeding, 20)
owner.adjustToxLoss(25)
inflamed = 1
diff --git a/code/modules/organs/internal/subtypes/augment.dm b/code/modules/organs/internal/subtypes/augment.dm
index 8dc71901e8c8..ce4b986f7e6c 100644
--- a/code/modules/organs/internal/subtypes/augment.dm
+++ b/code/modules/organs/internal/subtypes/augment.dm
@@ -177,7 +177,7 @@
var/list/present_augs = list()
- for(var/obj/item/organ/internal/augment/Aug in organs)
+ for(var/obj/item/organ/internal/augment/Aug in internal_organs)
if(Aug.my_radial_icon && !Aug.is_broken() && Aug.check_verb_compatability())
present_augs[Aug.radial_name] = Aug
diff --git a/code/modules/organs/internal/subtypes/brain.dm b/code/modules/organs/internal/subtypes/brain.dm
index a5bccaad54c0..1723bc97b5f1 100644
--- a/code/modules/organs/internal/subtypes/brain.dm
+++ b/code/modules/organs/internal/subtypes/brain.dm
@@ -2,6 +2,7 @@
name = "brain"
desc = "A piece of juicy meat found in a person's head."
organ_tag = "brain"
+ organ_key = ORGAN_KEY_BRAIN
parent_organ = BP_HEAD
vital = 1
decay_rate = ORGAN_DECAY_PER_SECOND_BRAIN
@@ -63,7 +64,9 @@
owner.custom_pain("Your feel very dizzy for a moment!",0)
owner.Confuse(2)
+// todo: this is silly.
/obj/item/organ/internal/brain/proc/replace_self_with(replace_path)
+ ASSERT(ispath(replace_path, /obj/item/organ/internal/brain))
var/mob/living/carbon/human/tmp_owner = owner
qdel(src)
if(tmp_owner)
@@ -257,7 +260,7 @@
H.adjustFireLoss(40)
H.afflict_unconscious(20 * 4)
H.update_health()
- for(var/obj/item/organ/external/E in H.organs) //They've still gotta congeal, but it's faster than the clone sickness they'd normally get.
+ for(var/obj/item/organ/external/E as anything in H.external_organs) //They've still gotta congeal, but it's faster than the clone sickness they'd normally get.
if(E && E.organ_tag == BP_L_ARM || E.organ_tag == BP_R_ARM || E.organ_tag == BP_L_LEG || E.organ_tag == BP_R_LEG)
E.removed()
qdel(E)
diff --git a/code/modules/organs/internal/subtypes/eyes.dm b/code/modules/organs/internal/subtypes/eyes.dm
index 90135cb98364..5b46096d9da1 100644
--- a/code/modules/organs/internal/subtypes/eyes.dm
+++ b/code/modules/organs/internal/subtypes/eyes.dm
@@ -3,6 +3,7 @@
name = "eyeballs"
icon_state = "eyes"
gender = PLURAL
+ organ_key = ORGAN_KEY_EYES
organ_tag = O_EYES
parent_organ = BP_HEAD
var/list/eye_colour = list(0,0,0)
diff --git a/code/modules/organs/internal/subtypes/heart.dm b/code/modules/organs/internal/subtypes/heart.dm
index 7607c6a1fb92..4a5606306902 100644
--- a/code/modules/organs/internal/subtypes/heart.dm
+++ b/code/modules/organs/internal/subtypes/heart.dm
@@ -47,13 +47,6 @@
standard_pulse_level = PULSE_NONE
-/obj/item/organ/internal/stomach/machine/handle_organ_proc_special()
- ..()
- if(owner && owner.stat != DEAD)
- owner.bodytemperature += round(owner.robobody_count * 0.25, 0.1)
-
- return
-
/obj/item/organ/internal/heart/proc/heart_attack() //Do 10 damage the first time and 5 damage subsequent times.
var/obj/item/organ/external/parent = owner.get_organ(parent_organ)
if(istype(parent))
diff --git a/code/modules/organs/internal/subtypes/lungs.dm b/code/modules/organs/internal/subtypes/lungs.dm
index 4ec5890f29d8..dcc5bf6c5fd1 100644
--- a/code/modules/organs/internal/subtypes/lungs.dm
+++ b/code/modules/organs/internal/subtypes/lungs.dm
@@ -32,7 +32,7 @@
owner.AdjustLosebreath(round(3 / max(0.1,Brain.get_control_efficiency())))
/obj/item/organ/internal/lungs/proc/rupture()
- var/obj/item/organ/external/parent = owner.get_organ(parent_organ)
+ var/obj/item/organ/external/parent = owner.legacy_organ_by_zone(parent_organ)
if(istype(parent))
owner.custom_pain("You feel a stabbing pain in your [parent.name]!", 50)
bruise()
diff --git a/code/modules/organs/internal/subtypes/spleen.dm b/code/modules/organs/internal/subtypes/spleen.dm
index 1dafb9477ead..7b50e8b16c5a 100644
--- a/code/modules/organs/internal/subtypes/spleen.dm
+++ b/code/modules/organs/internal/subtypes/spleen.dm
@@ -15,21 +15,15 @@
//High toxins levels are dangerous
if(owner.getToxLoss() >= 30 && !owner.reagents.has_reagent("anti_toxin"))
- //Healthy liver suffers on its own
if (src.damage < min_broken_damage)
src.damage += 0.2 * spleen_tick
- //Damaged one shares the fun
- else
- var/obj/item/organ/internal/O = pick(owner.internal_organs)
- if(O)
- O.damage += 0.2 * spleen_tick
else if(!src.is_broken()) // If the spleen isn't severely damaged, it can help fight infections. Key word, can.
- var/obj/item/organ/external/OEx = pick(owner.organs)
+ var/obj/item/organ/external/OEx = pick(owner.external_organs)
OEx.adjust_germ_level(round(rand(0 * spleen_efficiency,-10 * spleen_efficiency)))
- if(!src.is_bruised() && owner.internal_organs_by_name[O_BRAIN]) // If it isn't bruised, it helps with brain infections.
- var/obj/item/organ/internal/brain/B = owner.internal_organs_by_name[O_BRAIN]
+ if(!src.is_bruised() && owner.keyed_organs[ORGAN_KEY_BRAIN]) // If it isn't bruised, it helps with brain infections.
+ var/obj/item/organ/internal/brain/B = owner.keyed_organs[O_BRAIN]
B.adjust_germ_level(round(rand(-3 * spleen_efficiency, -10 * spleen_efficiency)))
//Detox can heal small amounts of damage
@@ -46,7 +40,7 @@
// Low levels can cause pain and haemophilia, high levels can cause brain infections.
if (. >= 1)
if(prob(1))
- owner.custom_pain("There's a sharp pain in your [owner.get_organ(parent_organ)]!",1)
+ owner.custom_pain("There's a sharp pain in your [owner.legacy_organ_by_zone(parent_organ)]!",1)
owner.add_modifier(/datum/modifier/trait/haemophilia, 2 MINUTES * spleen_efficiency)
if (. >= 2)
if(prob(1))
@@ -59,7 +53,7 @@
/obj/item/organ/internal/spleen/on_die()
. = ..()
owner.add_modifier(/datum/modifier/trait/haemophilia, round(15 MINUTES * spleen_efficiency))
- var/obj/item/organ/external/affecting = owner.get_organ(parent_organ)
+ var/obj/item/organ/external/affecting = owner.legacy_organ_by_zone(parent_organ)
affecting.create_specific_wound(/datum/wound/internal_bleeding, round(20 * spleen_efficiency))
owner.adjustToxLoss(15 * spleen_efficiency)
diff --git a/code/modules/organs/internal/subtypes/stomach.dm b/code/modules/organs/internal/subtypes/stomach.dm
index 0a15f48700d1..b6369fd6e686 100644
--- a/code/modules/organs/internal/subtypes/stomach.dm
+++ b/code/modules/organs/internal/subtypes/stomach.dm
@@ -57,9 +57,3 @@
acidtype = "sacid"
-/obj/item/organ/internal/stomach/machine/handle_organ_proc_special()
- ..()
- if(owner && owner.stat != DEAD)
- owner.bodytemperature += round(owner.robobody_count * 0.25, 0.1)
-
- return
diff --git a/code/modules/organs/organ-legacy-damage.dm b/code/modules/organs/organ-legacy-damage.dm
new file mode 100644
index 000000000000..09ef8425b062
--- /dev/null
+++ b/code/modules/organs/organ-legacy-damage.dm
@@ -0,0 +1,39 @@
+
+/obj/item/organ/proc/is_damaged()
+ return damage > 0
+
+/obj/item/organ/proc/is_bruised()
+ return damage >= min_bruised_damage
+
+/obj/item/organ/proc/is_broken()
+ return (damage >= min_broken_damage || (status & ORGAN_CUT_AWAY) || (status & ORGAN_BROKEN))
+
+//Note: external organs have their own version of this proc
+/obj/item/organ/proc/take_damage(amount, var/silent=0)
+ ASSERT(amount >= 0)
+ if(src.robotic >= ORGAN_ROBOT)
+ src.damage = between(0, src.damage + (amount * 0.8), max_damage)
+ else
+ src.damage = between(0, src.damage + amount, max_damage)
+
+ //only show this if the organ is not robotic
+ if(owner && parent_organ && amount > 0)
+ var/obj/item/organ/external/parent = owner?.legacy_organ_by_zone(parent_organ)
+ if(parent && !silent)
+ owner.custom_pain("Something inside your [parent.name] hurts a lot.", amount)
+
+/obj/item/organ/proc/bruise()
+ damage = max(damage, min_bruised_damage)
+
+// todo: unified organ damage system
+// for now, this is how to heal internal organs
+/obj/item/organ/proc/heal_damage_i(amount, force, can_revive)
+ ASSERT(amount > 0)
+ var/dead = !!(status & ORGAN_DEAD)
+ if(dead && !force && !can_revive)
+ return FALSE
+ //? which is better again..?
+ // damage = clamp(damage - round(amount, DAMAGE_PRECISION), 0, max_damage)
+ damage = clamp(round(damage - amount, DAMAGE_PRECISION), 0, max_damage)
+ if(dead && can_revive)
+ revive()
diff --git a/code/modules/organs/organ-legacy-eating.dm b/code/modules/organs/organ-legacy-eating.dm
new file mode 100644
index 000000000000..59f92131faa1
--- /dev/null
+++ b/code/modules/organs/organ-legacy-eating.dm
@@ -0,0 +1,44 @@
+/**
+ * yeah uh don't shoot the messenger i don't know why this file is here
+ *
+ * we should probably rework this or something at some point
+ */
+
+/obj/item/organ/attack_self(mob/user, datum/event_args/actor/actor)
+ . = ..()
+ if(.)
+ return
+
+ // Convert it to an edible form, yum yum.
+ if(!(robotic >= ORGAN_ROBOT) && user.a_intent == INTENT_HELP && user.zone_sel.selecting == O_MOUTH)
+ bitten(user)
+ return
+
+/obj/item/organ/proc/bitten(mob/user)
+
+ if(robotic >= ORGAN_ROBOT)
+ return
+
+ to_chat(user, SPAN_NOTICE("You take an experimental bite out of \the [src]."))
+ var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list
+ blood_splatter(src,B,1)
+
+ user.temporarily_remove_from_inventory(src, INV_OP_FORCE)
+
+ var/obj/item/reagent_containers/food/snacks/organ/O = new(get_turf(src))
+ O.name = name
+ O.icon = icon
+ O.icon_state = icon_state
+
+ // Pass over the blood.
+ reagents.trans_to(O, reagents.total_volume)
+
+ if(fingerprints)
+ O.fingerprints = fingerprints.Copy()
+ if(fingerprintshidden)
+ O.fingerprintshidden = fingerprintshidden.Copy()
+ if(fingerprintslast)
+ O.fingerprintslast = fingerprintslast
+
+ user.put_in_active_hand(O)
+ qdel(src)
diff --git a/code/modules/organs/organ-legacy-health.dm b/code/modules/organs/organ-legacy-health.dm
new file mode 100644
index 000000000000..ea87bbb8c7b4
--- /dev/null
+++ b/code/modules/organs/organ-legacy-health.dm
@@ -0,0 +1,87 @@
+
+/obj/item/organ/proc/update_health()
+ // TODO: refactor, this should only be on internal!
+ if(damage >= max_damage)
+ die()
+
+/obj/item/organ/proc/is_dead()
+ return (status & ORGAN_DEAD)
+
+/**
+ * Checks if we can currently die.
+ */
+/obj/item/organ/proc/can_die()
+ return (robotic < ORGAN_ROBOT)
+
+/**
+ * Called to kill this organ.
+ *
+ * @params
+ * * force - ignore can_die()
+ *
+ * @return TRUE / FALSE based on if this actually killed the organ. Returns TRUE if the organ was already dead.
+ */
+/obj/item/organ/proc/die(force = FALSE)
+ SHOULD_NOT_OVERRIDE(TRUE)
+ if(!can_die() && !force)
+ return FALSE
+ if(is_dead())
+ return TRUE
+ status |= ORGAN_DEAD
+ damage = max_damage
+ on_die()
+ if(owner)
+ handle_organ_mod_special(TRUE)
+ if(vital)
+ owner.death()
+ reconsider_processing()
+ return TRUE
+
+/**
+ * Called when we die (*not* our owner).
+ */
+/obj/item/organ/proc/on_die()
+ return
+
+/**
+ * Checks if we're currently able to be revived.
+ */
+/obj/item/organ/proc/can_revive()
+ return damage < max_damage
+
+/**
+ * Called to heal all damages
+ */
+/obj/item/organ/proc/rejuvenate()
+ damage = 0
+ germ_level = 0
+
+/**
+ * Called to bring us back to life.
+ *
+ * @params
+ * * full_heal - heal all maladies
+ * * force - ignore can_revive()
+ *
+ * @return TRUE / FALSE based on if this actually ended up reviving the organ. Returns TRUE if organ was already alive.
+ */
+/obj/item/organ/proc/revive(full_heal = FALSE, force = FALSE)
+ SHOULD_NOT_OVERRIDE(TRUE)
+ if(full_heal)
+ rejuvenate()
+ if(!is_dead())
+ return TRUE
+ if(!can_revive() && !force)
+ return FALSE
+ status &= ~ORGAN_DEAD
+ on_revive()
+ if(owner)
+ handle_organ_mod_special(FALSE)
+ reconsider_processing()
+ return TRUE
+
+/**
+ * Called when we're brought back to life.
+ */
+/obj/item/organ/proc/on_revive()
+ return
diff --git a/code/modules/organs/organ-legacy.dm b/code/modules/organs/organ-legacy.dm
new file mode 100644
index 000000000000..ec9c0b77b937
--- /dev/null
+++ b/code/modules/organs/organ-legacy.dm
@@ -0,0 +1,246 @@
+
+/obj/item/organ/proc/set_dna(datum/dna/new_dna)
+ if(new_dna)
+ dna = new_dna.Clone()
+ if(blood_DNA)
+ blood_DNA.Cut()
+ blood_DNA[dna.unique_enzymes] = dna.b_type
+
+ s_base = new_dna.s_base
+
+/obj/item/organ/proc/adjust_germ_level(var/amount) // Unless you're setting germ level directly to 0, use this proc instead
+ germ_level = clamp(germ_level + amount, 0, INFECTION_LEVEL_MAX)
+
+/obj/item/organ/examine(mob/user, dist)
+ . = ..()
+ if(status & ORGAN_DEAD)
+ . += "The decay has set in."
+
+/obj/item/organ/proc/rejuvenate_legacy(var/ignore_prosthetic_prefs)
+ damage = 0
+ status = 0
+ germ_level = 0
+ if(owner)
+ handle_organ_mod_special()
+ if(!ignore_prosthetic_prefs && owner && owner.client && owner.client.prefs && owner.client.prefs.real_name == owner.real_name)
+ var/status = owner.client.prefs.organ_data[organ_tag]
+ if(status == "assisted")
+ mechassist()
+ else if(status == "mechanical")
+ robotize()
+
+///Adds autopsy data for used_weapon.
+/obj/item/organ/proc/add_autopsy_data(var/used_weapon, var/damage)
+ var/datum/autopsy_data/W = autopsy_data[used_weapon]
+ if(!W)
+ W = new()
+ W.weapon = used_weapon
+ autopsy_data[used_weapon] = W
+
+ W.hits += 1
+ W.damage += damage
+ W.time_inflicted = world.time
+
+/// Being used to make robutt hearts, etc
+/obj/item/organ/proc/robotize()
+ robotic = ORGAN_ROBOT
+ src.status &= ~ORGAN_BROKEN
+ src.status &= ~ORGAN_BLEEDING
+ src.status &= ~ORGAN_CUT_AWAY
+
+/// Used to add things like pacemakers, etc
+/obj/item/organ/proc/mechassist()
+ robotize()
+ robotic = ORGAN_ASSISTED
+ min_bruised_damage = 15
+ min_broken_damage = 35
+ butcherable = FALSE
+
+///Used to make the circuit-brain. On this level in the event more circuit-organs are added/tweaks are wanted.
+/obj/item/organ/proc/digitize()
+ robotize()
+
+#warn obliterate
+/obj/item/organ/proc/removed(var/mob/living/user)
+ if(owner)
+ var/obj/item/organ/external/affected = owner.legacy_organ_by_zone(parent_organ)
+ if(affected)
+ affected.internal_organs -= src
+
+ forceMove(owner.drop_location())
+ rejecting = null
+
+ if(istype(owner))
+ var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list
+ if(!organ_blood || !organ_blood.data["blood_DNA"])
+ owner.vessel.trans_to(src, 5, 1, 1)
+
+ if(owner && vital)
+ if(user)
+ add_attack_logs(user, owner, "Removed vital organ [src.name]")
+ if(owner.stat != DEAD)
+ owner.can_defib = 0
+ owner.death()
+
+ owner = null
+ reconsider_processing()
+
+#warn obliterate
+/obj/item/organ/proc/replaced(var/mob/living/carbon/human/target,var/obj/item/organ/external/affected)
+ if(!istype(target))
+ return
+
+ var/datum/reagent/blood/transplant_blood = locate(/datum/reagent/blood) in reagents.reagent_list
+ transplant_data = list()
+ if(!transplant_blood)
+ transplant_data["species"] = target?.species.name
+ transplant_data["blood_type"] = target?.dna.b_type
+ transplant_data["blood_DNA"] = target?.dna.unique_enzymes
+ else
+ transplant_data["species"] = transplant_blood?.data["species"]
+ transplant_data["blood_type"] = transplant_blood?.data["blood_type"]
+ transplant_data["blood_DNA"] = transplant_blood?.data["blood_DNA"]
+
+ owner = target
+ loc = owner
+ reconsider_processing()
+
+/**
+ * can we decay?
+ */
+/obj/item/organ/proc/can_decay()
+ return CONFIG_GET(flag/organ_decay) && !HAS_TRAIT(src, TRAIT_ORGAN_PRESERVED) && (!loc || !HAS_TRAIT(loc, TRAIT_ORGAN_PRESERVED)) && (!owner || !HAS_TRAIT(owner, TRAIT_PRESERVE_ALL_ORGANS)) && decays
+
+/**
+ * preserved trait wrapper
+ */
+/obj/item/organ/proc/preserve(source)
+ ASSERT(source)
+ ADD_TRAIT(src, TRAIT_ORGAN_PRESERVED, source)
+ reconsider_processing()
+
+/**
+ * preserved trait wrapper
+ */
+/obj/item/organ/proc/unpreserve(source)
+ ASSERT(source)
+ REMOVE_TRAIT(src, TRAIT_ORGAN_PRESERVED, source)
+ reconsider_processing()
+
+//Germs
+/obj/item/organ/attackby(obj/item/W as obj, mob/user as mob)
+ if(can_butcher(W, user))
+ butcher(W, user)
+ return
+
+ return ..()
+
+/obj/item/organ/proc/can_butcher(var/obj/item/O, var/mob/living/user)
+ if(butcherable && meat_type)
+
+ if(istype(O, /obj/machinery/gibber)) // The great equalizer.
+ return TRUE
+
+ if(robotic >= ORGAN_ROBOT)
+ if(O.is_screwdriver())
+ return TRUE
+
+ else
+ if(is_sharp(O) && has_edge(O))
+ return TRUE
+
+ return FALSE
+
+/obj/item/organ/proc/butcher(var/obj/item/O, var/mob/living/user, var/atom/newtarget)
+ if(robotic >= ORGAN_ROBOT)
+ user?.visible_message(SPAN_NOTICE("[user] disassembles \the [src]."))
+
+ else
+ user?.visible_message(SPAN_NOTICE("[user] butchers \the [src]."))
+
+ if(!newtarget)
+ newtarget = get_turf(src)
+
+ var/obj/item/newmeat = new meat_type(newtarget)
+
+ if(istype(newmeat, /obj/item/reagent_containers/food/snacks/meat))
+ newmeat.name = "[src.name] [newmeat.name]" // "liver meat" "heart meat", etc.
+
+ qdel(src)
+
+/obj/item/organ/proc/organ_can_feel_pain()
+ if(species.species_flags & NO_PAIN)
+ return FALSE
+ if(status & ORGAN_DESTROYED)
+ return FALSE
+ if(robotic && robotic < ORGAN_LIFELIKE) //Super fancy humanlike robotics probably have sensors, or something?
+ return FALSE
+ if(stapled_nerves)
+ return FALSE
+ return 1
+
+/obj/item/organ/proc/handle_organ_mod_special(var/removed = FALSE) // Called when created, transplanted, and removed.
+ // todo: better way
+ if(owner)
+ rad_flags |= RAD_NO_CONTAMINATE
+ else
+ rad_flags &= ~RAD_NO_CONTAMINATE
+
+ if(!istype(owner))
+ return
+
+ var/list/save_verbs = list()
+
+ if(removed && organ_verbs) // Do we share verbs with any other organs? Are they functioning?
+ var/list/all_organs = list()
+ all_organs |= owner.organs
+ all_organs |= owner.internal_organs
+
+ for(var/obj/item/organ/O in all_organs)
+ if(!(O.status & ORGAN_DEAD) && O.organ_verbs && O.check_verb_compatability())
+ for(var/verb_type in O.organ_verbs)
+ if(verb_type in organ_verbs)
+ save_verbs |= verb_type
+
+ if(!removed && organ_verbs && check_verb_compatability())
+ for(var/verb_path in organ_verbs)
+ add_verb(owner, verb_path)
+ else if(organ_verbs)
+ for(var/verb_path in organ_verbs)
+ if(!(verb_path in save_verbs))
+ remove_verb(owner, verb_path)
+
+ if(removed)
+ on_remove(owner)
+ else
+ on_insert(owner)
+
+/// Used for determining if an organ should give or remove its verbs. I.E., FBP part in a human, no verbs. If true, keep or add.
+/obj/item/organ/proc/check_verb_compatability()
+ if(owner)
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ var/obj/item/organ/O = H.legacy_organ_by_zone(parent_organ)
+ if(forgiving_class)
+ if(O.robotic <= ORGAN_ASSISTED && robotic <= ORGAN_LIFELIKE) // Parent is organic or assisted, we are at most synthetic.
+ return TRUE
+
+ if(O.robotic >= ORGAN_ROBOT && robotic >= ORGAN_ASSISTED) // Parent is synthetic, and we are biosynthetic at least.
+ return TRUE
+
+ if(!target_parent_classes || !target_parent_classes.len) // Default checks, if we're not looking for a Specific type.
+
+ if(O.robotic == robotic) // Same thing, we're fine.
+ return TRUE
+
+ if(O.robotic < ORGAN_ROBOT && robotic < ORGAN_ROBOT)
+ return TRUE
+
+ if(O.robotic > ORGAN_ASSISTED && robotic > ORGAN_ASSISTED)
+ return TRUE
+
+ else
+ if(O.robotic in target_parent_classes)
+ return TRUE
+
+ return FALSE
diff --git a/code/modules/organs/organ-mappings.dm b/code/modules/organs/organ-mappings.dm
new file mode 100644
index 000000000000..7bd28a60bd7b
--- /dev/null
+++ b/code/modules/organs/organ-mappings.dm
@@ -0,0 +1,24 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+GLOBAL_LIST_INIT(biology_organ_mappings, zz__init_biology_organ_mappings())
+
+/**
+ * Mappings for organs go here.
+ *
+ * ## Why?
+ *
+ * New organs are composition based, optimally. This means that biologies tick on them
+ * instead of them having hard-coded tick procs.
+ *
+ * This has a downside; we are thus unable to implement things like say, organ actions for a specific default biology.
+ * We can do that with subtypes, but then we need to manually override it in the species, and if the player
+ * uses something like a biology injection (e.g. 'replace synthetic with protean') in their character entry,
+ * we'd need the injection to specify replacement organs.
+ *
+ * Which we still can do. But to make the defaults easier, this page will store a list of biology-to-default's
+ * for given organ keys. This means that if an organ defaults to a given biology, we will instead look up
+ * from the list what type it should be with its organ key without actually specifying its type manually.
+ */
+/proc/zz__init_biology_organ_mappings()
+ #warn impl
diff --git a/code/modules/organs/organ-tick.dm b/code/modules/organs/organ-tick.dm
new file mode 100644
index 000000000000..8bc1d2c8ab13
--- /dev/null
+++ b/code/modules/organs/organ-tick.dm
@@ -0,0 +1,222 @@
+
+/**
+ * called while alive
+ *
+ * preconditions: owner is a /mob
+ */
+/obj/item/organ/proc/tick_life(dt)
+ if(loc != owner)
+ stack_trace("organ outside of owner automatically yanked from owner. owner was [owner] ([REF(owner)]), src was [src] ([REF(src)])")
+ owner = null
+ return
+
+ handle_organ_proc_special()
+
+ //Process infections
+ if(robotic >= ORGAN_ROBOT || (istype(owner) && (owner.species && (owner.species.species_flags & (IS_PLANT | NO_INFECT)))))
+ germ_level = 0
+ return
+
+ if(owner?.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs
+ //** Handle antibiotics and curing infections
+ handle_antibiotics()
+ handle_rejection()
+ handle_germ_effects()
+
+/**
+ * called while dead
+ *
+ * preconditions: owner is a /mob
+ */
+/obj/item/organ/proc/tick_death(dt)
+ if(loc != owner)
+ stack_trace("organ outside of owner automatically yanked from owner. owner was [owner] ([REF(owner)]), src was [src] ([REF(src)])")
+ owner = null
+ return
+
+ handle_organ_proc_special()
+
+ //Process infections
+ if(robotic >= ORGAN_ROBOT || (istype(owner) && (owner.species && (owner.species.species_flags & (IS_PLANT | NO_INFECT)))))
+ germ_level = 0
+ return
+
+ // removal temporary, pending health rework
+ // if(owner?.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs
+ // //** Handle antibiotics and curing infections
+ // handle_antibiotics()
+ // handle_rejection()
+ // handle_germ_effects()
+
+ if(can_decay())
+ handle_decay(dt)
+ else
+ reconsider_processing()
+ update_health()
+
+/**
+ * called while removed from a mob
+ */
+/obj/item/organ/proc/tick_removed(dt)
+ handle_organ_proc_special()
+
+ if(can_decay())
+ handle_decay(dt)
+ else
+ reconsider_processing()
+ update_health()
+
+ //Process infections
+ if(reagents)
+ var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list
+ if(B && prob(40))
+ reagents.remove_reagent("blood",0.1)
+ blood_splatter(src,B,1)
+ adjust_germ_level(rand(2,6))
+ if(germ_level >= INFECTION_LEVEL_TWO)
+ adjust_germ_level(rand(2,6))
+ if(germ_level >= INFECTION_LEVEL_THREE)
+ die()
+
+/obj/item/organ/proc/handle_decay(dt)
+ var/multiplier = CONFIG_GET(number/organ_decay_multiplier)
+ take_damage(dt * decay_rate * multiplier, TRUE)
+
+/**
+ * do we need to process?
+ * do NOT check owner for removed, listen to the params!
+ * do NOT check owner for life/dead, listen to the params!
+ *
+ * ! DO NOT RELY ON THIS TO STOP PROCESSING.
+ * Define your tick_life, tick_death, tick_removed properly!
+ *
+ * @params
+ * - locality - check [code/__DEFINES/mobs/organs.dm]
+ */
+/obj/item/organ/proc/should_process(locality)
+ switch(locality)
+ if(ORGAN_LOCALITY_REMOVED)
+ return can_decay() && !is_dead()
+ if(ORGAN_LOCALITY_IN_LIVING_MOB)
+ return TRUE
+ if(ORGAN_LOCALITY_IN_DEAD_MOB)
+ return can_decay() && !is_dead()
+
+/**
+ * reconsider if we need to process
+ */
+/obj/item/organ/proc/reconsider_processing()
+ if(owner)
+ // we're in someone we'll always tick from their handle_organs so don't process externally
+ STOP_PROCESSING(SSobj, src)
+ return
+ // we're not in someone
+ if(should_process(ORGAN_LOCALITY_REMOVED))
+ START_PROCESSING(SSobj, src)
+ else
+ STOP_PROCESSING(SSobj, src)
+
+/obj/item/organ/proc/handle_antibiotics()
+ if(istype(owner))
+ var/antibiotics = owner.chem_effects[CE_ANTIBIOTIC] || 0
+
+ if (!germ_level || antibiotics < ANTIBIO_NORM)
+ return
+
+ // Cure instantly
+ if (germ_level < INFECTION_LEVEL_ONE)
+ germ_level = 0
+
+ /// At germ_level < 500, this should cure the infection in a minute
+ else if (germ_level < INFECTION_LEVEL_TWO)
+ adjust_germ_level(-antibiotics*4)
+
+ /// At germ_level < 1000, this will cure the infection in 5 minutes
+ else if (germ_level < INFECTION_LEVEL_THREE)
+ adjust_germ_level(-antibiotics*2)
+
+ else
+ /// You waited this long to get treated, you don't really deserve this organ.
+ adjust_germ_level(-antibiotics)
+
+///A little wonky: internal organs stop calling this (they return early in process) when dead, but external ones cause further damage when dead
+/obj/item/organ/proc/handle_germ_effects()
+ //* Handle the effects of infections
+ if(robotic >= ORGAN_ROBOT) //Just in case!
+ germ_level = 0
+ return 0
+
+ var/antibiotics = iscarbon(owner) ? owner.chem_effects[CE_ANTIBIOTIC] || 0 : 0
+
+ var/infection_damage = 0
+
+ //* Infection damage *//
+
+ //If the organ is dead, for the sake of organs that may have died due to non-infection, we'll only do damage if they have at least L1 infection (built up below)
+ if((status & ORGAN_DEAD) && antibiotics < ANTIBIO_OD && germ_level >= INFECTION_LEVEL_ONE)
+ infection_damage = max(1, 1 + round((germ_level - INFECTION_LEVEL_THREE)/200,0.25)) //1 Tox plus a little based on germ level
+
+ else if(germ_level > INFECTION_LEVEL_TWO && antibiotics < ANTIBIO_OD)
+ infection_damage = max(0.25, 0.25 + round((germ_level - INFECTION_LEVEL_TWO)/200,0.25))
+
+ if(infection_damage)
+ owner.adjustToxLoss(infection_damage)
+
+ if (germ_level > 0 && germ_level < INFECTION_LEVEL_ONE/2 && prob(30))
+ adjust_germ_level(-antibiotics)
+
+ //* Germ Accumulation
+
+ //Dead organs accumulate germs indefinitely
+ if(status & ORGAN_DEAD)
+ adjust_germ_level(1)
+
+ //Half of level 1 is growing but harmless
+ if (germ_level >= INFECTION_LEVEL_ONE/2)
+ //aiming for germ level to go from ambient to INFECTION_LEVEL_TWO in an average of 15 minutes
+ if(!antibiotics && prob(round(germ_level/6)))
+ adjust_germ_level(1)
+
+ //Level 1 qualifies for specific organ processing effects
+ if(germ_level >= INFECTION_LEVEL_ONE)
+ . = 1 //Organ qualifies for effect-specific processing
+ //var/fever_temperature = (owner.species.heat_level_1 - owner.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.species.body_temperature
+ //owner.bodytemperature += between(0, (fever_temperature - T20C)/BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature)
+ var/fever_temperature = owner?.species.heat_discomfort_level * 1.10 //Heat discomfort level plus 10%
+ if(owner?.bodytemperature < fever_temperature)
+ owner?.bodytemperature += min(0.2,(fever_temperature - owner?.bodytemperature) / 10) //Will usually climb by 0.2, else 10% of the difference if less
+
+ //Level two qualifies for further processing effects
+ if (germ_level >= INFECTION_LEVEL_TWO)
+ . = 2 //Organ qualifies for effect-specific processing
+ //No particular effect on the general 'organ' at 3
+
+ //Level three qualifies for significant growth and further effects
+ if (germ_level >= INFECTION_LEVEL_THREE && antibiotics < ANTIBIO_OD)
+ . = 3 //Organ qualifies for effect-specific processing
+ adjust_germ_level(rand(5,10)) //Germ_level increases without overdose of antibiotics
+
+/obj/item/organ/proc/handle_rejection()
+ // Process unsuitable transplants. TODO: consider some kind of
+ // immunosuppressant that changes transplant data to make it match.
+ if(dna && can_reject)
+ if(!rejecting)
+ if(blood_incompatible(dna.b_type, owner.dna.b_type, species.name, owner.species.name)) // Process species by name.
+ rejecting = 1
+ else
+ rejecting++ //Rejection severity increases over time.
+ if(rejecting % 10 == 0) //Only fire every ten rejection ticks.
+ switch(rejecting)
+ if(1 to 50)
+ adjust_germ_level(1)
+ if(51 to 200)
+ adjust_germ_level(rand(1,2))
+ if(201 to 500)
+ adjust_germ_level(rand(2,3))
+ if(501 to INFINITY)
+ adjust_germ_level(rand(3,5))
+ owner.reagents.add_reagent("toxin", rand(1,2))
+
+/// Called when processed.
+/obj/item/organ/proc/handle_organ_proc_special()
+ return
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index 3ca01afc5760..d2d642f05526 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -1,4 +1,5 @@
/obj/item/organ
+ abstract_type = /obj/item/organ
name = "organ"
icon = 'icons/obj/surgery.dmi'
germ_level = 0
@@ -6,6 +7,7 @@
pickup_sound = 'sound/items/pickup/flesh.ogg'
//* Actions *//
+
/// actions to give the owner of this organ
///
/// valid starting values include:
@@ -17,6 +19,45 @@
/// description for organ action; defaults to [desc]
var/organ_action_desc
+ //* Biology *//
+
+ /// Our biology. Set to type to init.
+ ///
+ /// * Null biology is allowed but is usually not what you want.
+ var/datum/biology/biology
+ /// Our biology's scratch space.
+ ///
+ /// * Only set if our biology requires a state.
+ var/datum/biology_organ_state/biology_state
+ #warn impl
+
+ //* Flags *//
+
+ /// Our organ flags.
+ var/organ_flags = NONE
+ /// Our organ discovery flags
+ var/organ_discovery_flags = NONE
+
+ //* Insert / Remove *//
+
+ /// Always drop, except for ashing / dusting a mob.
+ ///
+ /// * Admin deletions will still delete the organ.
+ var/always_drop_on_gib = FALSE
+ #warn hook
+ /// Always drop, including for ash / dust.
+ ///
+ /// * Admin deletions will still delete the organ.
+ /// * Implies [always_drop_on_gib]
+ var/always_drop_on_everything = FALSE
+ #warn hook
+ /// Our organ key to register as.
+ ///
+ /// * This is **not** arbitrary. Keys have type semantics.
+ var/organ_key
+
+ //! legacy below !//
+
//* ## STRINGS VARS
/// Unique identifier.
var/organ_tag = "organ"
@@ -92,24 +133,14 @@
/// What does butchering, if possible, make?
var/meat_type
-/obj/item/organ/Initialize(mapload, internal)
- . = ..(mapload)
+/obj/item/organ/Initialize(mapload)
+ . = ..()
create_reagents(5)
// HACK: if we're in repository subsystem load, skip brainmob
if(!SSrepository.initialized)
return
- if(isliving(loc))
- owner = loc
- set_weight_class(max(src.w_class + mob_size_difference(owner.mob_size, MOB_MEDIUM), 1)) //smaller mobs have smaller organs.
- if(internal)
- LAZYDISTINCTADD(owner.internal_organs, src)
- LAZYSET(owner.internal_organs_by_name, organ_tag, src)
- else
- LAZYDISTINCTADD(owner.organs, src)
- LAZYSET(owner.organs_by_name, organ_tag, src)
-
if(!max_damage)
max_damage = min_broken_damage * 2
@@ -127,7 +158,7 @@
var/mob/living/carbon/human/H = C
if(istype(H))
if(internal)
- var/obj/item/organ/external/E = H.get_organ(parent_organ)
+ var/obj/item/organ/external/E = H.legacy_organ_by_zone(parent_organ)
if(E)
if(E.internal_organs == null)
E.internal_organs = list()
@@ -153,13 +184,10 @@
else
meat_type = /obj/item/reagent_containers/food/snacks/meat
- handle_organ_mod_special()
-
/obj/item/organ/Destroy()
- handle_organ_mod_special(TRUE)
STOP_PROCESSING(SSobj, src)
if(owner)
- owner = null
+ remove(null, TRUE)
if(transplant_data)
transplant_data.Cut()
if(autopsy_data)
@@ -170,659 +198,6 @@
species = null
return ..()
-/obj/item/organ/proc/update_health()
- // TODO: refactor, this should only be on internal!
- if(damage >= max_damage)
- die()
-
-/obj/item/organ/proc/set_dna(datum/dna/new_dna)
- if(new_dna)
- dna = new_dna.Clone()
- if(blood_DNA)
- blood_DNA.Cut()
- blood_DNA[dna.unique_enzymes] = dna.b_type
-
- s_base = new_dna.s_base
-
-/obj/item/organ/proc/is_dead()
- return (status & ORGAN_DEAD)
-
-/**
- * Checks if we can currently die.
- */
-/obj/item/organ/proc/can_die()
- return (robotic < ORGAN_ROBOT)
-
-/**
- * Called to kill this organ.
- *
- * @params
- * * force - ignore can_die()
- *
- * @return TRUE / FALSE based on if this actually killed the organ. Returns TRUE if the organ was already dead.
- */
-/obj/item/organ/proc/die(force = FALSE)
- SHOULD_NOT_OVERRIDE(TRUE)
- if(!can_die() && !force)
- return FALSE
- if(is_dead())
- return TRUE
- status |= ORGAN_DEAD
- damage = max_damage
- on_die()
- if(owner)
- handle_organ_mod_special(TRUE)
- if(vital)
- owner.death()
- reconsider_processing()
- return TRUE
-
-/**
- * Called when we die (*not* our owner).
- */
-/obj/item/organ/proc/on_die()
- return
-
-/**
- * Checks if we're currently able to be revived.
- */
-/obj/item/organ/proc/can_revive()
- return damage < max_damage
-
-/**
- * Called to heal all damages
- */
-/obj/item/organ/proc/rejuvenate()
- damage = 0
- germ_level = 0
-
-/**
- * Called to bring us back to life.
- *
- * @params
- * * full_heal - heal all maladies
- * * force - ignore can_revive()
- *
- * @return TRUE / FALSE based on if this actually ended up reviving the organ. Returns TRUE if organ was already alive.
- */
-/obj/item/organ/proc/revive(full_heal = FALSE, force = FALSE)
- SHOULD_NOT_OVERRIDE(TRUE)
- if(full_heal)
- rejuvenate()
- if(!is_dead())
- return TRUE
- if(!can_revive() && !force)
- return FALSE
- status &= ~ORGAN_DEAD
- on_revive()
- if(owner)
- handle_organ_mod_special(FALSE)
- reconsider_processing()
- return TRUE
-
-/**
- * Called when we're brought back to life.
- */
-/obj/item/organ/proc/on_revive()
- return
-
-/obj/item/organ/proc/adjust_germ_level(var/amount) // Unless you're setting germ level directly to 0, use this proc instead
- germ_level = clamp(germ_level + amount, 0, INFECTION_LEVEL_MAX)
-
-/obj/item/organ/examine(mob/user, dist)
- . = ..()
- if(status & ORGAN_DEAD)
- . += "The decay has set in."
-
-/obj/item/organ/proc/receive_chem(chemical as obj)
- return 0
-
-/obj/item/organ/proc/remove_rejuv()
- qdel(src)
-
-/obj/item/organ/proc/rejuvenate_legacy(var/ignore_prosthetic_prefs)
- damage = 0
- status = 0
- germ_level = 0
- if(owner)
- handle_organ_mod_special()
- if(!ignore_prosthetic_prefs && owner && owner.client && owner.client.prefs && owner.client.prefs.real_name == owner.real_name)
- var/status = owner.client.prefs.organ_data[organ_tag]
- if(status == "assisted")
- mechassist()
- else if(status == "mechanical")
- robotize()
-
-/obj/item/organ/proc/is_damaged()
- return damage > 0
-
-/obj/item/organ/proc/is_bruised()
- return damage >= min_bruised_damage
-
-/obj/item/organ/proc/is_broken()
- return (damage >= min_broken_damage || (status & ORGAN_CUT_AWAY) || (status & ORGAN_BROKEN))
-
-///Adds autopsy data for used_weapon.
-/obj/item/organ/proc/add_autopsy_data(var/used_weapon, var/damage)
- var/datum/autopsy_data/W = autopsy_data[used_weapon]
- if(!W)
- W = new()
- W.weapon = used_weapon
- autopsy_data[used_weapon] = W
-
- W.hits += 1
- W.damage += damage
- W.time_inflicted = world.time
-
-//Note: external organs have their own version of this proc
-/obj/item/organ/proc/take_damage(amount, var/silent=0)
- ASSERT(amount >= 0)
- if(src.robotic >= ORGAN_ROBOT)
- src.damage = between(0, src.damage + (amount * 0.8), max_damage)
- else
- src.damage = between(0, src.damage + amount, max_damage)
-
- //only show this if the organ is not robotic
- if(owner && parent_organ && amount > 0)
- var/obj/item/organ/external/parent = owner?.get_organ(parent_organ)
- if(parent && !silent)
- owner.custom_pain("Something inside your [parent.name] hurts a lot.", amount)
-
-/obj/item/organ/proc/bruise()
- damage = max(damage, min_bruised_damage)
-
-/obj/item/organ/proc/break_organ()
- damage = max(damage, min_broken_damage)
-
-/// Being used to make robutt hearts, etc
-/obj/item/organ/proc/robotize()
- robotic = ORGAN_ROBOT
- src.status &= ~ORGAN_BROKEN
- src.status &= ~ORGAN_BLEEDING
- src.status &= ~ORGAN_CUT_AWAY
-
-/// Used to add things like pacemakers, etc
-/obj/item/organ/proc/mechassist()
- robotize()
- robotic = ORGAN_ASSISTED
- min_bruised_damage = 15
- min_broken_damage = 35
- butcherable = FALSE
-
-///Used to make the circuit-brain. On this level in the event more circuit-organs are added/tweaks are wanted.
-/obj/item/organ/proc/digitize()
- robotize()
-
-/obj/item/organ/proc/removed(var/mob/living/user)
- if(owner)
- owner.internal_organs_by_name[organ_tag] = null
- owner.internal_organs_by_name -= organ_tag
- owner.internal_organs_by_name -= null
- owner.internal_organs -= src
-
- var/obj/item/organ/external/affected = owner.get_organ(parent_organ)
- if(affected) affected.internal_organs -= src
-
- forceMove(owner.drop_location())
- rejecting = null
-
- if(istype(owner))
- var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list
- if(!organ_blood || !organ_blood.data["blood_DNA"])
- owner.vessel.trans_to(src, 5, 1, 1)
-
- if(owner && vital)
- if(user)
- add_attack_logs(user, owner, "Removed vital organ [src.name]")
- if(owner.stat != DEAD)
- owner.can_defib = 0
- owner.death()
-
- handle_organ_mod_special(TRUE)
- owner = null
- reconsider_processing()
-
-/obj/item/organ/proc/replaced(var/mob/living/carbon/human/target,var/obj/item/organ/external/affected)
-
- if(!istype(target)) return
-
- var/datum/reagent/blood/transplant_blood = locate(/datum/reagent/blood) in reagents.reagent_list
- transplant_data = list()
- if(!transplant_blood)
- transplant_data["species"] = target?.species.name
- transplant_data["blood_type"] = target?.dna.b_type
- transplant_data["blood_DNA"] = target?.dna.unique_enzymes
- else
- transplant_data["species"] = transplant_blood?.data["species"]
- transplant_data["blood_type"] = transplant_blood?.data["blood_type"]
- transplant_data["blood_DNA"] = transplant_blood?.data["blood_DNA"]
-
- owner = target
- loc = owner
- target.internal_organs |= src
- affected.internal_organs |= src
- target.internal_organs_by_name[organ_tag] = src
- handle_organ_mod_special()
- reconsider_processing()
-
-/**
- * called while alive
- *
- * preconditions: owner is a /mob
- */
-/obj/item/organ/proc/tick_life(dt)
- if(loc != owner)
- stack_trace("organ outside of owner automatically yanked from owner. owner was [owner] ([REF(owner)]), src was [src] ([REF(src)])")
- owner = null
- return
-
- handle_organ_proc_special()
-
- //Process infections
- if(robotic >= ORGAN_ROBOT || (istype(owner) && (owner.species && (owner.species.species_flags & (IS_PLANT | NO_INFECT)))))
- germ_level = 0
- return
-
- if(owner?.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs
- //** Handle antibiotics and curing infections
- handle_antibiotics()
- handle_rejection()
- handle_germ_effects()
-
-/**
- * called while dead
- *
- * preconditions: owner is a /mob
- */
-/obj/item/organ/proc/tick_death(dt)
- if(loc != owner)
- stack_trace("organ outside of owner automatically yanked from owner. owner was [owner] ([REF(owner)]), src was [src] ([REF(src)])")
- owner = null
- return
-
- handle_organ_proc_special()
-
- //Process infections
- if(robotic >= ORGAN_ROBOT || (istype(owner) && (owner.species && (owner.species.species_flags & (IS_PLANT | NO_INFECT)))))
- germ_level = 0
- return
-
- // removal temporary, pending health rework
- // if(owner?.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs
- // //** Handle antibiotics and curing infections
- // handle_antibiotics()
- // handle_rejection()
- // handle_germ_effects()
-
- if(can_decay())
- handle_decay(dt)
- else
- reconsider_processing()
- update_health()
-
-/**
- * called while removed from a mob
- */
-/obj/item/organ/proc/tick_removed(dt)
- handle_organ_proc_special()
-
- if(can_decay())
- handle_decay(dt)
- else
- reconsider_processing()
- update_health()
-
- //Process infections
- if(reagents)
- var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list
- if(B && prob(40))
- reagents.remove_reagent("blood",0.1)
- blood_splatter(src,B,1)
- adjust_germ_level(rand(2,6))
- if(germ_level >= INFECTION_LEVEL_TWO)
- adjust_germ_level(rand(2,6))
- if(germ_level >= INFECTION_LEVEL_THREE)
- die()
-
-/obj/item/organ/proc/handle_decay(dt)
- var/multiplier = CONFIG_GET(number/organ_decay_multiplier)
- take_damage(dt * decay_rate * multiplier, TRUE)
-
-/**
- * do we need to process?
- * do NOT check owner for removed, listen to the params!
- * do NOT check owner for life/dead, listen to the params!
- *
- * ! DO NOT RELY ON THIS TO STOP PROCESSING.
- * Define your tick_life, tick_death, tick_removed properly!
- *
- * @params
- * - locality - check [code/__DEFINES/mobs/organs.dm]
- */
-/obj/item/organ/proc/should_process(locality)
- switch(locality)
- if(ORGAN_LOCALITY_REMOVED)
- return can_decay() && !is_dead()
- if(ORGAN_LOCALITY_IN_LIVING_MOB)
- return TRUE
- if(ORGAN_LOCALITY_IN_DEAD_MOB)
- return can_decay() && !is_dead()
-
-/**
- * reconsider if we need to process
- */
-/obj/item/organ/proc/reconsider_processing()
- if(owner)
- // we're in someone we'll always tick from their handle_organs so don't process externally
- STOP_PROCESSING(SSobj, src)
- return
- // we're not in someone
- if(should_process(ORGAN_LOCALITY_REMOVED))
- START_PROCESSING(SSobj, src)
- else
- STOP_PROCESSING(SSobj, src)
-
-/**
- * can we decay?
- */
-/obj/item/organ/proc/can_decay()
- return CONFIG_GET(flag/organ_decay) && !HAS_TRAIT(src, TRAIT_ORGAN_PRESERVED) && (!loc || !HAS_TRAIT(loc, TRAIT_ORGAN_PRESERVED)) && (!owner || !HAS_TRAIT(owner, TRAIT_PRESERVE_ALL_ORGANS)) && decays
-
-/**
- * preserved trait wrapper
- */
-/obj/item/organ/proc/preserve(source)
- ASSERT(source)
- ADD_TRAIT(src, TRAIT_ORGAN_PRESERVED, source)
- reconsider_processing()
-
-/**
- * preserved trait wrapper
- */
-/obj/item/organ/proc/unpreserve(source)
- ASSERT(source)
- REMOVE_TRAIT(src, TRAIT_ORGAN_PRESERVED, source)
- reconsider_processing()
-
-//Germs
-/obj/item/organ/proc/handle_antibiotics()
- if(istype(owner))
- var/antibiotics = owner.chem_effects[CE_ANTIBIOTIC] || 0
-
- if (!germ_level || antibiotics < ANTIBIO_NORM)
- return
-
- // Cure instantly
- if (germ_level < INFECTION_LEVEL_ONE)
- germ_level = 0
-
- /// At germ_level < 500, this should cure the infection in a minute
- else if (germ_level < INFECTION_LEVEL_TWO)
- adjust_germ_level(-antibiotics*4)
-
- /// At germ_level < 1000, this will cure the infection in 5 minutes
- else if (germ_level < INFECTION_LEVEL_THREE)
- adjust_germ_level(-antibiotics*2)
-
- else
- /// You waited this long to get treated, you don't really deserve this organ.
- adjust_germ_level(-antibiotics)
-
-///A little wonky: internal organs stop calling this (they return early in process) when dead, but external ones cause further damage when dead
-/obj/item/organ/proc/handle_germ_effects()
- //* Handle the effects of infections
- if(robotic >= ORGAN_ROBOT) //Just in case!
- germ_level = 0
- return 0
-
- var/antibiotics = iscarbon(owner) ? owner.chem_effects[CE_ANTIBIOTIC] || 0 : 0
-
- var/infection_damage = 0
-
- //* Infection damage *//
-
- //If the organ is dead, for the sake of organs that may have died due to non-infection, we'll only do damage if they have at least L1 infection (built up below)
- if((status & ORGAN_DEAD) && antibiotics < ANTIBIO_OD && germ_level >= INFECTION_LEVEL_ONE)
- infection_damage = max(1, 1 + round((germ_level - INFECTION_LEVEL_THREE)/200,0.25)) //1 Tox plus a little based on germ level
-
- else if(germ_level > INFECTION_LEVEL_TWO && antibiotics < ANTIBIO_OD)
- infection_damage = max(0.25, 0.25 + round((germ_level - INFECTION_LEVEL_TWO)/200,0.25))
-
- if(infection_damage)
- owner.adjustToxLoss(infection_damage)
-
- if (germ_level > 0 && germ_level < INFECTION_LEVEL_ONE/2 && prob(30))
- adjust_germ_level(-antibiotics)
-
- //* Germ Accumulation
-
- //Dead organs accumulate germs indefinitely
- if(status & ORGAN_DEAD)
- adjust_germ_level(1)
-
- //Half of level 1 is growing but harmless
- if (germ_level >= INFECTION_LEVEL_ONE/2)
- //aiming for germ level to go from ambient to INFECTION_LEVEL_TWO in an average of 15 minutes
- if(!antibiotics && prob(round(germ_level/6)))
- adjust_germ_level(1)
-
- //Level 1 qualifies for specific organ processing effects
- if(germ_level >= INFECTION_LEVEL_ONE)
- . = 1 //Organ qualifies for effect-specific processing
- //var/fever_temperature = (owner.species.heat_level_1 - owner.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.species.body_temperature
- //owner.bodytemperature += between(0, (fever_temperature - T20C)/BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature)
- var/fever_temperature = owner?.species.heat_discomfort_level * 1.10 //Heat discomfort level plus 10%
- if(owner?.bodytemperature < fever_temperature)
- owner?.bodytemperature += min(0.2,(fever_temperature - owner?.bodytemperature) / 10) //Will usually climb by 0.2, else 10% of the difference if less
-
- //Level two qualifies for further processing effects
- if (germ_level >= INFECTION_LEVEL_TWO)
- . = 2 //Organ qualifies for effect-specific processing
- //No particular effect on the general 'organ' at 3
-
- //Level three qualifies for significant growth and further effects
- if (germ_level >= INFECTION_LEVEL_THREE && antibiotics < ANTIBIO_OD)
- . = 3 //Organ qualifies for effect-specific processing
- adjust_germ_level(rand(5,10)) //Germ_level increases without overdose of antibiotics
-
-/obj/item/organ/proc/handle_rejection()
- // Process unsuitable transplants. TODO: consider some kind of
- // immunosuppressant that changes transplant data to make it match.
- if(dna && can_reject)
- if(!rejecting)
- if(blood_incompatible(dna.b_type, owner.dna.b_type, species.name, owner.species.name)) // Process species by name.
- rejecting = 1
- else
- rejecting++ //Rejection severity increases over time.
- if(rejecting % 10 == 0) //Only fire every ten rejection ticks.
- switch(rejecting)
- if(1 to 50)
- adjust_germ_level(1)
- if(51 to 200)
- adjust_germ_level(rand(1,2))
- if(201 to 500)
- adjust_germ_level(rand(2,3))
- if(501 to INFINITY)
- adjust_germ_level(rand(3,5))
- owner.reagents.add_reagent("toxin", rand(1,2))
-
-/obj/item/organ/proc/bitten(mob/user)
-
- if(robotic >= ORGAN_ROBOT)
- return
-
- to_chat(user, SPAN_NOTICE("You take an experimental bite out of \the [src]."))
- var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list
- blood_splatter(src,B,1)
-
- user.temporarily_remove_from_inventory(src, INV_OP_FORCE)
-
- var/obj/item/reagent_containers/food/snacks/organ/O = new(get_turf(src))
- O.name = name
- O.icon = icon
- O.icon_state = icon_state
-
- // Pass over the blood.
- reagents.trans_to(O, reagents.total_volume)
-
- if(fingerprints)
- O.fingerprints = fingerprints.Copy()
- if(fingerprintshidden)
- O.fingerprintshidden = fingerprintshidden.Copy()
- if(fingerprintslast)
- O.fingerprintslast = fingerprintslast
-
- user.put_in_active_hand(O)
- qdel(src)
-
-/obj/item/organ/attack_self(mob/user, datum/event_args/actor/actor)
- . = ..()
- if(.)
- return
-
- // Convert it to an edible form, yum yum.
- if(!(robotic >= ORGAN_ROBOT) && user.a_intent == INTENT_HELP && user.zone_sel.selecting == O_MOUTH)
- bitten(user)
- return
-
-/obj/item/organ/attackby(obj/item/W as obj, mob/user as mob)
- if(can_butcher(W, user))
- butcher(W, user)
- return
-
- return ..()
-
-/obj/item/organ/proc/can_butcher(var/obj/item/O, var/mob/living/user)
- if(butcherable && meat_type)
-
- if(istype(O, /obj/machinery/gibber)) // The great equalizer.
- return TRUE
-
- if(robotic >= ORGAN_ROBOT)
- if(O.is_screwdriver())
- return TRUE
-
- else
- if(is_sharp(O) && has_edge(O))
- return TRUE
-
- return FALSE
-
-/obj/item/organ/proc/butcher(var/obj/item/O, var/mob/living/user, var/atom/newtarget)
- if(robotic >= ORGAN_ROBOT)
- user?.visible_message(SPAN_NOTICE("[user] disassembles \the [src]."))
-
- else
- user?.visible_message(SPAN_NOTICE("[user] butchers \the [src]."))
-
- if(!newtarget)
- newtarget = get_turf(src)
-
- var/obj/item/newmeat = new meat_type(newtarget)
-
- if(istype(newmeat, /obj/item/reagent_containers/food/snacks/meat))
- newmeat.name = "[src.name] [newmeat.name]" // "liver meat" "heart meat", etc.
-
- qdel(src)
-
-
-/obj/item/organ/proc/organ_can_feel_pain()
- if(species.species_flags & NO_PAIN)
- return FALSE
- if(status & ORGAN_DESTROYED)
- return FALSE
- if(robotic && robotic < ORGAN_LIFELIKE) //Super fancy humanlike robotics probably have sensors, or something?
- return FALSE
- if(stapled_nerves)
- return FALSE
- return 1
-
-/obj/item/organ/proc/handle_organ_mod_special(var/removed = FALSE) // Called when created, transplanted, and removed.
- // todo: better way
- if(owner)
- rad_flags |= RAD_NO_CONTAMINATE
- else
- rad_flags &= ~RAD_NO_CONTAMINATE
-
- if(!istype(owner))
- return
-
- var/list/save_verbs = list()
-
- if(removed && organ_verbs) // Do we share verbs with any other organs? Are they functioning?
- var/list/all_organs = list()
- all_organs |= owner.organs
- all_organs |= owner.internal_organs
-
- for(var/obj/item/organ/O in all_organs)
- if(!(O.status & ORGAN_DEAD) && O.organ_verbs && O.check_verb_compatability())
- for(var/verb_type in O.organ_verbs)
- if(verb_type in organ_verbs)
- save_verbs |= verb_type
-
- if(!removed && organ_verbs && check_verb_compatability())
- for(var/verb_path in organ_verbs)
- add_verb(owner, verb_path)
- else if(organ_verbs)
- for(var/verb_path in organ_verbs)
- if(!(verb_path in save_verbs))
- remove_verb(owner, verb_path)
-
- if(removed)
- on_remove(owner)
- else
- on_insert(owner)
-
-/// Called when processed.
-/obj/item/organ/proc/handle_organ_proc_special()
- return
-
-/// Used for determining if an organ should give or remove its verbs. I.E., FBP part in a human, no verbs. If true, keep or add.
-/obj/item/organ/proc/check_verb_compatability()
- if(owner)
- if(ishuman(owner))
- var/mob/living/carbon/human/H = owner
- var/obj/item/organ/O = H.get_organ(parent_organ)
- if(forgiving_class)
- if(O.robotic <= ORGAN_ASSISTED && robotic <= ORGAN_LIFELIKE) // Parent is organic or assisted, we are at most synthetic.
- return TRUE
-
- if(O.robotic >= ORGAN_ROBOT && robotic >= ORGAN_ASSISTED) // Parent is synthetic, and we are biosynthetic at least.
- return TRUE
-
- if(!target_parent_classes || !target_parent_classes.len) // Default checks, if we're not looking for a Specific type.
-
- if(O.robotic == robotic) // Same thing, we're fine.
- return TRUE
-
- if(O.robotic < ORGAN_ROBOT && robotic < ORGAN_ROBOT)
- return TRUE
-
- if(O.robotic > ORGAN_ASSISTED && robotic > ORGAN_ASSISTED)
- return TRUE
-
- else
- if(O.robotic in target_parent_classes)
- return TRUE
-
- return FALSE
-
-/obj/item/organ/proc/refresh_action_button()
- update_action_buttons()
-
-// todo: unified organ damage system
-// for now, this is how to heal internal organs
-/obj/item/organ/proc/heal_damage_i(amount, force, can_revive)
- ASSERT(amount > 0)
- var/dead = !!(status & ORGAN_DEAD)
- if(dead && !force && !can_revive)
- return FALSE
- //? which is better again..?
- // damage = clamp(damage - round(amount, DAMAGE_PRECISION), 0, max_damage)
- damage = clamp(round(damage - amount, DAMAGE_PRECISION), 0, max_damage)
- if(dead && can_revive)
- revive()
-
//* Actions *//
/obj/item/organ/update_action_buttons()
@@ -867,42 +242,139 @@
//* Biologies *//
+#warn impl
+
+//* Insert / Remove *//
+
/**
- * checks if we're any of the given biology types
+ * Inserts into a mob.
+ *
+ * @params
+ * * target - person being inserted into
+ * * from_init - we are performing initial setup in Initialize() after we've grabbed our organs and templates from species / persistence.
+ * this is not set in any other case.
+ *
+ * @return TRUE on success, FALSE on failure
*/
-/obj/item/organ/proc/is_any_biology_type(biology_types)
- switch(robotic)
- if(ORGAN_FLESH)
- return biology_types & BIOLOGY_TYPE_HUMAN
- if(ORGAN_ASSISTED)
- return biology_types & BIOLOGY_TYPE_HUMAN
- if(ORGAN_CRYSTAL)
- return biology_types & BIOLOGY_TYPE_CRYSTALLINE
- if(ORGAN_ROBOT)
- return biology_types & BIOLOGY_TYPE_SYNTH
- if(ORGAN_NANOFORM)
- return biology_types & BIOLOGY_TYPE_SYNTH
- if(ORGAN_LIFELIKE)
- return biology_types & BIOLOGY_TYPE_SYNTH
+/obj/item/organ/proc/insert(mob/living/carbon/target, from_init)
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
-//* Insert / Remove *//
+ #warn check for organ key
+
+/**
+ * Removes from a mob.
+ *
+ * @params
+ * * move_to - forceMove to this location. if null, we will not move out of our old container.
+ * * from_qdel - our owner and the organ are being qdeleted in the QDEL_LIST loop.
+ * this is not set in any other case, including on gib and set_species().
+ *
+ * @return TRUE on success, FALSE on failure
+ */
+/obj/item/organ/proc/remove(atom/move_to, from_qdel)
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
+
+ if(isnull(move_to) && (loc == null))
+ CRASH("no move_to destination and our loc was null. this can result in a memory leak if the organ is unpredictably referenced, and the calling proc fails to delete or move us.")
+
+ #warn impl
+
+/**
+ * Replaces into a mob.
+ *
+ * @params
+ * * target - person being inserted into
+ *
+ * @return TRUE on success, FALSE on failure
+ */
+/obj/item/organ/proc/replace(mob/living/carbon/target)
+ #warn impl
+
+#warn impl
/**
* called on being put into a mob
*
* @params
- * * owner - person being inserted into
- * * initializing - part of init for owner. set_species() counts as this too!
+ * * target - person being inserted into
+ * * replacing - called as part of a replacement
+ * * from_init - we are performing initial setup in Initialize() after we've grabbed our organs and templates from species / persistence.
+ * this is not set in any other case.
*/
-/obj/item/organ/proc/on_insert(mob/owner, initializing)
+#warn audit calls
+/obj/item/organ/proc/on_insert(mob/living/carbon/target, from_init)
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
+
+ register(target)
+
ensure_organ_actions_loaded()
- grant_organ_actions(owner)
+ grant_organ_actions(target)
+
+ //! LEGACY !//
+ handle_organ_mod_special(FALSE)
+ //! END !//
+
+/**
+ * called during a replace() operation
+ *
+ * * called before on_remove is called on the old
+ *
+ * @params
+ * * target - person being replaced into
+ * * replacing - (optional) old organ, if any
+ */
+/obj/item/organ/proc/before_replace(mob/living/carbon/target, obj/item/organ/replacing)
+ return
+
+/**
+ * called during a replace() operation
+ *
+ * * called after on_insert is called on the ourselves
+ *
+ * @params
+ * * target - person being replaced into
+ * * replacing - (optional) old organ, if any
+ */
+/obj/item/organ/proc/after_replace(mob/living/carbon/target, obj/item/organ/replacing)
+ return
/**
* called on being removed from a mob
*
* @params
- * * owner - person being removed from
+ * * target - person being removed from
+ * * replacing - called as part of a replacement
+ * * from_qdel - we and the organ are being qdeleted in the QDEL_LIST loop.
+ * this is not set in any other case, including on gib and set_species().
+ */
+#warn audit calls
+/obj/item/organ/proc/on_remove(mob/living/carbon/target, from_qdel)
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
+
+ revoke_organ_actions(target)
+
+ unregister(target)
+
+ //! LEGACY !//
+ handle_organ_mod_special(TRUE)
+ //! END !//
+
+/**
+ * Performs base registration.
+ *
+ * * Do not put custom behavior in here. This should only be implemented on base subtypes of /organ.
+ */
+/obj/item/organ/proc/register(mob/living/carbon/target)
+ CRASH("base registration unimplemented on [type]")
+
+/**
+ * Performs base unregistration.
+ *
+ * * Do not put custom behavior in here. This should only be implemented on base subtypes of /organ.
*/
-/obj/item/organ/proc/on_remove(mob/owner)
- revoke_organ_actions(owner)
+/obj/item/organ/proc/unregister(mob/living/carbon/target)
+ CRASH("base registration unimplemented on [type]")
diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm
index 70dc9c4f6aec..35225d584bab 100644
--- a/code/modules/organs/subtypes/machine.dm
+++ b/code/modules/organs/subtypes/machine.dm
@@ -27,6 +27,7 @@
return
+#warn this needs to be a /brain lol
// Used for an MMI or posibrain being installed into a human.
/obj/item/organ/internal/mmi_holder
name = "brain interface"
diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm
index 703be6a1edb9..3bcdaa14bc29 100644
--- a/code/modules/paperwork/paperplane.dm
+++ b/code/modules/paperwork/paperplane.dm
@@ -92,7 +92,7 @@
return
visible_message("\The [src] hits [H] in the eye!")
H.eye_blurry += 10
- var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/E = H.keyed_organs[ORGAN_KEY_EYES]
if(E)
E.take_damage(2.5)
H.emote("scream")
diff --git a/code/modules/preferences/preference_setup/general/03_body.dm b/code/modules/preferences/preference_setup/general/03_body.dm
index 9d1a93c7a97e..b21b6100201f 100644
--- a/code/modules/preferences/preference_setup/general/03_body.dm
+++ b/code/modules/preferences/preference_setup/general/03_body.dm
@@ -203,7 +203,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
continue
var/obj/item/organ/I = character.internal_organs_by_name[name]
if(istype(I, /obj/item/organ/internal/brain))
- var/obj/item/organ/external/E = character.get_organ(I.parent_organ)
+ var/obj/item/organ/external/E = character.legacy_organ_by_zone(I.parent_organ)
if(E.robotic < ORGAN_ASSISTED)
continue
if(I)
diff --git a/code/modules/projectiles/firing_pin.dm b/code/modules/projectiles/firing_pin.dm
index bc63a65de4f1..9fb793deeb7c 100644
--- a/code/modules/projectiles/firing_pin.dm
+++ b/code/modules/projectiles/firing_pin.dm
@@ -94,7 +94,7 @@
/obj/item/firing_pin/implant/pin_auth(mob/living/carbon/human/user)
if(user)
- for(var/obj/item/organ/external/E in user.organs)
+ for(var/obj/item/organ/external/E as anything in user.external_organs)
for(var/obj/item/implant/I in E.implants)
if(I.implanted)
if(istype(I,req_implant))
diff --git a/code/modules/projectiles/guns/ballistic/microbattery/medigun_cells.dm b/code/modules/projectiles/guns/ballistic/microbattery/medigun_cells.dm
index 5a71dff13438..29d367c1ab29 100644
--- a/code/modules/projectiles/guns/ballistic/microbattery/medigun_cells.dm
+++ b/code/modules/projectiles/guns/ballistic/microbattery/medigun_cells.dm
@@ -61,8 +61,7 @@
/obj/projectile/beam/medical_cell/stabilize/on_hit_legacy(var/mob/living/carbon/human/target)
if(istype(target, /mob/living/carbon/human))
target.adjustOxyLoss(-30)
- for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO))
- var/obj/item/organ/external/O = target.organs_by_name[name]
+ for(var/obj/item/organ/external/O in target.external_organs)
for (var/datum/wound/W as anything in O.wounds)
if (W.internal)
continue
@@ -153,8 +152,7 @@
/obj/projectile/beam/medical_cell/stabilize2/on_hit_legacy(var/mob/living/carbon/human/target)
if(istype(target, /mob/living/carbon/human))
target.adjustOxyLoss(-200)
- for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO))
- var/obj/item/organ/external/O = target.organs_by_name[name]
+ for(var/obj/item/organ/external/O in target.external_organs)
for (var/datum/wound/W as anything in O.wounds)
if(W.internal)
continue
diff --git a/code/modules/projectiles/projectile/subtypes/unsorted.dm b/code/modules/projectiles/projectile/subtypes/unsorted.dm
index d9b5882ed3e2..41eddb73efdb 100644
--- a/code/modules/projectiles/projectile/subtypes/unsorted.dm
+++ b/code/modules/projectiles/projectile/subtypes/unsorted.dm
@@ -257,7 +257,7 @@
var/mob/living/carbon/human/H = L
var/target_armor = H.legacy_mob_armor(def_zone, damage_flag)
- var/obj/item/organ/external/target_limb = H.get_organ(def_zone)
+ var/obj/item/organ/external/target_limb = H.legacy_organ_by_zone(def_zone)
var/armor_special = 0
diff --git a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Dispenser.dm
index f65c970acf9b..25dfb45eaf1c 100644
--- a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Dispenser.dm
+++ b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Dispenser.dm
@@ -121,7 +121,8 @@
return
/datum/reagent/ethanol/affect_ingest(mob/living/carbon/M, alien, removed)
- if(issmall(M)) removed *= 2
+ if(issmall(M))
+ removed *= 2
M.adjust_nutrition(nutriment_factor * removed)
M.adjust_hydration(hydration_factor * removed)
M.bloodstr.add_reagent("ethanol", removed * ABV)
@@ -135,7 +136,6 @@
if(halluci)
M.setHallucination(max(M.hallucination, halluci))
- return
/datum/reagent/ethanol/touch_obj(obj/O)
if(istype(O, /obj/item/paper))
@@ -221,7 +221,7 @@
if(!M.unacidable && removed > 0)
if(istype(M, /mob/living/carbon/human) && volume >= meltdose)
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(BP_HEAD)
if(affecting)
affecting.inflict_bodypart_damage(
burn = removed * power * 0.1,
diff --git a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Food-Drinks.dm
index 56c37118c323..91ead004851c 100644
--- a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Food-Drinks.dm
+++ b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Food-Drinks.dm
@@ -567,7 +567,7 @@
var/mob/living/carbon/human/H = M
if(!H.can_feel_pain())
return
- if(!H.internal_organs_by_name[O_EYES])
+ if(!H.keyed_organs[ORGAN_KEY_EYES])
eyes_covered = TRUE
safe_thing = "Lack of eyes"
if(H.head)
@@ -3323,14 +3323,6 @@
..()
if(. > 30)
M.adjustToxLoss(2 * removed)
- if(. > 60 && ishuman(M) && prob(5))
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/internal/heart/L = H.internal_organs_by_name[O_HEART]
- if (L && istype(L))
- if(. < 120)
- L.take_damage(10 * removed)
- else
- L.take_damage(100)
/datum/reagent/ethanol/red_mead
name = "Red Mead"
diff --git a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Medicine.dm
index cb52e4e473da..60453e18e8ef 100644
--- a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Medicine.dm
+++ b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Medicine.dm
@@ -40,7 +40,7 @@
M.eye_blurry = min(M.eye_blurry + wound_heal, 250)
if(ishuman(M))
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/external/O in H.bad_external_organs)//for-loop that covers all injured external organs
+ for(var/obj/item/organ/external/O in H.external_organs)//for-loop that covers all injured external organs
for(var/datum/wound/W as anything in O.wounds)//for-loop that covers all wounds in the organ we are currently looking at.
if(W.bleeding() || W.internal)//Checks if the wound is bleeding or internal
W.damage = max(W.damage - wound_heal, 0)//reduces the damage, and sets it to 0 if its lower than 0
@@ -216,7 +216,7 @@
M.remove_a_modifier_of_type(/datum/modifier/poisoned)//better chance to remove the poisoned effect
if(ishuman(M))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/internal/liver/L = H.internal_organs_by_name[O_LIVER]
+ var/obj/item/organ/internal/liver/L = H.legacy_organ_by_type(/obj/item/organ/internal/liver)
if(istype(L))
if(L.robotic >= ORGAN_ROBOT)
return
@@ -655,7 +655,7 @@
M.eye_blurry = max(M.eye_blurry - 5, 0)
if(ishuman(M))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/E = H.keyed_organs[ORGAN_KEY_EYES]
if(istype(E))
if(E.robotic >= ORGAN_ROBOT)
return
@@ -732,7 +732,7 @@
M.heal_organ_damage(3 * removed, 0) //Gives the bones a chance to set properly even without other meds
if(ishuman(M))
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/external/O in H.bad_external_organs)
+ for(var/obj/item/organ/external/O in H.external_organs)
if(O.status & ORGAN_BROKEN)
O.mend_fracture() //Only works if the bone won't rebreak, as usual
H.custom_pain("You feel a terrible agony tear through your bones!",60)
@@ -756,7 +756,7 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/wound_heal = removed * repair_strength
- for(var/obj/item/organ/external/O in H.bad_external_organs)
+ for(var/obj/item/organ/external/O in H.external_organs)
for(var/datum/wound/W as anything in O.wounds)
if(W.bleeding())
W.damage = max(W.damage - wound_heal, 0)
@@ -933,9 +933,11 @@
if(alien != IS_DIONA)
H.adjustToxLoss((30 / strength_mod) * removed)
- var/list/organtotal = list()
- organtotal |= H.organs
- organtotal |= H.internal_organs
+ var/list/obj/item/organ/organtotal = list()
+ for(var/obj/item/organ/organ as anything in H.get_organs())
+ if(organ.robotic >= ORGAN_ROBOT)
+ continue
+ organtotal += organ
for(var/obj/item/organ/I in organtotal) // Don't mess with robot bits, they don't reject.
if(I.robotic >= ORGAN_ROBOT)
@@ -978,9 +980,12 @@
if(alien != IS_SKRELL)
H.adjustToxLoss(20 * removed)
- var/list/organtotal = list()
- organtotal |= H.organs
- organtotal |= H.internal_organs
+
+ var/list/obj/item/organ/organtotal = list()
+ for(var/obj/item/organ/organ as anything in H.get_organs())
+ if(organ.robotic >= ORGAN_ROBOT)
+ continue
+ organtotal += organ
for(var/obj/item/organ/I in organtotal) // Don't mess with robot bits, they don't reject.
if(I.robotic >= ORGAN_ROBOT)
@@ -1181,7 +1186,7 @@
M.adjustBrainLoss(2 * removed)
M.nutrition = max(H.nutrition - 20, 0)
if(M.bruteloss >= 60 && M.toxloss >= 60 && M.brainloss >= 30) //Total Structural Failure. Limbs start splattering.
- var/obj/item/organ/external/O = pick(H.organs)
+ var/obj/item/organ/external/O = pick(H.external_organs)
if(prob(20) && !istype(O, /obj/item/organ/external/chest/unbreakable/slime) && !istype(O, /obj/item/organ/external/groin/unbreakable/slime))
to_chat(M, "You feel your [O] begin to dissolve, before it sloughs from your body.")
O.droplimb() //Splat.
@@ -1199,7 +1204,7 @@
//One of the levofloxacin side effects is 'spontaneous tendon rupture', which I'll immitate here. 1:1000 chance, so, pretty darn rare.
if(ishuman(M) && rand(1,10000) == 1)
- var/obj/item/organ/external/eo = pick(H.organs) //Misleading variable name, 'organs' is only external organs
+ var/obj/item/organ/external/eo = pick(H.external_organs) //Misleading variable name, 'organs' is only external organs
eo.fracture()
/datum/reagent/spacomycaze
diff --git a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Other.dm
index aa3fb658bdb7..806374379fc5 100644
--- a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Other.dm
+++ b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Other.dm
@@ -234,7 +234,7 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/wound_heal = 5
- for(var/obj/item/organ/external/O in H.bad_external_organs)
+ for(var/obj/item/organ/external/O in H.external_organs)
if(O.status & ORGAN_BROKEN)
O.mend_fracture() //Only works if the bone won't rebreak, as usual
for(var/datum/wound/W as anything in O.wounds)
diff --git a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Toxins.dm
index 4491514ddbbf..58695bfc1ed3 100644
--- a/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Toxins.dm
+++ b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Toxins.dm
@@ -700,7 +700,7 @@
H.shapeshifter_set_colour("#05FF9B") //They can still change their color.
if(backup_implants.len)
- var/obj/item/organ/external/torso = H.get_organ(BP_TORSO)
+ var/obj/item/organ/external/torso = H.legacy_organ_by_zone(BP_TORSO)
for(var/obj/item/implant/backup/BI in backup_implants)
BI.forceMove(torso)
torso.implants += BI
diff --git a/code/modules/reagents/chemistry/reagents/Chemistry-Topical.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Topical.dm
index 76fe7a487c03..13ce016453eb 100644
--- a/code/modules/reagents/chemistry/reagents/Chemistry-Topical.dm
+++ b/code/modules/reagents/chemistry/reagents/Chemistry-Topical.dm
@@ -82,7 +82,7 @@
M.ceiling_chemical_effect(CE_PAINKILLER, 40)
if(ishuman(M))
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/external/O in H.bad_external_organs)
+ for(var/obj/item/organ/external/O in H.external_organs)
for(var/datum/wound/W as anything in O.wounds)
if(!W.bleeding())
continue
@@ -139,7 +139,7 @@
/datum/reagent/topical/sterilaze/affect_touch(mob/living/carbon/M, alien, removed)
if(ishuman(M))
var/mob/living/carbon/human/H = M
- for(var/obj/item/organ/external/O in H.bad_external_organs)
+ for(var/obj/item/organ/external/O in H.external_organs)
for(var/datum/wound/W in O.wounds)
W.disinfected = 1
diff --git a/code/modules/reagents/items/hypospray.dm b/code/modules/reagents/items/hypospray.dm
index 66f3038ab18f..2d01f7d43e01 100644
--- a/code/modules/reagents/items/hypospray.dm
+++ b/code/modules/reagents/items/hypospray.dm
@@ -146,15 +146,15 @@
return CLICKCHAIN_DO_NOT_PROPAGATE
/obj/item/hypospray/proc/injection_checks(mob/target, mob/user, target_zone, speed_mult = 1, silent = FALSE)
- // todo: legacy cast, get organ/etc should be on mob level maybe.
- var/mob/living/L = target
+ // todo: legacy cast, we need simplemob handling.
+ var/mob/living/carbon/L = target
if(!istype(L))
user.action_feedback(SPAN_WARNING("[target] isn't injectable."), src)
return FALSE
if(!loaded?.reagents?.total_volume)
user.action_feedback(SPAN_WARNING("[src]'s vial is empty."), src)
return FALSE
- var/obj/item/organ/external/limb = L.get_organ(target_zone || BP_HEAD)
+ var/obj/item/organ/external/limb = L.legacy_organ_by_zone(target_zone || BP_HEAD)
if(isnull(limb))
user.action_feedback(SPAN_WARNING("[target] doesn't have that limb."), src)
return FALSE
@@ -167,7 +167,7 @@
inject_verb = "spray"
inject_message = "[user] starts to [inject_verb] [target] with \the [src]."
var/block_flags = NONE
- for(var/obj/item/I as anything in target.inventory.items_that_cover(limb.body_part_flags))
+ for(var/obj/item/I as anything in target.inventory.query_body_cover_items(limb.body_part_flags))
block_flags |= (I.clothing_flags & (CLOTHING_THICK_MATERIAL | CLOTHING_INJECTION_PORT))
// got all coverage, proceed.
var/delay = injection_time
diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm
index b3e376449830..4618aa190e3d 100644
--- a/code/modules/reagents/reagent_containers/borghydro.dm
+++ b/code/modules/reagents/reagent_containers/borghydro.dm
@@ -73,7 +73,7 @@
var/mob/living/carbon/human/H = L
if(istype(H))
- var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(!affected)
to_chat(user, "\The [H] is missing that limb!")
return
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 70066556c1fc..6f5317b464b5 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -37,7 +37,7 @@
var/mob/living/carbon/human/H = target
if(istype(H))
- var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(!affected)
to_chat(user, "\The [H] is missing that limb!")
return
diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm
index 3530d1e47df5..f449577988c4 100644
--- a/code/modules/reagents/reagent_containers/patch.dm
+++ b/code/modules/reagents/reagent_containers/patch.dm
@@ -46,7 +46,7 @@
if(target == L)
if(istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/H = target
- var/obj/item/organ/external/affecting = H.get_organ(check_zone(L.zone_sel.selecting))
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(check_zone(L.zone_sel.selecting))
if(!affecting)
to_chat(user, SPAN_WARNING("The limb is missing!"))
return
@@ -81,7 +81,7 @@
else if(istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/H = target
- var/obj/item/organ/external/affecting = H.get_organ(check_zone(L.zone_sel.selecting))
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(check_zone(L.zone_sel.selecting))
if(!affecting)
to_chat(user, SPAN_WARNING("The limb is missing!"))
return
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index fc1117b70ece..b831b60e205a 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -165,7 +165,7 @@
var/mob/living/carbon/human/H = target
var/obj/item/organ/external/affected
if(istype(H))
- affected = H.get_organ(user.zone_sel.selecting)
+ affected = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(!affected)
to_chat(user, "\The [H] is missing that limb!")
return
@@ -238,7 +238,7 @@
var/mob/living/carbon/human/H = target
var/target_zone = ran_zone(check_zone(user.zone_sel.selecting, target))
- var/obj/item/organ/external/affecting = H.get_organ(target_zone)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(target_zone)
if (!affecting || affecting.is_stump())
to_chat(user, "They are missing that limb!")
diff --git a/code/modules/research/designs/prosfab_designs.dm b/code/modules/research/designs/prosfab_designs.dm
index ef31ec733651..1b757468d715 100644
--- a/code/modules/research/designs/prosfab_designs.dm
+++ b/code/modules/research/designs/prosfab_designs.dm
@@ -59,13 +59,13 @@
var/mob/living/carbon/human/H = new(where,newspecies)
H.set_stat(DEAD)
H.gender = gender
- for(var/obj/item/organ/external/EO in H.organs)
+ for(var/obj/item/organ/external/EO as anything in H.external_organs)
if(EO.organ_tag == BP_TORSO || EO.organ_tag == BP_GROIN)
continue //Roboticizing a torso does all the children and wastes time, do it later
else
EO.remove_rejuv()
- for(var/obj/item/organ/external/O in H.organs)
+ for(var/obj/item/organ/external/O as anything in H.external_organs)
O.species = SScharacters.resolve_species_name(newspecies)
if(!(O.organ_tag in manf.parts)) // Make sure we're using an actually present icon.
diff --git a/code/modules/resleeving/infomorph.dm b/code/modules/resleeving/infomorph.dm
index ddf6d6a4d18f..bb5f2fce60b3 100644
--- a/code/modules/resleeving/infomorph.dm
+++ b/code/modules/resleeving/infomorph.dm
@@ -233,7 +233,7 @@ var/list/infomorph_emotions = list(
var/mob/holder = card.loc
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
- for(var/obj/item/organ/external/affecting in H.organs)
+ for(var/obj/item/organ/external/affecting as anything in H.external_organs)
if(card in affecting.implants)
affecting.inflict_bodypart_damage(
brute = rand(30, 50),
diff --git a/code/modules/species/outsider/replicant.dm b/code/modules/species/outsider/replicant.dm
index e7275b001979..44676ecc1bd5 100644
--- a/code/modules/species/outsider/replicant.dm
+++ b/code/modules/species/outsider/replicant.dm
@@ -52,19 +52,7 @@
/mob/living/carbon/human/proc/exit_vr,
)
- has_organ = list(
- O_HEART = /obj/item/organ/internal/heart/replicant/rage,
- O_LUNGS = /obj/item/organ/internal/lungs/replicant/mending,
- O_VOICE = /obj/item/organ/internal/voicebox/replicant,
- O_LIVER = /obj/item/organ/internal/liver/replicant,
- O_KIDNEYS = /obj/item/organ/internal/kidneys/replicant,
- O_BRAIN = /obj/item/organ/internal/brain/replicant,
- O_EYES = /obj/item/organ/internal/eyes/replicant,
- O_AREJECT = /obj/item/organ/internal/immunehub/replicant,
- O_VRLINK = /obj/item/organ/internal/brainmirror,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
- )
+ biology = /datum/biology/organic/replicant
/datum/species/shapeshifter/replicant/alpha
name = SPECIES_REPLICANT_ALPHA
@@ -89,20 +77,11 @@
/mob/living/carbon/human/proc/acidspit,
)
+ use_internal_organs = list(
+ )
has_organ = list(
- O_HEART = /obj/item/organ/internal/heart/replicant,
- O_LUNGS = /obj/item/organ/internal/lungs/replicant,
- O_VOICE = /obj/item/organ/internal/voicebox/replicant,
- O_LIVER = /obj/item/organ/internal/liver/replicant,
- O_KIDNEYS = /obj/item/organ/internal/kidneys/replicant,
- O_BRAIN = /obj/item/organ/internal/brain/replicant,
- O_EYES = /obj/item/organ/internal/eyes/replicant,
- O_AREJECT = /obj/item/organ/internal/immunehub/replicant,
- O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/replicant,
- O_ACID = /obj/item/organ/internal/xenos/acidgland/replicant,
- O_VRLINK = /obj/item/organ/internal/brainmirror,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine
+ O_PLASMA = /obj/item/organ/internal/xenomorph/plasmavessel/replicant,
+ O_ACID = /obj/item/organ/internal/xenomorph/acidgland/replicant,
)
/datum/species/shapeshifter/replicant/beta
@@ -118,19 +97,9 @@
LANGUAGE_ID_DIONA_HIVEMIND
)
+ use_internal_organs = list(
+ )
has_organ = list(
- O_HEART = /obj/item/organ/internal/heart/replicant/rage,
- O_LUNGS = /obj/item/organ/internal/lungs/replicant/mending,
- O_VOICE = /obj/item/organ/internal/voicebox/replicant,
- O_LIVER = /obj/item/organ/internal/liver/replicant,
- O_KIDNEYS = /obj/item/organ/internal/kidneys/replicant,
- O_BRAIN = /obj/item/organ/internal/brain/replicant/torso,
- O_EYES = /obj/item/organ/internal/eyes/replicant,
- O_AREJECT = /obj/item/organ/internal/immunehub/replicant,
- O_VENTC = /obj/item/organ/internal/metamorphgland/replicant,
- O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/replicant,
- O_RESIN = /obj/item/organ/internal/xenos/resinspinner/replicant,
- O_VRLINK = /obj/item/organ/internal/brainmirror,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
+ O_PLASMA = /obj/item/organ/internal/xenomorph/plasmavessel/replicant,
+ O_RESIN = /obj/item/organ/internal/xenomorph/resinspinner/replicant,
)
diff --git a/code/modules/species/outsider/shadow.dm b/code/modules/species/outsider/shadow.dm
index 8c7232beb200..981199cfc9fa 100644
--- a/code/modules/species/outsider/shadow.dm
+++ b/code/modules/species/outsider/shadow.dm
@@ -16,7 +16,6 @@
light_dam = 2
vision_innate = /datum/vision/baseline/species_tier_3
- has_organ = list()
siemens_coefficient = 0
vision_organ = O_EYES
@@ -34,6 +33,8 @@
genders = list(NEUTER)
+ biology = /datum/biology/simple/pretend_organic
+
unarmed_types = list(
/datum/unarmed_attack/claws/strong,
/datum/unarmed_attack/bite/sharp,
diff --git a/code/modules/species/outsider/skeleton.dm b/code/modules/species/outsider/skeleton.dm
index bf0e50609144..173dce17f4a3 100644
--- a/code/modules/species/outsider/skeleton.dm
+++ b/code/modules/species/outsider/skeleton.dm
@@ -44,8 +44,6 @@
death_message = "falls over and stops moving!"
knockout_message = "falls over and stops moving!"
- has_organ = list()
-
warning_low_pressure = 50
hazard_low_pressure = -1
@@ -59,6 +57,8 @@
body_temperature = T20C
+ biology = /datum/biology/simple/pretend_organic
+
unarmed_types = list( //Bones are pointy, fight me.
/datum/unarmed_attack/claws/strong,
/datum/unarmed_attack/bite/sharp,
diff --git a/code/modules/species/outsider/vox.dm b/code/modules/species/outsider/vox.dm
index 847423b80fa6..3ce16a965306 100644
--- a/code/modules/species/outsider/vox.dm
+++ b/code/modules/species/outsider/vox.dm
@@ -67,21 +67,6 @@
reagent_tag = IS_VOX
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/vox),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
- )
-
-
has_organ = list(
O_HEART = /obj/item/organ/internal/heart/vox,
O_LUNGS = /obj/item/organ/internal/lungs/vox,
diff --git a/code/modules/species/promethean/promethean.dm b/code/modules/species/promethean/promethean.dm
index 5f4f719f95a0..e7d638b07819 100644
--- a/code/modules/species/promethean/promethean.dm
+++ b/code/modules/species/promethean/promethean.dm
@@ -1,5 +1,3 @@
-var/datum/species/shapeshifter/promethean/prometheans
-
// Species definition follows.
/datum/species/shapeshifter/promethean
name = SPECIES_PROMETHEAN
@@ -99,6 +97,7 @@ var/datum/species/shapeshifter/promethean/prometheans
dispersed_eyes = TRUE
+ biology = /datum/biology/organic/promethean
has_limbs = list(
BP_TORSO = list("path" = /obj/item/organ/external/chest/unbreakable/slime),
BP_GROIN = list("path" = /obj/item/organ/external/groin/unbreakable/slime),
@@ -149,10 +148,6 @@ var/datum/species/shapeshifter/promethean/prometheans
heal_rate = 0.35
trashcan = TRUE //They have goopy bodies. They can just dissolve things within them.
-/datum/species/shapeshifter/promethean/New()
- ..()
- prometheans = src
-
/datum/species/shapeshifter/promethean/equip_survival_gear(mob/living/carbon/human/H)
var/boxtype = pick(list(
/obj/item/storage/toolbox/lunchbox,
diff --git a/code/modules/species/protean/protean.dm b/code/modules/species/protean/protean.dm
index b0840303649c..6dfed19bc60f 100644
--- a/code/modules/species/protean/protean.dm
+++ b/code/modules/species/protean/protean.dm
@@ -17,7 +17,7 @@
death_message = "rapidly loses cohesion, dissolving into a cloud of gray dust..."
knockout_message = "collapses inwards, forming a disordered puddle of gray goo."
remains_type = /obj/effect/debris/cleanable/ash
- mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/protean
+ intrinsic_physiology_modifier = /datum/physiology_modifier/intrinsic/species/protean
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) // Regular human attack verbs are enough.
@@ -208,7 +208,7 @@
H.gib()
/datum/species/protean/proc/getActualDamage(mob/living/carbon/human/H)
- var/obj/item/organ/external/E = H.get_organ(BP_TORSO)
+ var/obj/item/organ/external/E = H.legacy_organ_by_zone(BP_TORSO)
return E.brute_dam + E.burn_dam
/datum/species/protean/handle_environment_special(mob/living/carbon/human/H, datum/gas_mixture/environment, dt)
@@ -296,8 +296,8 @@
..()
var/dt = 2 // put it on param sometime but for now assume 2
var/mob/living/carbon/human/H = holder
- var/obj/item/organ/external/E = H.get_organ(BP_TORSO)
- var/obj/item/organ/external/HE = H.get_organ(BP_HEAD) // Head for disfigurement
+ var/obj/item/organ/external/E = H.legacy_organ_by_zone(BP_TORSO)
+ var/obj/item/organ/external/HE = H.legacy_organ_by_zone(BP_HEAD) // Head for disfigurement
var/heal = 1 * dt
var/brute_heal_left = max(0, heal - E.brute_dam)
var/burn_heal_left = max(0, heal - E.burn_dam)
diff --git a/code/modules/species/protean/protean_blob.dm b/code/modules/species/protean/protean_blob.dm
index 2a6a13850edb..9e3d75bcac49 100644
--- a/code/modules/species/protean/protean_blob.dm
+++ b/code/modules/species/protean/protean_blob.dm
@@ -106,7 +106,7 @@
if(humanform)
//Set the max
maxHealth = humanform.getMaxHealth() + 100 // +100 for crit threshold so you don't die from trying to blob to heal, ironically
- var/obj/item/organ/external/E = humanform.get_organ(BP_TORSO)
+ var/obj/item/organ/external/E = humanform.legacy_organ_by_zone(BP_TORSO)
//Set us to their health, but, human health ignores robolimbs so we do it 'the hard way'
health = maxHealth - E.brute_dam - E.burn_dam
movement_cooldown = 0.5 + max(0, (maxHealth - health) - 100) / 50
@@ -762,7 +762,7 @@
return
var/dt = 2 // put it on param sometime but for now assume 2
var/mob/living/carbon/human/H = holder
- var/obj/item/organ/external/E = H.get_organ(BP_TORSO)
+ var/obj/item/organ/external/E = H.legacy_organ_by_zone(BP_TORSO)
var/heal = 5 * dt
var/brute_heal_left = max(0, heal - E.brute_dam)
var/burn_heal_left = max(0, heal - E.burn_dam)
diff --git a/code/modules/species/protean/protean_powers.dm b/code/modules/species/protean/protean_powers.dm
index d128bb9e578e..fa2867c27adc 100644
--- a/code/modules/species/protean/protean_powers.dm
+++ b/code/modules/species/protean/protean_powers.dm
@@ -18,9 +18,12 @@
to_chat(src,"You don't have a working refactory module!")
return
-
- var/choice = input(src,"Pick the bodypart to change:", "Refactor - One Bodypart") as null|anything in species.has_limbs
- if(!choice)
+ var/list/datum/species_organ_entry/pick_entries_by_name = list()
+ for(var/datum/species_organ_entry/entry as anything in species.computed_external_organs)
+ pick_entries_by_name[entry.name] = entry
+ var/picked_choice = input(src,"Pick the bodypart to change:", "Refactor - One Bodypart") as null|anything in pick_entries_by_name
+ var/datum/species_organ_entry/picked_entry = pick_entries_by_name[picked_choice]
+ if(!picked_entry)
return
//Organ is missing, needs restoring
@@ -44,6 +47,7 @@
return
var/list/limblist = species.has_limbs[choice]
var/limbpath = limblist["path"]
+ #warn INSERT THIS PROPERLY
var/obj/item/organ/external/new_eo = new limbpath(src)
organs_by_name[choice] = new_eo
new_eo.robotize(synthetic ? synthetic.company : null) //Use the base we started with
@@ -79,9 +83,6 @@
visible_message("[src]'s [eo] subtly contorts.")
update_icons_body()
-////
-// Full Refactor
-////
/mob/living/carbon/human/proc/nano_regenerate() //fixed the proc, it used to leave active_regen true.
set name = "Ref - Whole Body"
set desc = "Allows you to regrow limbs and replace organs, given you have enough materials."
@@ -104,85 +105,83 @@
return
var/swap_not_rebuild = alert(src,"Do you want to rebuild, or reshape?","Rebuild or Reshape","Reshape","Cancel","Rebuild")
- if(swap_not_rebuild == "Cancel")
- return
- if(swap_not_rebuild == "Reshape")
- var/list/usable_manufacturers = list()
- for(var/company in GLOB.chargen_robolimbs)
- var/datum/robolimb/M = GLOB.chargen_robolimbs[company]
- if(!(BP_TORSO in M.parts))
- continue
- if(impersonate_bodytype_legacy in M.species_cannot_use)
- continue
- if(M.whitelisted_to && !(ckey in M.whitelisted_to))
- continue
- usable_manufacturers[company] = M
- if(!usable_manufacturers.len)
- return
- var/manu_choice = input(src, "Which manufacturer do you wish to mimic?", "Manufacturer") as null|anything in usable_manufacturers
-
- if(!manu_choice)
- return //Changed mind
- if(!organs_by_name[BP_TORSO])
- return //Ain't got a torso!
-
- var/obj/item/organ/external/torso = organs_by_name[BP_TORSO]
- to_chat(src, "Remain still while the process takes place! It will take 5 seconds.")
- visible_message("[src]'s form collapses into an amorphous blob of black ichor...")
-
- var/mob/living/simple_mob/protean_blob/blob = nano_intoblob()
- active_regen = TRUE
- if(do_self(blob, 5 SECONDS, DO_AFTER_IGNORE_ACTIVE_ITEM | DO_AFTER_IGNORE_MOVEMENT, NONE))
- synthetic = usable_manufacturers[manu_choice]
- torso.robotize(manu_choice) //Will cascade to all other organs.
- regenerate_icons()
- visible_message("[src]'s form reshapes into a new one...")
- active_regen = FALSE
- nano_outofblob(blob)
- return
-
- //Not enough resources (AND spends the resources, should be the last check)
- if(refactory.get_stored_material(MAT_STEEL) < min(10000, refactory.max_storage))
- to_chat(src, "You need to be maxed out on normal metal to do this!")
- return
+ switch(swap_not_rebuild)
+ if("Cancel")
+ if("Reshape")
+ var/list/usable_manufacturers = list()
+ for(var/company in GLOB.chargen_robolimbs)
+ var/datum/robolimb/M = GLOB.chargen_robolimbs[company]
+ if(!(BP_TORSO in M.parts))
+ continue
+ if(impersonate_bodytype_legacy in M.species_cannot_use)
+ continue
+ if(M.whitelisted_to && !(ckey in M.whitelisted_to))
+ continue
+ usable_manufacturers[company] = M
+ if(!usable_manufacturers.len)
+ return
+ var/manu_choice = input(src, "Which manufacturer do you wish to mimic?", "Manufacturer") as null|anything in usable_manufacturers
- var/delay_length = round(active_regen_delay * species.active_regen_mult)
- to_chat(src, "Remain still while the process takes place! It will take [delay_length/10] seconds.")
- visible_message("[src]'s form begins to shift and ripple as if made of oil...")
- active_regen = TRUE
+ if(!manu_choice)
+ return //Changed mind
+ if(!organs_by_name[BP_TORSO])
+ return //Ain't got a torso!
- var/mob/living/simple_mob/protean_blob/blob = nano_intoblob()
- if(do_self(blob, 5 SECONDS, DO_AFTER_IGNORE_ACTIVE_ITEM | DO_AFTER_IGNORE_MOVEMENT, NONE))
- if(stat != DEAD && refactory)
+ var/obj/item/organ/external/torso = organs_by_name[BP_TORSO]
+ to_chat(src, "Remain still while the process takes place! It will take 5 seconds.")
+ visible_message("[src]'s form collapses into an amorphous blob of black ichor...")
+
+ var/mob/living/simple_mob/protean_blob/blob = nano_intoblob()
+ active_regen = TRUE
+ if(do_self(blob, 5 SECONDS, DO_AFTER_IGNORE_ACTIVE_ITEM | DO_AFTER_IGNORE_MOVEMENT, NONE))
+ synthetic = usable_manufacturers[manu_choice]
+ torso.robotize(manu_choice) //Will cascade to all other organs.
+ regenerate_icons()
+ visible_message("[src]'s form reshapes into a new one...")
+ active_regen = FALSE
+ nano_outofblob(blob)
+ if("Rebuild")
//Not enough resources (AND spends the resources, should be the last check)
- if(!refactory.use_stored_material(MAT_STEEL,refactory.max_storage))
+ if(refactory.get_stored_material(MAT_STEEL) < min(10000, refactory.max_storage))
to_chat(src, "You need to be maxed out on normal metal to do this!")
return
- var/list/holder = refactory.stored_materials
- species.create_organs(src)
- var/obj/item/organ/external/torso = organs_by_name[BP_TORSO]
- torso.robotize() //synthetic wasn't defined here.
- LAZYCLEARLIST(blood_DNA)
- LAZYCLEARLIST(feet_blood_DNA)
- blood_color = null
- feet_blood_color = null
- regenerate_icons() //Probably worth it, yeah.
- var/obj/item/organ/internal/nano/refactory/new_refactory = locate() in internal_organs
- if(!new_refactory)
- log_debug(SPAN_DEBUGWARNING("[src] protean-regen'd but lacked a refactory when done."))
- else
- new_refactory.stored_materials = holder
- to_chat(src, "Your refactoring is complete.") //Guarantees the message shows no matter how bad the timing.
- to_chat(blob, "Your refactoring is complete!")
- else
- to_chat(src, "Your refactoring has failed.")
- to_chat(blob, "Your refactoring has failed!")
- else
- to_chat(src, "Your refactoring is interrupted.")
- to_chat(blob, "Your refactoring is interrupted!")
- active_regen = FALSE
- nano_outofblob()
+ var/delay_length = round(active_regen_delay * species.active_regen_mult)
+ to_chat(src, "Remain still while the process takes place! It will take [delay_length/10] seconds.")
+ visible_message("[src]'s form begins to shift and ripple as if made of oil...")
+ active_regen = TRUE
+
+ var/mob/living/simple_mob/protean_blob/blob = nano_intoblob()
+ if(do_self(blob, 5 SECONDS, DO_AFTER_IGNORE_ACTIVE_ITEM | DO_AFTER_IGNORE_MOVEMENT, NONE))
+ if(stat != DEAD && refactory)
+ //Not enough resources (AND spends the resources, should be the last check)
+ if(!refactory.use_stored_material(MAT_STEEL,refactory.max_storage))
+ to_chat(src, "You need to be maxed out on normal metal to do this!")
+ return
+ var/list/holder = refactory.stored_materials
+ species.create_organs(src)
+ var/obj/item/organ/external/torso = organs_by_name[BP_TORSO]
+ torso.robotize() //synthetic wasn't defined here.
+ LAZYCLEARLIST(blood_DNA)
+ LAZYCLEARLIST(feet_blood_DNA)
+ blood_color = null
+ feet_blood_color = null
+ regenerate_icons() //Probably worth it, yeah.
+ var/obj/item/organ/internal/nano/refactory/new_refactory = locate() in internal_organs
+ if(!new_refactory)
+ log_debug(SPAN_DEBUGWARNING("[src] protean-regen'd but lacked a refactory when done."))
+ else
+ new_refactory.stored_materials = holder
+ to_chat(src, "Your refactoring is complete.") //Guarantees the message shows no matter how bad the timing.
+ to_chat(blob, "Your refactoring is complete!")
+ else
+ to_chat(src, "Your refactoring has failed.")
+ to_chat(blob, "Your refactoring has failed!")
+ else
+ to_chat(src, "Your refactoring is interrupted.")
+ to_chat(blob, "Your refactoring is interrupted!")
+ active_regen = FALSE
+ nano_outofblob()
////
// Storing metal
@@ -357,9 +356,7 @@
return humanform.nano_get_refactory()
/mob/living/carbon/human/nano_get_refactory()
- return ..(locate(/obj/item/organ/internal/nano/refactory) in internal_organs)
-
-
+ return ..(legacy_organ_by_type(/obj/item/organ/internal/nano/refactory))
/// /// /// Ability objects for stat panel
/obj/effect/protean_ability
diff --git a/code/modules/species/shadekin/shadekin-organs.dm b/code/modules/species/shadekin/shadekin-organs.dm
new file mode 100644
index 000000000000..b390246d58d3
--- /dev/null
+++ b/code/modules/species/shadekin/shadekin-organs.dm
@@ -0,0 +1,63 @@
+/obj/item/organ/internal/shadekin
+ abstract_type = /obj/item/organ/internal/shadekin
+
+/datum/action/organ_action/shadekin_storage
+ name = "Access Storage"
+ desc = "Access your dimensional pocket."
+
+/datum/object_system/storage/shadekin
+ max_single_weight_class = WEIGHT_CLASS_SMALL
+ max_items = 7
+
+/**
+ * Shadekin powers come from here.
+ */
+/obj/item/organ/internal/shadekin/dimensional_cluster
+ name = "transient-plane cluster"
+ desc = {"
+ A strange network reminiscent of the lymphatic systems in mammals. It stretches across the
+ body of its host and allows them access to another plane.
+ "}
+ organ_key = ORGAN_KEY_SHADEKIN_DIMENSIONAL_CLUSTER
+
+ var/dark_energy = 100
+ var/max_dark_energy = 100
+ var/dark_energy_infinite = FALSE
+
+ organ_actions = list(
+ /datum/action/organ_action/shadekin_storage,
+ )
+
+/obj/item/organ/internal/shadekin/dimensional_cluster/Initialize(mapload)
+ . = ..()
+ obj_storage = new /datum/object_system/storage/shadekin(src)
+ obj_storage.indirect(src)
+
+/obj/item/organ/internal/shadekin/dimensional_cluster/on_insert(mob/owner, initializing)
+ . = ..()
+ RegisterSignal(owner, COMSIG_ATOM_REACHABILITY_DIRECTACCESS, PROC_REF(handle_storage_reachability))
+
+/obj/item/organ/internal/shadekin/dimensional_cluster/on_remove(mob/owner)
+ . = ..()
+ UnregisterSignal(owner, COMSIG_ATOM_REACHABILITY_DIRECTACCESS)
+
+/obj/item/organ/internal/shadekin/dimensional_cluster/proc/handle_storage_reachability(atom/source, list/direct_access)
+ var/atom/movable/storage_indirection/indirection = locate() in contents
+ if(!indirection)
+ return
+ direct_access += indirection
+
+/obj/item/organ/internal/shadekin/dimensional_cluster/ui_action_click(datum/action/action, datum/event_args/actor/actor)
+ obj_storage.show(actor.performer)
+
+/obj/item/organ/internal/shadekin/dimensional_cluster/crewkin
+ dark_energy = 50
+ max_dark_energy = 50
+
+/obj/item/organ/internal/shadekin/dimensional_cluster/crewkin/damaged
+ dark_energy = 25
+ max_dark_energy = 25
+
+/obj/item/organ/internal/shadekin/dimensional_cluster/crewkin/heavilydamaged
+ dark_energy = 0
+ max_dark_energy = 0
diff --git a/code/modules/species/shadekin/shadekin.dm b/code/modules/species/shadekin/shadekin.dm
index bb75aba3f289..b40726939301 100644
--- a/code/modules/species/shadekin/shadekin.dm
+++ b/code/modules/species/shadekin/shadekin.dm
@@ -94,29 +94,15 @@
move_trail = /obj/effect/debris/cleanable/blood/tracks/paw
- has_organ = list(
- O_HEART = /obj/item/organ/internal/heart,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_BRAIN = /obj/item/organ/internal/brain/shadekin,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/vr/shadekin;
+ },
)
-
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/vr/shadekin),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ use_internal_organs = list(
+ ORGAN_KEY_SHADEKIN_DIMENSIONAL_CLUSTER = /datum/species_organ_entry{
+ override_type = /obj/item/organ/internal/shadekin/dimensional_cluster;
+ },
)
vision_innate = /datum/vision/baseline/species_tier_3/for_snowflake_ocs
@@ -208,35 +194,35 @@
update_shadekin_hud(H)
/datum/species/shadekin/proc/get_energy(mob/living/carbon/human/H)
- var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
+ var/obj/item/organ/internal/shadekin/dimensional_cluster/shade_organ = H.keyed_organs[ORGAN_KEY_SHADEKIN_DIMENSIONAL_CLUSTER]
if(!istype(shade_organ))
return FALSE
return shade_organ.dark_energy
/datum/species/shadekin/proc/get_max_energy(mob/living/carbon/human/H)
- var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
+ var/obj/item/organ/internal/shadekin/dimensional_cluster/shade_organ = H.keyed_organs[ORGAN_KEY_SHADEKIN_DIMENSIONAL_CLUSTER]
if(!istype(shade_organ))
return FALSE
return shade_organ.max_dark_energy
/datum/species/shadekin/proc/set_energy(mob/living/carbon/human/H, new_energy)
- var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
+ var/obj/item/organ/internal/shadekin/dimensional_cluster/shade_organ = H.keyed_organs[ORGAN_KEY_SHADEKIN_DIMENSIONAL_CLUSTER]
if(!istype(shade_organ))
return
shade_organ.dark_energy = clamp(new_energy, 0, get_max_energy(H))
/datum/species/shadekin/proc/set_max_energy(mob/living/carbon/human/H, new_max_energy)
- var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
+ var/obj/item/organ/internal/shadekin/dimensional_cluster/shade_organ = H.keyed_organs[ORGAN_KEY_SHADEKIN_DIMENSIONAL_CLUSTER]
if(!istype(shade_organ))
return FALSE
shade_organ.max_dark_energy = new_max_energy
/datum/species/shadekin/proc/check_infinite_energy(mob/living/carbon/human/H)
- var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
+ var/obj/item/organ/internal/shadekin/dimensional_cluster/shade_organ = H.keyed_organs[ORGAN_KEY_SHADEKIN_DIMENSIONAL_CLUSTER]
if(!istype(shade_organ))
return FALSE
diff --git a/code/modules/species/shadekin/shadekin_traits.dm b/code/modules/species/shadekin/shadekin_traits.dm
index 392f0a98c968..24d43a4a2c31 100644
--- a/code/modules/species/shadekin/shadekin_traits.dm
+++ b/code/modules/species/shadekin/shadekin_traits.dm
@@ -158,7 +158,7 @@
..()
if(user == target) //Prevent self attack to gain energy
return
- var/obj/item/organ/internal/brain/shadekin/shade_organ = user.internal_organs_by_name[O_BRAIN]
+ var/obj/item/organ/internal/shadekin/dimensional_cluster/shade_organ = user.internal_organs_by_name[O_BRAIN]
if(!istype(shade_organ))
return
shade_organ.dark_energy = clamp(shade_organ.dark_energy + attack_damage,0,shade_organ.max_dark_energy) //Convert Damage done to Energy Gained
diff --git a/code/modules/species/species-organs.dm b/code/modules/species/species-organs.dm
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm
index c94cfb4b646b..9e5fe22fdc09 100644
--- a/code/modules/species/species.dm
+++ b/code/modules/species/species.dm
@@ -50,9 +50,9 @@
//* Traits / Physiology *//
/// Intrinsic datum traits to apply to the mob
- var/list/mob_traits
+ var/list/intrinsic_datum_traits
/// physiology modifier to add - path or instance
- var/datum/physiology_modifier/mob_physiology_modifier
+ var/datum/physiology_modifier/intrinsic_physiology_modifier
//* Sprite Accessories *//
/// default sprite accessories for each slot; will render onto mobs if they don't have one specifically set.
@@ -119,6 +119,8 @@
//* Inventory *//
+ /// todo: make and have this use /datum/inventory_slot_tweak instead of an associated list
+ ///
/// Available inventory slots IDs
///
/// * associate to list for remapping; use INVENTORY_SLOT_REMAP_* keys
@@ -160,33 +162,57 @@
var/list/base_skin_colours
- //? Organs
- /// Determines the organs that the species spawns with and which required-organ checks are conducted.
- var/list/has_organ = list(
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_APPENDIX = /obj/item/organ/internal/appendix,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
- )
- var/list/has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
+ //* Biology & Organs *//
+
+ /// Our primary biology.
+ ///
+ /// * Our organs default to this biology.
+ /// * This is a typepath or instance.
+ /// * This can be overridden in certain cases
+ var/datum/biology/biology
+ #warn impl
+ /// Our default limbs.
+ ///
+ /// Accepts a list of:
+ /// * External bodypart organ keys without associations
+ /// * External bodypart organ keys associated to a /datum/species_organ_entry
+ var/list/has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD,
+ ORGAN_KEY_EXT_CHEST,
+ ORGAN_KEY_EXT_GROIN,
+ ORGAN_KEY_EXT_LEFT_ARM,
+ ORGAN_KEY_EXT_LEFT_HAND,
+ ORGAN_KEY_EXT_RIGHT_ARM,
+ ORGAN_KEY_EXT_RIGHT_HAND,
+ ORGAN_KEY_EXT_LEFT_LEG,
+ ORGAN_KEY_EXT_LEFT_FOOT,
+ ORGAN_KEY_EXT_RIGHT_LEG,
+ ORGAN_KEY_EXT_RIGHT_FOOT,
)
+ /// Our internal organ overrides.
+ ///
+ /// * `ORGAN_KEY_BRAIN` is implicit and can never be omitted.
+ ///
+ /// Inherits:
+ /// * Our default biology's `default_internal_organ_keys`.
+ ///
+ /// Accepts a list of:
+ /// * Organ key associated to an ORGAN_DEFAULT_* value.
+ /// * Organ key without association to include something not included by default with the biology
+ /// * Organ key associated to a /datum/species_organ_entry value.
+ var/list/use_internal_organs = list()
+ /// Add certain unkeyed internal organs.
+ ///
+ /// Accepts a list of:
+ /// * /datum/species_organ_entry values.
+ var/list/add_internal_organs = list()
+ /// Our resultant limbs.
+ ///
+ /// * Automatically generated to be a list of /datum/species_organ_entry's
+ var/tmp/list/computed_external_organs
+ ///
+ /// * Automatically generated to be a list of /datum/species_organ_entry's
+ var/tmp/list/computed_internal_organs
//? Speech
/// Part of icon_state to use for speech bubbles when talking. See talk.dmi for available icons.
@@ -572,8 +598,8 @@
H.maxHealth = total_health
- if(!isnull(mob_physiology_modifier))
- H.add_physiology_modifier(mob_physiology_modifier)
+ if(!isnull(intrinsic_physiology_modifier))
+ H.add_physiology_modifier(intrinsic_physiology_modifier)
add_inherent_verbs(H)
@@ -581,7 +607,7 @@
var/datum/trait/T = all_traits[name]
T.apply(src, H)
- for(var/trait in mob_traits)
+ for(var/trait in intrinsic_datum_traits)
ADD_TRAIT(H, trait, SPECIES_TRAIT)
for(var/datum/ability/ability as anything in abilities)
@@ -604,14 +630,14 @@
remove_inherent_verbs(H)
H.holder_type = null
- if(!isnull(mob_physiology_modifier))
- H.remove_physiology_modifier(mob_physiology_modifier)
+ if(!isnull(intrinsic_physiology_modifier))
+ H.remove_physiology_modifier(intrinsic_physiology_modifier)
for(var/name in traits)
var/datum/trait/T = all_traits[name]
T.remove(src, H)
- for(var/trait in mob_traits)
+ for(var/trait in intrinsic_datum_traits)
REMOVE_TRAIT(H, trait, SPECIES_TRAIT)
for(var/datum/ability/ability as anything in abilities)
@@ -675,6 +701,48 @@ GLOBAL_LIST_INIT(species_oxygen_tank_by_gas, list(
else
H.equip_to_slot_or_del(box, /datum/inventory_slot/abstract/put_in_backpack, INV_OP_FORCE | INV_OP_SILENT)
+#warn audit calls
+/**
+ * Creates default organs in a human.
+ *
+ * todo: target should be casted to carbon, not human
+ *
+ * @params
+ * * target - The carbon target.
+ * * patch_incompatible - Replace existing organs that aren't suitable.
+ * * reset_everything - Destroy all existing organs if they exist. Implies `patch_incompatible`
+ * * legacy_delete_nif - Deletes their NIF.
+ */
+/datum/species/proc/create_organs(mob/living/carbon/human/target, patch_incompatible = TRUE, reset_everything = FALSE, legacy_delete_nif)
+ //! LEGACY !//
+ target.mob_size = mob_size
+ var/obj/item/nif/our_nif = target.nif
+ if(target.nif)
+ target.nif.unimplant(H)
+ //! END !//
+
+ #warn replacement?
+
+ var/list/obj/item/organ/existing_organs = target.get_organs()
+ if(reset_everything)
+ else
+
+ //! LEGACY !//
+ if(our_nif)
+ if(legacy_delete_nif)
+ qdel(our_nif)
+ else
+ our_nif.quick_implant(target)
+ if(base_color)
+ target.r_skin = hex2num(copytext(base_color,2,4))
+ target.g_skin = hex2num(copytext(base_color,4,6))
+ target.b_skin = hex2num(copytext(base_color,6,8))
+ else
+ target.r_skin = 0
+ target.g_skin = 0
+ target.b_skin = 0
+ //! END !//
+
/**
* called to ensure organs are consistent with our species's
* this is a destructive operation and will erase old organs!
@@ -682,11 +750,6 @@ GLOBAL_LIST_INIT(species_oxygen_tank_by_gas, list(
/datum/species/proc/create_organs(var/mob/living/carbon/human/H, var/delete_nif = FALSE) //Handles creation of mob organs.
H.mob_size = mob_size
- // if we have a NIF, unimplant it before it gets wiped
- var/obj/item/nif/our_nif = H.nif
- if(H.nif)
- H.nif.unimplant(H)
-
// store the markings for each limb we have so we can apply them to our new limbs
var/list/temporary_marking_store = list()
for(var/limb_type in has_limbs)
@@ -694,23 +757,10 @@ GLOBAL_LIST_INIT(species_oxygen_tank_by_gas, list(
if(existing_limb && istype(existing_limb))
temporary_marking_store[limb_type] = existing_limb.markings
- for(var/obj/item/organ/organ in H.contents)
- if((organ in H.organs) || (organ in H.internal_organs))
- qdel(organ)
-
- if(H.organs) H.organs.Cut()
- if(H.internal_organs) H.internal_organs.Cut()
- if(H.organs_by_name) H.organs_by_name.Cut()
- if(H.internal_organs_by_name) H.internal_organs_by_name.Cut()
-
- H.organs = list()
- H.internal_organs = list()
- H.organs_by_name = list()
- H.internal_organs_by_name = list()
-
for(var/limb_type in has_limbs)
var/list/organ_data = has_limbs[limb_type]
var/limb_path = organ_data["path"]
+ #warn INSERT THIS PROPERLY
var/obj/item/organ/O = new limb_path(H)
organ_data["descriptor"] = O.name
if(O.parent_organ)
@@ -725,28 +775,13 @@ GLOBAL_LIST_INIT(species_oxygen_tank_by_gas, list(
for(var/organ_tag in has_organ)
var/organ_type = has_organ[organ_tag]
+ #warn INSERT THIS PROPERLY
var/obj/item/organ/O = new organ_type(H,1)
if(organ_tag != O.organ_tag)
warning("[O.type] has a default organ tag \"[O.organ_tag]\" that differs from the species' organ tag \"[organ_tag]\". Updating organ_tag to match.")
O.organ_tag = organ_tag
H.internal_organs_by_name[organ_tag] = O
- // if we had a NIF, decide if we want to delete it, or put it back
- if(our_nif)
- if(delete_nif)
- QDEL_NULL(our_nif)
- else
- our_nif.quick_implant(H)
-
- if(base_color)
- H.r_skin = hex2num(copytext(base_color,2,4))
- H.g_skin = hex2num(copytext(base_color,4,6))
- H.b_skin = hex2num(copytext(base_color,6,8))
- else
- H.r_skin = 0
- H.g_skin = 0
- H.b_skin = 0
-
/**
* called to ensure blood is consistent
* this is a destructive proc and will erase incompatible blood.
@@ -833,10 +868,6 @@ GLOBAL_LIST_INIT(species_oxygen_tank_by_gas, list(
/datum/species/proc/handle_login_special(var/mob/living/carbon/human/H)
return
-// As above.
-/datum/species/proc/handle_logout_special(var/mob/living/carbon/human/H)
- return
-
// Builds the HUD using species-specific icons and usable slots.
/datum/species/proc/build_hud(var/mob/living/carbon/human/H)
return
diff --git a/code/modules/species/species_attack.dm b/code/modules/species/species_attack.dm
index 55d4e4955dcb..ed7f3b77e8d3 100644
--- a/code/modules/species/species_attack.dm
+++ b/code/modules/species/species_attack.dm
@@ -22,7 +22,7 @@
/datum/unarmed_attack/claws/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
var/skill = user.skills["combat"]
- var/obj/item/organ/external/affecting = target.get_organ(zone)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(zone)
var/datum/gender/T = GLOB.gender_datums[user.get_visible_gender()]
var/datum/gender/TT = GLOB.gender_datums[target.get_visible_gender()]
if(!skill) skill = 1
@@ -95,7 +95,7 @@
return damage
/datum/unarmed_attack/stomp/weak/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
- var/obj/item/organ/external/affecting = target.get_organ(zone)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(zone)
user.visible_message("[user] jumped up and down on \the [target]'s [affecting.name]!")
playsound(user.loc, attack_sound, 25, 1, -1)
@@ -106,7 +106,7 @@
damage_mode = DAMAGE_MODE_SHARP
/datum/unarmed_attack/bite/sharp/numbing/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
- var/obj/item/organ/external/affecting = target.get_organ(zone)
+ var/obj/item/organ/external/affecting = target.legacy_organ_by_zone(zone)
attack_damage = clamp(attack_damage, 1, 5)
if(target == user)
diff --git a/code/modules/species/species_organ_entry.dm b/code/modules/species/species_organ_entry.dm
new file mode 100644
index 000000000000..c85bc2346c7b
--- /dev/null
+++ b/code/modules/species/species_organ_entry.dm
@@ -0,0 +1,56 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * An entry for a species organ preset.
+ */
+/datum/species_organ_entry
+ //* Set *//
+
+ /// override biology
+ ///
+ /// overrides:
+ /// * species default biology
+ ///
+ /// accepts:
+ /// * typepath
+ /// * instance
+ var/datum/biology/override_biology
+ /// override typepath
+ ///
+ /// overrides:
+ /// * biology default organ
+ ///
+ /// accepts:
+ /// * typepath
+ var/override_type
+ /// physiology modifiers to apply to just that limb
+ ///
+ /// accepts (as a list of):
+ /// * typepaths
+ /// * instances
+ var/list/physiology_modifiers
+
+ //* Generated *//
+
+ /// our name.
+ ///
+ /// * if specified, this overrides normal organ name
+ /// * if not specified, this will be generated on species init for the species's resultant organ caches.
+ var/name
+
+/datum/species_organ_entry/clone(include_contents)
+ var/datum/species_organ_entry/cloning = new
+ #warn impl
+
+/datum/species_organ_entry/serialize()
+ . = list()
+ #warn impl
+
+/datum/species_organ_entry/deserialize(list/data)
+ #warn impl
+
+/datum/species_organ_entry/proc/create_organ() as /obj/item/organ
+
+
+#warn impl all
diff --git a/code/modules/species/species_shapeshift.dm b/code/modules/species/species_shapeshift.dm
index eeec0317d9e7..bffa2cabd254 100644
--- a/code/modules/species/species_shapeshift.dm
+++ b/code/modules/species/species_shapeshift.dm
@@ -82,7 +82,7 @@ var/list/wrapped_species_by_ref = list()
H.g_facial = H.g_skin
H.b_facial = H.b_skin
- for(var/obj/item/organ/external/E in H.organs)
+ for(var/obj/item/organ/external/E as anything in H.external_organs)
E.sync_colour_to_human(H)
// Verbs follow.
@@ -214,7 +214,7 @@ var/list/wrapped_species_by_ref = list()
g_facial = g_skin
b_facial = b_skin
- for(var/obj/item/organ/external/E in organs)
+ for(var/obj/item/organ/external/E in external_organs)
E.sync_colour_to_human(src)
regenerate_icons()
@@ -275,7 +275,7 @@ var/list/wrapped_species_by_ref = list()
g_eyes = new_color_rgb_list[2]
b_eyes = new_color_rgb_list[3]
// Now sync the organ's eye_colour list, if possible
- var/obj/item/organ/internal/eyes/eyes = internal_organs_by_name[O_EYES]
+ var/obj/item/organ/internal/eyes/eyes = keyed_organs[ORGAN_KEY_EYES]
if(istype(eyes))
eyes.update_colour()
@@ -504,7 +504,7 @@ var/list/wrapped_species_by_ref = list()
last_special = world.time + 50
- for(var/limb in src.organs)
+ for(var/limb in src.external_organs)
var/obj/item/organ/external/L = limb
L.transparent = !L.transparent
visible_message(SPAN_NOTICE("\The [src]'s internal composition seems to change."))
@@ -523,7 +523,7 @@ var/list/wrapped_species_by_ref = list()
var/new_transparency = input("Pick a number between 100 and 255, 255 being no transparency.", "Change Transparency") as num|null
if(new_transparency)
new_transparency = clamp(new_transparency,100,255)
- var/obj/item/organ/external/head/H = src.get_organ(BP_HEAD)
+ var/obj/item/organ/external/head/H = src.legacy_organ_by_zone(BP_HEAD)
H.hair_opacity = new_transparency
visible_message(SPAN_NOTICE("\The [src]'s \"hair\" composition seems to change."))
update_hair()
diff --git a/code/modules/species/station/adherent.dm b/code/modules/species/station/adherent.dm
index f55fd5a8f4ae..06dfec3f0661 100644
--- a/code/modules/species/station/adherent.dm
+++ b/code/modules/species/station/adherent.dm
@@ -9,15 +9,10 @@
built by an extinct culture. They are devoted to the memory of their long-dead creators, \
whose home system and burgeoning stellar empire was scoured to bedrock by a solar flare. \
Physically, they are large, floating squidlike machines made of a crystalline composite."
-// hidden_from_codex = FALSE
-// silent_steps = TRUE
meat_type = null
- // bone_material = null
- // skin_material = null
genders = list(PLURAL)
-// cyborg_noun = null
icon_template = 'icons/mob/species/adherent/template.dmi'
icobase = 'icons/mob/species/adherent/body.dmi'
@@ -28,12 +23,9 @@
blood_mask = 'icons/mob/species/adherent/blood_mask.dmi'
siemens_coefficient = 0
- //rarity_value = 6
min_age = 10000
max_age = 12000
- // antaghud_offset_y = 14
mob_size = MOB_LARGE
- // strength = STR_HIGH
has_glowing_eyes = TRUE
warning_low_pressure = 50
@@ -75,39 +67,10 @@
vision_innate = /datum/vision/baseline/species_tier_2
-/*
- available_cultural_info = list(
- TAG_CULTURE = list(
- CULTURE_ADHERENT
- ),
- TAG_HOMEWORLD = list(
- HOME_SYSTEM_ADHERENT,
- HOME_SYSTEM_ADHERENT_MOURNER
- ),
- TAG_FACTION = list(
- FACTION_ADHERENT_PRESERVERS,
- FACTION_ADHERENT_LOYALISTS,
- FACTION_ADHERENT_SEPARATISTS
- ),
- TAG_RELIGION = list(
- RELIGION_OTHER
- )
- )
-*/
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest/crystal),
- BP_GROIN = list("path" = /obj/item/organ/external/groin/crystal),
- BP_HEAD = list("path" = /obj/item/organ/external/head/crystal),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm/crystal),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/crystal),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand/crystal),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/crystal),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg/tendril),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/tendril/),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot/tendril/),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/tendril),
- )
+ biology = /datum/biology/crystalline/adherent
+ use_internal_organs = list(
+ )
has_organ = list(
O_BRAIN = /obj/item/organ/internal/brain/adherent,
O_CELL = /obj/item/organ/internal/cell/adherent,
diff --git a/code/modules/species/station/alraune.dm b/code/modules/species/station/alraune.dm
index 4666f4372fb1..9f3cbaf25ddf 100644
--- a/code/modules/species/station/alraune.dm
+++ b/code/modules/species/station/alraune.dm
@@ -1,6 +1,6 @@
/datum/physiology_modifier/intrinsic/species/alraune
- carry_strength_add = CARRY_STRENGTH_ADD_ALRAUNE
- carry_strength_factor = CARRY_FACTOR_MOD_ALRAUNE
+ g_carry_strength_add = CARRY_STRENGTH_ADD_ALRAUNE
+ g_carry_strength_factor = CARRY_FACTOR_MOD_ALRAUNE
/datum/species/alraune
uid = SPECIES_ID_ALRAUNE
diff --git a/code/modules/species/station/apidaen.dm b/code/modules/species/station/apidaen.dm
index 74e3317abc35..7dcf229c1d92 100644
--- a/code/modules/species/station/apidaen.dm
+++ b/code/modules/species/station/apidaen.dm
@@ -57,17 +57,10 @@
base_color = "#333333" // Blackish-gray
blood_color = "#D3C77C" // Internet says Bee haemolymph is a 'pale straw' color.
+ use_internal_organs = list(
+ )
has_organ = list(
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
O_SPLEEN = /obj/item/organ/internal/spleen/minor,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
O_HONEYSTOMACH = /obj/item/organ/internal/honey_stomach,
)
diff --git a/code/modules/species/station/custom_species.dm b/code/modules/species/station/custom_species.dm
index 2dfdcf2295d3..85e0db8384d0 100644
--- a/code/modules/species/station/custom_species.dm
+++ b/code/modules/species/station/custom_species.dm
@@ -25,20 +25,6 @@
vision_organ = O_EYES
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest, "descriptor" = "torso"),
- BP_GROIN = list("path" = /obj/item/organ/external/groin, "descriptor" = "groin"),
- BP_HEAD = list("path" = /obj/item/organ/external/head, "descriptor" = "head"),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm, "descriptor" = "left arm"),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right, "descriptor" = "right arm"),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg, "descriptor" = "left leg"),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right, "descriptor" = "right leg"),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand, "descriptor" = "left hand"),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right, "descriptor" = "right hand"),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot, "descriptor" = "left foot"),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right, "descriptor" = "right foot"),
- )
-
unarmed_types = list(
/datum/unarmed_attack/stomp,
/datum/unarmed_attack/kick,
@@ -67,33 +53,3 @@
/datum/species/custom/get_race_key(mob/living/carbon/human/H)
var/datum/species/real = SScharacters.resolve_species_name(base_species)
return real.real_race_key(H)
-
-// Stub species overrides for shoving trait abilities into
-
-//Called when face-down in the water or otherwise over their head.
-// Return: TRUE for able to breathe fine in water.
-/datum/species/custom/can_breathe_water()
- return ..()
-
-//Called during handle_environment in Life() ticks.
-// Return: Not used.
-/datum/species/custom/handle_environment_special(mob/living/carbon/human/H, datum/gas_mixture/environment, dt)
- return ..()
-
-//Called when spawning to equip them with special things.
-/datum/species/custom/equip_survival_gear(mob/living/carbon/human/H)
- /* Example, from Vox:
- H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(H), SLOT_ID_MASK)
- if(H.backbag == 1)
- H.equip_to_slot_or_del(new /obj/item/tank/vox(H), SLOT_ID_BACK)
- H.equip_to_slot_or_del(new /obj/item/storage/box/vox(H), /datum/inventory_slot/abstract/hand/right)
- H.internal = H.back
- else
- H.equip_to_slot_or_del(new /obj/item/tank/vox(H), /datum/inventory_slot/abstract/hand/right)
- H.equip_to_slot_or_del(new /obj/item/storage/box/vox(H.back), /datum/inventory_slot/abstract/put_in_backpack)
- H.internal = H.r_hand
- H.internal = locate(/obj/item/tank) in H.contents
- if(istype(H.internal,/obj/item/tank) && H.internals)
- H.internals.icon_state = "internal1"
- */
- return ..()
diff --git a/code/modules/species/station/diona.dm b/code/modules/species/station/diona.dm
index 18c736fc3852..e5876fcb2a1c 100644
--- a/code/modules/species/station/diona.dm
+++ b/code/modules/species/station/diona.dm
@@ -1,6 +1,6 @@
/datum/physiology_modifier/intrinsic/species/diona
- carry_strength_add = CARRY_STRENGTH_ADD_DIONA
- carry_strength_factor = CARRY_FACTOR_MOD_DIONA
+ g_carry_strength_add = CARRY_STRENGTH_ADD_DIONA
+ g_carry_strength_factor = CARRY_FACTOR_MOD_DIONA
/datum/species/diona
uid = SPECIES_ID_DIONA
@@ -8,7 +8,7 @@
name = SPECIES_DIONA
name_plural = "Dionaea"
//primitive_form = "Nymph"
- mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/diona
+ intrinsic_physiology_modifier = /datum/physiology_modifier/intrinsic/species/diona
icobase = 'icons/mob/species/diona/body.dmi'
deform = 'icons/mob/species/diona/deformed_body.dmi'
diff --git a/code/modules/species/station/phoronoids.dm b/code/modules/species/station/phoronoids.dm
index 3033d87f7d5c..56490847ff66 100644
--- a/code/modules/species/station/phoronoids.dm
+++ b/code/modules/species/station/phoronoids.dm
@@ -55,15 +55,8 @@
death_message = "falls over and stops moving!"
knockout_message = "falls over!"
- has_organ = list(
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_EYES = /obj/item/organ/internal/eyes,
- )
+ biology = /datum/biology/organic/phoronoid
+
vision_organ = O_EYES
cold_level_1 = 200
diff --git a/code/modules/species/station/standard/human.dm b/code/modules/species/station/standard/human.dm
index 104a403e2bb4..105fe8765577 100644
--- a/code/modules/species/station/standard/human.dm
+++ b/code/modules/species/station/standard/human.dm
@@ -1,6 +1,6 @@
/datum/physiology_modifier/intrinsic/species/human
- carry_strength_add = CARRY_STRENGTH_ADD_HUMAN
- carry_strength_factor = CARRY_FACTOR_MOD_HUMAN
+ g_carry_strength_add = CARRY_STRENGTH_ADD_HUMAN
+ g_carry_strength_factor = CARRY_FACTOR_MOD_HUMAN
/datum/species/human
id = SPECIES_ID_HUMAN
@@ -39,19 +39,6 @@
species_spawn_flags = SPECIES_SPAWN_CHARACTER
- has_organ = list(
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_APPENDIX = /obj/item/organ/internal/appendix,
- O_SPLEEN = /obj/item/organ/internal/spleen,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
- )
vision_organ = O_EYES
unarmed_types = list(
diff --git a/code/modules/species/station/standard/moth.dm b/code/modules/species/station/standard/moth.dm
index d64fd81d06dc..caa71da64e1d 100644
--- a/code/modules/species/station/standard/moth.dm
+++ b/code/modules/species/station/standard/moth.dm
@@ -121,20 +121,6 @@ GLOBAL_LIST_INIT(moth_lore_data, init_moth_lore())
primitive_form = null
species_appearance_flags = HAS_HAIR_COLOR | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
- has_organ = list(
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_APPENDIX = /obj/item/organ/internal/appendix,
- O_SPLEEN = /obj/item/organ/internal/spleen,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
- )
-
inherent_verbs = list(
/mob/living/carbon/human/proc/tie_hair,
/mob/living/carbon/human/proc/hide_horns,
@@ -165,14 +151,14 @@ GLOBAL_LIST_INIT(moth_lore_data, init_moth_lore())
value = CATALOGUER_REWARD_TRIVIAL
/datum/physiology_modifier/intrinsic/species/nepid/dark
- carry_strength_add = CARRY_STRENGTH_ADD_MOTH_DARK
- carry_strength_factor = CARRY_FACTOR_MOD_MOTH_DARK
+ g_carry_strength_add = CARRY_STRENGTH_ADD_MOTH_DARK
+ g_carry_strength_factor = CARRY_FACTOR_MOD_MOTH_DARK
/datum/species/moth/dark
name = SPECIES_MOTH_DARK
uid = SPECIES_ID_MOTH_DARK
species_spawn_flags = SPECIES_SPAWN_CHARACTER
- mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/nepid/dark
+ intrinsic_physiology_modifier = /datum/physiology_modifier/intrinsic/species/nepid/dark
// darksight, but weak to light
vision_innate = /datum/vision/baseline/species_tier_2
@@ -180,14 +166,14 @@ GLOBAL_LIST_INIT(moth_lore_data, init_moth_lore())
flash_mod = 1.2
/datum/physiology_modifier/intrinsic/species/nepid/light
- carry_strength_add = CARRY_STRENGTH_ADD_MOTH_LIGHT
- carry_strength_factor = CARRY_FACTOR_MOD_MOTH_LIGHT
+ g_carry_strength_add = CARRY_STRENGTH_ADD_MOTH_LIGHT
+ g_carry_strength_factor = CARRY_FACTOR_MOD_MOTH_LIGHT
/datum/species/moth/light
name = SPECIES_MOTH_LIGHT
uid = SPECIES_ID_MOTH_LIGHT
species_spawn_flags = SPECIES_SPAWN_CHARACTER
- mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/nepid/light
+ intrinsic_physiology_modifier = /datum/physiology_modifier/intrinsic/species/nepid/light
// hardy, but no darksight
vision_innate = /datum/vision/baseline/species_tier_0
diff --git a/code/modules/species/station/standard/naramadi.dm b/code/modules/species/station/standard/naramadi.dm
index cb9dada73b3d..58da4cea68ed 100644
--- a/code/modules/species/station/standard/naramadi.dm
+++ b/code/modules/species/station/standard/naramadi.dm
@@ -63,18 +63,10 @@
"Your overheated skin itches.",
)
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/vr/sergal),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/vr/sergal;
+ },
)
unarmed_types = list(
diff --git a/code/modules/species/station/standard/skrell.dm b/code/modules/species/station/standard/skrell.dm
index d9c235744c26..472dba0dd810 100644
--- a/code/modules/species/station/standard/skrell.dm
+++ b/code/modules/species/station/standard/skrell.dm
@@ -76,18 +76,10 @@
reagent_tag = null
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/skrell),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/skrell;
+ },
)
unarmed_types = list(
diff --git a/code/modules/species/station/standard/tajaran.dm b/code/modules/species/station/standard/tajaran.dm
index 1e8b8b3bb9cd..044a42f94259 100644
--- a/code/modules/species/station/standard/tajaran.dm
+++ b/code/modules/species/station/standard/tajaran.dm
@@ -1,6 +1,6 @@
/datum/physiology_modifier/intrinsic/species/tajaran
- carry_strength_add = CARRY_STRENGTH_ADD_TAJARAN
- carry_strength_factor = CARRY_FACTOR_MOD_TAJARAN
+ g_carry_strength_add = CARRY_STRENGTH_ADD_TAJARAN
+ g_carry_strength_factor = CARRY_FACTOR_MOD_TAJARAN
/datum/species/tajaran
uid = SPECIES_ID_TAJARAN
@@ -9,7 +9,7 @@
name_plural = "Tajaran"
category = "Tajaran"
default_bodytype = BODYTYPE_TAJARAN
- mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/tajaran
+ intrinsic_physiology_modifier = /datum/physiology_modifier/intrinsic/species/tajaran
icobase = 'icons/mob/species/tajaran/body_greyscale.dmi'
deform = 'icons/mob/species/tajaran/deformed_body_greyscale.dmi'
@@ -100,16 +100,8 @@
cold_discomfort_level = 275
- has_organ = list( //No appendix.
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
+ #warn todo: no appendix
+ use_internal_organs = list(
)
unarmed_types = list(
diff --git a/code/modules/species/station/standard/teshari.dm b/code/modules/species/station/standard/teshari.dm
index 2a387379d718..e3dbaec9652a 100644
--- a/code/modules/species/station/standard/teshari.dm
+++ b/code/modules/species/station/standard/teshari.dm
@@ -1,6 +1,6 @@
/datum/physiology_modifier/intrinsic/species/teshari
- carry_strength_add = CARRY_STRENGTH_ADD_TESHARI
- carry_strength_factor = CARRY_FACTOR_MOD_TESHARI
+ g_carry_strength_add = CARRY_STRENGTH_ADD_TESHARI
+ g_carry_strength_factor = CARRY_FACTOR_MOD_TESHARI
/datum/species/teshari
uid = SPECIES_ID_TESHARI
@@ -10,7 +10,7 @@
category = "Teshari"
name_plural = "Tesharii"
uid = SPECIES_ID_TESHARI
- mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/teshari
+ intrinsic_physiology_modifier = /datum/physiology_modifier/intrinsic/species/teshari
blurb = {"
A race of feathered raptors who developed alongside the Skrell, inhabiting
@@ -116,31 +116,34 @@
minimum_breath_pressure = 12 // Smaller, so needs less air
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/teshari),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand/teshari),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/teshari),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot/teshari),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/teshari),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/teshari;
+ },
+ ORGAN_KEY_EXT_CHEST,
+ ORGAN_KEY_EXT_GROIN,
+ ORGAN_KEY_EXT_LEFT_ARM,
+ ORGAN_KEY_EXT_LEFT_HAND = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/hand/left/teshari;
+ },
+ ORGAN_KEY_EXT_RIGHT_ARM,
+ ORGAN_KEY_EXT_RIGHT_HAND = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/hand/right/teshari;
+ },
+ ORGAN_KEY_EXT_LEFT_LEG,
+ ORGAN_KEY_EXT_LEFT_FOOT = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/foot/left/teshari;
+ },
+ ORGAN_KEY_EXT_RIGHT_LEG,
+ ORGAN_KEY_EXT_RIGHT_FOOT = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/foot/right/teshari;
+ },
)
- has_organ = list(
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
+ #warn no appendix
+ use_internal_organs = list(
)
+
vision_organ = O_EYES
unarmed_types = list(
@@ -168,10 +171,10 @@
)
var/static/list/flight_bodyparts = list(
- BP_L_ARM,
- BP_R_ARM,
- BP_L_HAND,
- BP_R_HAND,
+ ORGAN_KEY_EXT_LEFT_ARM,
+ ORGAN_KEY_EXT_RIGHT_ARM,
+ ORGAN_KEY_EXT_LEFT_HAND,
+ ORGAN_KEY_EXT_RIGHT_HAND,
)
var/static/list/flight_suit_blacklisted_types = list(
/obj/item/clothing/suit/space,
@@ -218,8 +221,8 @@
return ..()
// Do we have working wings?
- for(var/bp in flight_bodyparts)
- var/obj/item/organ/external/E = H.organs_by_name[bp]
+ for(var/key in flight_bodyparts)
+ var/obj/item/organ/external/E = H.keyed_organs[key]
if(!istype(E) || !E.is_usable() || E.is_broken() || E.is_stump())
if(!silent)
to_chat(H, SPAN_WARNING("You try to spread your wings to slow your fall, but they won't hold your weight!"))
diff --git a/code/modules/species/station/standard/unathi.dm b/code/modules/species/station/standard/unathi.dm
index fc7f8fcac053..08b494c855f3 100644
--- a/code/modules/species/station/standard/unathi.dm
+++ b/code/modules/species/station/standard/unathi.dm
@@ -1,6 +1,6 @@
/datum/physiology_modifier/intrinsic/species/unathi
- carry_strength_add = CARRY_STRENGTH_ADD_UNATHI
- carry_strength_factor = CARRY_FACTOR_MOD_UNATHI
+ g_carry_strength_add = CARRY_STRENGTH_ADD_UNATHI
+ g_carry_strength_factor = CARRY_FACTOR_MOD_UNATHI
/datum/species/unathi
uid = SPECIES_ID_UNATHI
@@ -88,30 +88,30 @@
move_trail = /obj/effect/debris/cleanable/blood/tracks/claw
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest/unathi),
- BP_GROIN = list("path" = /obj/item/organ/external/groin/unathi),
- BP_HEAD = list("path" = /obj/item/organ/external/head/unathi),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/unathi;
+ },
+ ORGAN_KEY_EXT_CHEST = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/chest/unathi;
+ },
+ ORGAN_KEY_EXT_GROIN = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/groin/unathi;
+ },
+ ORGAN_KEY_EXT_LEFT_ARM,
+ ORGAN_KEY_EXT_LEFT_HAND,
+ ORGAN_KEY_EXT_RIGHT_ARM,
+ ORGAN_KEY_EXT_RIGHT_HAND,
+ ORGAN_KEY_EXT_LEFT_LEG,
+ ORGAN_KEY_EXT_LEFT_FOOT,
+ ORGAN_KEY_EXT_RIGHT_LEG,
+ ORGAN_KEY_EXT_RIGHT_FOOT,
)
- //No kidneys or appendix
- has_organ = list(
- O_HEART = /obj/item/organ/internal/heart/unathi,
- O_LUNGS = /obj/item/organ/internal/lungs/unathi,
- O_LIVER = /obj/item/organ/internal/liver/unathi,
- O_BRAIN = /obj/item/organ/internal/brain/unathi,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach/unathi,
- O_INTESTINE = /obj/item/organ/internal/intestine/unathi,
+ #warn no kidneys, no appendix
+ use_internal_organs = list(
)
+
vision_organ = O_EYES
unarmed_types = list(
diff --git a/code/modules/species/station/standard/unathidigi.dm b/code/modules/species/station/standard/unathidigi.dm
index 91567adb686f..0bf01b4ba82b 100644
--- a/code/modules/species/station/standard/unathidigi.dm
+++ b/code/modules/species/station/standard/unathidigi.dm
@@ -18,16 +18,22 @@
While some unathi are plantigrade and almost resemble humans in their silhouette, others are more hulking; a digitigrade, beastial and alien creature.
"}
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest/unathi),
- BP_GROIN = list("path" = /obj/item/organ/external/groin/unathi),
- BP_HEAD = list("path" = /obj/item/organ/external/head/unathi/digi),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/unathi/digi;
+ },
+ ORGAN_KEY_EXT_CHEST = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/chest/unathi;
+ },
+ ORGAN_KEY_EXT_GROIN = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/groin/unathi;
+ },
+ ORGAN_KEY_EXT_LEFT_ARM,
+ ORGAN_KEY_EXT_LEFT_HAND,
+ ORGAN_KEY_EXT_RIGHT_ARM,
+ ORGAN_KEY_EXT_RIGHT_HAND,
+ ORGAN_KEY_EXT_LEFT_LEG,
+ ORGAN_KEY_EXT_LEFT_FOOT,
+ ORGAN_KEY_EXT_RIGHT_LEG,
+ ORGAN_KEY_EXT_RIGHT_FOOT,
)
diff --git a/code/modules/species/station/standard/zaddat.dm b/code/modules/species/station/standard/zaddat.dm
index 911a4a28ec52..94abdc211855 100644
--- a/code/modules/species/station/standard/zaddat.dm
+++ b/code/modules/species/station/standard/zaddat.dm
@@ -75,17 +75,10 @@
"Your antenna ache.",
)
- has_organ = list( //No appendix.
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine
+ #warn no appendix
+ use_internal_organs = list(
)
+
vision_organ = O_EYES
unarmed_types = list(
@@ -127,7 +120,7 @@
return
var/damageable = H.get_damageable_organs()
- var/covered = H.get_coverage()
+ var/covered = H.inventory.query_body_cover()
var/light_amount = 0 //how much light there is in the place, affects damage
if(isturf(H.loc)) //else, there's considered to be no light
@@ -135,6 +128,7 @@
light_amount = T.get_lumcount() * 5
- for(var/K in damageable)
- if(!(K in covered))
- H.apply_damage(light_amount/4, DAMAGE_TYPE_BURN, K, 0, 0, "Abnormal growths")
+ for(var/obj/item/organ/external/E in damageable)
+ if(E.body_part_flags & covered)
+ continue
+ H.apply_damage(light_amount/4, DAMAGE_TYPE_BURN, E, 0, 0, "Abnormal growths")
diff --git a/code/modules/species/station/station_special_abilities.dm b/code/modules/species/station/station_special_abilities.dm
index b7debb074b5d..0d73562d8f2f 100644
--- a/code/modules/species/station/station_special_abilities.dm
+++ b/code/modules/species/station/station_special_abilities.dm
@@ -772,7 +772,7 @@
return //Silent, because can_shred does messages.
//Let them pick any of the target's external organs
- var/obj/item/organ/external/T_ext = input(src,"What do you wish to severely damage?") as null|anything in T.organs //D for destroy.
+ var/obj/item/organ/external/T_ext = input(src,"What do you wish to severely damage?") as null|anything in T.external_organs //D for destroy.
if(!T_ext) //Picking something here is critical.
return
if(T_ext.vital)
diff --git a/code/modules/species/station/vasilissan.dm b/code/modules/species/station/vasilissan.dm
index 3b2552683bf1..9d841dff1fa2 100644
--- a/code/modules/species/station/vasilissan.dm
+++ b/code/modules/species/station/vasilissan.dm
@@ -35,18 +35,11 @@
/mob/living/carbon/human/proc/weave_structure,
)
- has_organ = list(
- O_HEART = /obj/item/organ/internal/heart,
- O_LUNGS = /obj/item/organ/internal/lungs,
- O_VOICE = /obj/item/organ/internal/voicebox,
- O_LIVER = /obj/item/organ/internal/liver,
- O_KIDNEYS = /obj/item/organ/internal/kidneys,
- O_SPLEEN = /obj/item/organ/internal/spleen/minor,
- O_BRAIN = /obj/item/organ/internal/brain,
- O_EYES = /obj/item/organ/internal/eyes,
- O_STOMACH = /obj/item/organ/internal/stomach,
- O_INTESTINE = /obj/item/organ/internal/intestine,
- O_WEAVER = /obj/item/organ/internal/weaver,
+ #warn no appendix
+ use_internal_organs = list(
+ )
+ add_internal_organs = list(
+ /obj/item/organ/internal/weaver,
)
max_age = 80
diff --git a/code/modules/species/station/werebeast.dm b/code/modules/species/station/werebeast.dm
index f9ceb2f44b91..3aefa11d89d9 100644
--- a/code/modules/species/station/werebeast.dm
+++ b/code/modules/species/station/werebeast.dm
@@ -54,18 +54,20 @@
"Your overheated skin itches.",
)
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/vr/werebeast),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/vr/werebeast;
+ },
+ ORGAN_KEY_EXT_CHEST,
+ ORGAN_KEY_EXT_GROIN,
+ ORGAN_KEY_EXT_LEFT_ARM,
+ ORGAN_KEY_EXT_LEFT_HAND,
+ ORGAN_KEY_EXT_RIGHT_ARM,
+ ORGAN_KEY_EXT_RIGHT_HAND,
+ ORGAN_KEY_EXT_LEFT_LEG,
+ ORGAN_KEY_EXT_LEFT_FOOT,
+ ORGAN_KEY_EXT_RIGHT_LEG,
+ ORGAN_KEY_EXT_RIGHT_FOOT,
)
unarmed_types = list(
diff --git a/code/modules/species/station/xenomorph_hybrids/hybrid_abilities.dm b/code/modules/species/station/xenomorph_hybrids/hybrid_abilities.dm
index 8013c24949ce..572052f746ee 100644
--- a/code/modules/species/station/xenomorph_hybrids/hybrid_abilities.dm
+++ b/code/modules/species/station/xenomorph_hybrids/hybrid_abilities.dm
@@ -22,18 +22,18 @@
return FALSE
if(plasma_cost > 0 && !check_plasmavessel(H))
return FALSE
- var/obj/item/organ/internal/xenos/plasmavessel/P = H.internal_organs_by_name[O_PLASMA]
+ var/obj/item/organ/internal/xenomorph/plasmavessel/P = H.keyed_organs[ORGAN_KEY_XENOMORPH_PLASMA_VESSEL]
if(istype(P) && P.stored_plasma < plasma_cost)
return FALSE
/datum/ability/species/xenomorph_hybrid/proc/check_plasmavessel(var/mob/living/carbon/human/H)
- var/obj/item/organ/internal/xenos/plasmavessel/P = H.internal_organs_by_name[O_PLASMA]
+ var/obj/item/organ/internal/xenomorph/plasmavessel/P = H.keyed_organs[ORGAN_KEY_XENOMORPH_PLASMA_VESSEL]
if(!istype(P))
return FALSE
return TRUE
/datum/ability/species/xenomorph_hybrid/proc/take_plasma(var/mob/living/carbon/human/H)
- var/obj/item/organ/internal/xenos/plasmavessel/P = H.internal_organs_by_name[O_PLASMA]
+ var/obj/item/organ/internal/xenomorph/plasmavessel/P = H.keyed_organs[ORGAN_KEY_XENOMORPH_PLASMA_VESSEL]
if(!istype(P))
return
P.adjust_plasma(-plasma_cost)
@@ -67,9 +67,3 @@
E.status &= ~ORGAN_BROKEN
to_chat(O, SPAN_NOTICEALIEN("You mend the bone in your [E]"))
return//fix one then stop, trigger again to mend more
-
-
-
-
-
-
diff --git a/code/modules/species/station/xenomorph_hybrids/hybrid_resin.dm b/code/modules/species/station/xenomorph_hybrids/hybrid_resin.dm
index 254fbb36bb21..290bbc469681 100644
--- a/code/modules/species/station/xenomorph_hybrids/hybrid_resin.dm
+++ b/code/modules/species/station/xenomorph_hybrids/hybrid_resin.dm
@@ -171,7 +171,7 @@
/obj/structure/alien/hybrid_resin/attack_hand(mob/user, datum/event_args/actor/clickchain/e_args)
if(iscarbon(user))
var/mob/living/carbon/C = user
- if(locate(/obj/item/organ/internal/xenos/hivenode) in C.internal_organs)
+ if(C.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
visible_message(SPAN_WARNING("[C] strokes the [name], and it melts away!"))
qdel(src)
return CLICKCHAIN_DID_SOMETHING | CLICKCHAIN_DO_NOT_PROPAGATE
diff --git a/code/modules/species/station/xenomorph_hybrids/xeno_hybrids.dm b/code/modules/species/station/xenomorph_hybrids/xeno_hybrids.dm
index 4f807228f546..871abb80760c 100644
--- a/code/modules/species/station/xenomorph_hybrids/xeno_hybrids.dm
+++ b/code/modules/species/station/xenomorph_hybrids/xeno_hybrids.dm
@@ -1,6 +1,6 @@
/datum/physiology_modifier/intrinsic/species/xenohybrid
- carry_strength_add = CARRY_STRENGTH_ADD_XENOHYBRID
- carry_strength_factor = CARRY_FACTOR_MOD_XENOHYBRID
+ g_carry_strength_add = CARRY_STRENGTH_ADD_XENOHYBRID
+ g_carry_strength_factor = CARRY_FACTOR_MOD_XENOHYBRID
/datum/species/xenohybrid
name = SPECIES_XENOHYBRID
@@ -8,7 +8,7 @@
uid = SPECIES_ID_XENOHYBRID
id = SPECIES_ID_XENOHYBRID
default_bodytype = BODYTYPE_XENOHYBRID
- mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/xenohybrid
+ intrinsic_physiology_modifier = /datum/physiology_modifier/intrinsic/species/xenohybrid
icobase = 'icons/mob/species/xenohybrid/body.dmi'
deform = 'icons/mob/species/xenohybrid/deformed_body.dmi'
@@ -101,10 +101,10 @@
O_LIVER = /obj/item/organ/internal/liver,
O_KIDNEYS = /obj/item/organ/internal/kidneys,
O_BRAIN = /obj/item/organ/internal/brain,
- O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/hunter,//Important for the xenomorph abilities, hunter to have a pretty small plasma capacity
+ O_PLASMA = /obj/item/organ/internal/xenomorph/plasmavessel/hunter,//Important for the xenomorph abilities, hunter to have a pretty small plasma capacity
O_STOMACH = /obj/item/organ/internal/stomach,
O_INTESTINE = /obj/item/organ/internal/intestine,
- O_RESIN = /obj/item/organ/internal/xenos/resinspinner/hybrid,
+ O_RESIN = /obj/item/organ/internal/xenomorph/resinspinner/hybrid,
)
vision_organ = O_BRAIN//Neomorphs have no (visible) Eyes, seeing without them should be possible.
diff --git a/code/modules/species/virtual_reality/opaque_form.dm b/code/modules/species/virtual_reality/opaque_form.dm
index 485005bee4a6..6b2027f03119 100644
--- a/code/modules/species/virtual_reality/opaque_form.dm
+++ b/code/modules/species/virtual_reality/opaque_form.dm
@@ -8,19 +8,7 @@
icobase = 'icons/mob/species/human/body.dmi'
deform = 'icons/mob/species/human/deformed_body.dmi'
species_appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
- )
+ biology = /datum/biology/organic
/datum/species/shapeshifter/promethean/avatar/unathi
uid = SPECIES_ID_VIRTUAL_REALITY_UNATHI
@@ -60,19 +48,6 @@
)
species_appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
- )
/datum/species/shapeshifter/promethean/avatar/skrell
uid = SPECIES_ID_VIRTUAL_REALITY_SKRELL
@@ -81,18 +56,10 @@
icobase = 'icons/mob/species/skrell/body_greyscale.dmi'
deform = 'icons/mob/species/skrell/deformed_body_greyscale.dmi'
species_appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/skrell),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/skrell;
+ },
)
/datum/species/shapeshifter/promethean/avatar/teshari
@@ -148,18 +115,10 @@
blood_mask = 'icons/mob/species/monkey/blood_mask.dmi'
fire_icon_state = "monkey"
species_appearance_flags = NONE
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/no_eyes),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/no_eyes;
+ },
)
/datum/species/shapeshifter/promethean/avatar/vox
@@ -169,18 +128,10 @@
icobase = 'icons/mob/species/vox/body.dmi'
deform = 'icons/mob/species/vox/deformed_body.dmi'
species_appearance_flags = HAS_EYE_COLOR | HAS_HAIR_COLOR
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head/vox),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
+ has_external_organs = list(
+ ORGAN_KEY_EXT_HEAD = /datum/species_organ_entry{
+ override_type = /obj/item/organ/external/head/vox;
+ },
)
/datum/species/shapeshifter/promethean/avatar/skeleton
@@ -190,16 +141,3 @@
icobase = 'icons/mob/species/human/skeleton.dmi'
deform = 'icons/mob/species/human/skeleton.dmi'
species_appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR
- has_limbs = list(
- BP_TORSO = list("path" = /obj/item/organ/external/chest),
- BP_GROIN = list("path" = /obj/item/organ/external/groin),
- BP_HEAD = list("path" = /obj/item/organ/external/head),
- BP_L_ARM = list("path" = /obj/item/organ/external/arm),
- BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
- BP_L_LEG = list("path" = /obj/item/organ/external/leg),
- BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
- BP_L_HAND = list("path" = /obj/item/organ/external/hand),
- BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
- BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
- BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right),
- )
diff --git a/code/modules/species/xenomorphs/alien_embryo.dm b/code/modules/species/xenomorphs/alien_embryo.dm
index 560a40a209f5..169783d7d38c 100644
--- a/code/modules/species/xenomorphs/alien_embryo.dm
+++ b/code/modules/species/xenomorphs/alien_embryo.dm
@@ -109,7 +109,7 @@ Des: Removes all infection images from aliens and places an infection image on a
for(var/mob/living/carbon/alien in GLOB.player_list)
- if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs)
+ if(!alien.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
continue
if(alien.client)
@@ -131,7 +131,7 @@ Des: Checks if the passed mob (C) is infected with the alien egg, then gives eac
for(var/mob/living/carbon/alien in GLOB.player_list)
- if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs)
+ if(!alien.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
continue
if(alien.client)
@@ -150,7 +150,7 @@ Des: Removes the alien infection image from all aliens in the world located in p
for(var/mob/living/carbon/alien in GLOB.player_list)
- if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs)
+ if(!alien.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
continue
if(alien.client)
diff --git a/code/modules/species/xenomorphs/alien_facehugger.dm b/code/modules/species/xenomorphs/alien_facehugger.dm
index a0d1e3292d76..1a7e059725ef 100644
--- a/code/modules/species/xenomorphs/alien_facehugger.dm
+++ b/code/modules/species/xenomorphs/alien_facehugger.dm
@@ -121,7 +121,7 @@ var/const/MAX_ACTIVE_TIME = 400
return
var/mob/living/carbon/C = M
- if(istype(C) && locate(/obj/item/organ/internal/xenos/hivenode) in C.internal_organs)
+ if(istype(C) && C.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
return
@@ -229,7 +229,7 @@ var/const/MAX_ACTIVE_TIME = 400
return 0
var/mob/living/carbon/C = M
- if(istype(C) && locate(/obj/item/organ/internal/xenos/hivenode) in C.internal_organs)
+ if(istype(C) && C.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
return 0
if(ishuman(C))
@@ -401,7 +401,7 @@ var/const/MAX_ACTIVE_TIME = 400
return
var/mob/living/carbon/C = M
- if(istype(C) && locate(/obj/item/organ/internal/xenos/hivenode) in C.internal_organs)
+ if(istype(C) && C.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
return
@@ -501,7 +501,7 @@ var/const/MAX_ACTIVE_TIME = 400
return 0
var/mob/living/carbon/C = M
- if(istype(C) && locate(/obj/item/organ/internal/xenos/hivenode) in C.internal_organs)
+ if(istype(C) && C.legacy_organ_by_type(/obj/item/organ/internal/xenomorph/hivenode))
return 0
if(ishuman(C))
diff --git a/code/modules/species/xenomorphs/alien_powers.dm b/code/modules/species/xenomorphs/alien_powers.dm
index f8701abf4501..303c9e89fd35 100644
--- a/code/modules/species/xenomorphs/alien_powers.dm
+++ b/code/modules/species/xenomorphs/alien_powers.dm
@@ -11,8 +11,9 @@
/mob/living/carbon/human/proc/gain_plasma(var/amount)
- var/obj/item/organ/internal/xenos/plasmavessel/I = internal_organs_by_name[O_PLASMA]
- if(!istype(I)) return
+ var/obj/item/organ/internal/xenomorph/plasmavessel/I = keyed_organs[ORGAN_KEY_XENOMORPH_PLASMA_VESSEL]
+ if(!istype(I))
+ return
if(amount)
I.stored_plasma += amount
@@ -20,13 +21,13 @@
/mob/living/carbon/human/proc/check_alien_ability(var/cost,var/needs_foundation,var/needs_organ) //Returns 1 if the ability is clear for usage.
- var/obj/item/organ/internal/xenos/plasmavessel/P = internal_organs_by_name[O_PLASMA]
+ var/obj/item/organ/internal/xenomorph/plasmavessel/P = keyed_organs[ORGAN_KEY_XENOMORPH_PLASMA_VESSEL]
if(!istype(P))
to_chat(src, "Your plasma vessel has been removed!")
return
if(needs_organ)
- var/obj/item/organ/internal/I = internal_organs_by_name[needs_organ]
+ var/obj/item/organ/internal/I = legacy_organ_by_tag[needs_organ]
if(!I)
to_chat(src, "Your [needs_organ] has been removed!")
return
@@ -62,7 +63,7 @@
to_chat(src, "You need to be closer.")
return
- var/obj/item/organ/internal/xenos/plasmavessel/I = M.internal_organs_by_name[O_PLASMA]
+ var/obj/item/organ/internal/xenomorph/plasmavessel/I = M.keyed_organs[ORGAN_KEY_XENOMORPH_PLASMA_VESSEL]
if(!istype(I))
to_chat(src, "Their plasma vessel is missing.")
return
@@ -110,7 +111,7 @@
if(check_alien_ability(500))
visible_message("[src] begins to twist and contort!", "You begin to evolve!")
- src.set_species(/datum/species/xenos/queen)
+ src.set_species(/datum/species/xenomorph/queen)
return
diff --git a/code/modules/species/xenomorphs/alien_species.dm b/code/modules/species/xenomorphs/alien_species.dm
index 6016d95308a2..7956dc324bba 100644
--- a/code/modules/species/xenomorphs/alien_species.dm
+++ b/code/modules/species/xenomorphs/alien_species.dm
@@ -1,5 +1,5 @@
//Stand-in until this is made more lore-friendly.
-/datum/species/xenos
+/datum/species/xenomorph
id = SPECIES_ID_XENOMORPH
uid = SPECIES_ID_XENOMORPH
name = SPECIES_XENO
@@ -55,8 +55,8 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart,
O_BRAIN = /obj/item/organ/internal/brain/xeno,
- O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel,
- O_HIVE = /obj/item/organ/internal/xenos/hivenode,
+ O_PLASMA = /obj/item/organ/internal/xenomorph/plasmavessel,
+ O_HIVE = /obj/item/organ/internal/xenomorph/hivenode,
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients,
O_STOMACH = /obj/item/organ/internal/stomach/xeno,
O_INTESTINE = /obj/item/organ/internal/intestine/xeno
@@ -89,24 +89,24 @@
MOB_IFF_FACTION_XENOMORPH,
)
-/datum/species/xenos/get_bodytype_legacy()
+/datum/species/xenomorph/get_bodytype_legacy()
return SPECIES_XENO
-/datum/species/xenos/get_random_name()
+/datum/species/xenomorph/get_random_name()
return "alien [caste_name] ([alien_number])"
-/datum/species/xenos/can_understand(var/mob/other)
+/datum/species/xenomorph/can_understand(var/mob/other)
if(istype(other,/mob/living/carbon/alien/larva))
return 1
return 0
-/datum/species/xenos/hug(var/mob/living/carbon/human/H,var/mob/living/target)
+/datum/species/xenomorph/hug(var/mob/living/carbon/human/H,var/mob/living/target)
H.visible_message("[H] caresses [target] with its scythe-like arm.", \
"You caress [target] with your scythe-like arm.")
-/datum/species/xenos/handle_post_spawn(var/mob/living/carbon/human/H)
+/datum/species/xenomorph/handle_post_spawn(var/mob/living/carbon/human/H)
if(H.mind)
H.mind.assigned_role = "Alien"
@@ -118,17 +118,17 @@
..()
-/datum/species/xenos/handle_environment_special(mob/living/carbon/human/H, datum/gas_mixture/environment, dt)
+/datum/species/xenomorph/handle_environment_special(mob/living/carbon/human/H, datum/gas_mixture/environment, dt)
if(!environment)
return
if(environment.gas[GAS_ID_PHORON] > 0 || locate(/obj/structure/alien/weeds) in get_turf(H))
if(!regenerate(H))
- var/obj/item/organ/internal/xenos/plasmavessel/P = H.internal_organs_by_name[O_PLASMA]
+ var/obj/item/organ/internal/xenomorph/plasmavessel/P = H.keyed_organs[ORGAN_KEY_XENOMORPH_PLASMA_VESSEL]
P.stored_plasma += weeds_plasma_rate
P.stored_plasma = min(max(P.stored_plasma,0),P.max_plasma)
-/datum/species/xenos/proc/regenerate(var/mob/living/carbon/human/H)
+/datum/species/xenomorph/proc/regenerate(var/mob/living/carbon/human/H)
var/heal_rate = weeds_heal_rate
var/mend_prob = 10
if (!H.resting)
@@ -163,16 +163,16 @@
return 0
/*
-/datum/species/xenos/handle_login_special(var/mob/living/carbon/human/H)
+/datum/species/xenomorph/handle_login_special(var/mob/living/carbon/human/H)
H.AddInfectionImages()
..()
-/datum/species/xenos/handle_logout_special(var/mob/living/carbon/human/H)
+/datum/species/xenomorph/handle_logout_special(var/mob/living/carbon/human/H)
H.RemoveInfectionImages()
..()
*/
-/datum/species/xenos/drone
+/datum/species/xenomorph/drone
uid = SPECIES_ID_XENOMORPH_DRONE
name = SPECIES_XENO_DRONE
caste_name = "drone"
@@ -189,10 +189,10 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart,
O_BRAIN = /obj/item/organ/internal/brain/xeno,
- O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/queen,
- O_ACID = /obj/item/organ/internal/xenos/acidgland,
- O_HIVE = /obj/item/organ/internal/xenos/hivenode,
- O_RESIN = /obj/item/organ/internal/xenos/resinspinner,
+ O_PLASMA = /obj/item/organ/internal/xenomorph/plasmavessel/queen,
+ O_ACID = /obj/item/organ/internal/xenomorph/acidgland,
+ O_HIVE = /obj/item/organ/internal/xenomorph/hivenode,
+ O_RESIN = /obj/item/organ/internal/xenomorph/resinspinner,
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients,
O_STOMACH = /obj/item/organ/internal/stomach/xeno,
O_INTESTINE = /obj/item/organ/internal/intestine/xeno
@@ -206,14 +206,14 @@
/mob/living/carbon/human/proc/corrosive_acid
)
-/datum/species/xenos/drone/handle_post_spawn(var/mob/living/carbon/human/H)
+/datum/species/xenomorph/drone/handle_post_spawn(var/mob/living/carbon/human/H)
var/mob/living/carbon/human/A = H
if(!istype(A))
return ..()
..()
-/datum/species/xenos/hunter
+/datum/species/xenomorph/hunter
uid = SPECIES_ID_XENOMORPH_HUNTER
name = SPECIES_XENO_HUNTER
weeds_plasma_rate = 5
@@ -231,8 +231,8 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart,
O_BRAIN = /obj/item/organ/internal/brain/xeno,
- O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/hunter,
- O_HIVE = /obj/item/organ/internal/xenos/hivenode,
+ O_PLASMA = /obj/item/organ/internal/xenomorph/plasmavessel/hunter,
+ O_HIVE = /obj/item/organ/internal/xenomorph/hivenode,
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients,
O_STOMACH = /obj/item/organ/internal/stomach/xeno,
O_INTESTINE = /obj/item/organ/internal/intestine/xeno
@@ -247,7 +247,7 @@
/mob/living/carbon/human/proc/regurgitate
)
-/datum/species/xenos/sentinel
+/datum/species/xenomorph/sentinel
uid = SPECIES_ID_XENOMORPH_SENTINEL
name = SPECIES_XENO_SENTINEL
weeds_plasma_rate = 10
@@ -265,9 +265,9 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart,
O_BRAIN = /obj/item/organ/internal/brain/xeno,
- O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/sentinel,
- O_ACID = /obj/item/organ/internal/xenos/acidgland,
- O_HIVE = /obj/item/organ/internal/xenos/hivenode,
+ O_PLASMA = /obj/item/organ/internal/xenomorph/plasmavessel/sentinel,
+ O_ACID = /obj/item/organ/internal/xenomorph/acidgland,
+ O_HIVE = /obj/item/organ/internal/xenomorph/hivenode,
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients,
O_STOMACH = /obj/item/organ/internal/stomach/xeno,
O_INTESTINE = /obj/item/organ/internal/intestine/xeno
@@ -283,7 +283,7 @@
/mob/living/carbon/human/proc/acidspit
)
-/datum/species/xenos/queen
+/datum/species/xenomorph/queen
uid = SPECIES_ID_XENOMORPH_QUEEN
name = SPECIES_XENO_QUEEN
total_health = 250
@@ -304,11 +304,11 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart,
O_BRAIN = /obj/item/organ/internal/brain/xeno,
- O_EGG = /obj/item/organ/internal/xenos/eggsac,
- O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/queen,
- O_ACID = /obj/item/organ/internal/xenos/acidgland,
- O_HIVE = /obj/item/organ/internal/xenos/hivenode,
- O_RESIN = /obj/item/organ/internal/xenos/resinspinner,
+ O_EGG = /obj/item/organ/internal/xenomorph/eggsac,
+ O_PLASMA = /obj/item/organ/internal/xenomorph/plasmavessel/queen,
+ O_ACID = /obj/item/organ/internal/xenomorph/acidgland,
+ O_HIVE = /obj/item/organ/internal/xenomorph/hivenode,
+ O_RESIN = /obj/item/organ/internal/xenomorph/resinspinner,
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients,
O_STOMACH = /obj/item/organ/internal/stomach/xeno,
O_INTESTINE = /obj/item/organ/internal/intestine/xeno
@@ -340,7 +340,7 @@
),
)
-/datum/species/xenos/queen/handle_login_special(var/mob/living/carbon/human/H)
+/datum/species/xenomorph/queen/handle_login_special(var/mob/living/carbon/human/H)
..()
// Make sure only one official queen exists at any point.
if(!alien_queen_exists(1,H))
diff --git a/code/modules/species/xenomorphs/xenomorphs.dm b/code/modules/species/xenomorphs/xenomorphs.dm
index ce9a6e4f5481..30ef0c680363 100644
--- a/code/modules/species/xenomorphs/xenomorphs.dm
+++ b/code/modules/species/xenomorphs/xenomorphs.dm
@@ -8,22 +8,22 @@
return new_alien
/mob/living/carbon/human/xdrone
- species = /datum/species/xenos/drone
+ species = /datum/species/xenomorph/drone
h_style = "Bald"
iff_factions = MOB_IFF_FACTION_XENOMORPH
/mob/living/carbon/human/xsentinel
- species = /datum/species/xenos/sentinel
+ species = /datum/species/xenomorph/sentinel
h_style = "Bald"
iff_factions = MOB_IFF_FACTION_XENOMORPH
/mob/living/carbon/human/xhunter
- species = /datum/species/xenos/hunter
+ species = /datum/species/xenomorph/hunter
h_style = "Bald"
iff_factions = MOB_IFF_FACTION_XENOMORPH
/mob/living/carbon/human/xqueen
- species = /datum/species/xenos/queen
+ species = /datum/species/xenomorph/queen
h_style = "Bald"
iff_factions = MOB_IFF_FACTION_XENOMORPH
diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm
index 734a788d43e9..47b3954b2c26 100644
--- a/code/modules/surgery/bones.dm
+++ b/code/modules/surgery/bones.dm
@@ -23,11 +23,11 @@
/datum/surgery_step/glue_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2 && affected.stage == 0
/datum/surgery_step/glue_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected.stage == 0)
user.visible_message("[user] starts applying medication to the damaged bones in [target]'s [affected.name] with \the [tool]." , \
"You start applying medication to the damaged bones in [target]'s [affected.name] with \the [tool].")
@@ -35,13 +35,13 @@
..()
/datum/surgery_step/glue_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] applies some [tool] to [target]'s bone in [affected.name]", \
"You apply some [tool] to [target]'s bone in [affected.name] with \the [tool].")
affected.stage = 1
/datum/surgery_step/glue_bone/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, smearing [tool] in the incision in [target]'s [affected.name]!" , \
"Your hand slips, smearing [tool] in the incision in [target]'s [affected.name]!")
@@ -63,18 +63,18 @@
/datum/surgery_step/set_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.organ_tag != BP_HEAD && !(affected.robotic >= ORGAN_ROBOT) && affected.open >= 2 && affected.stage == 1
/datum/surgery_step/set_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] is beginning to set the bone in [target]'s [affected.name] in place with \the [tool]." , \
"You are beginning to set the bone in [target]'s [affected.name] in place with \the [tool].")
target.custom_pain("The pain in your [affected.name] is going to make you pass out!", 50)
..()
/datum/surgery_step/set_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected.status & ORGAN_BROKEN)
user.visible_message("[user] sets the bone in [target]'s [affected.name] in place with \the [tool].", \
"You set the bone in [target]'s [affected.name] in place with \the [tool].")
@@ -85,7 +85,7 @@
affected.fracture()
/datum/surgery_step/set_bone/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, damaging the bone in [target]'s [affected.name] with \the [tool]!" , \
"Your hand slips, damaging the bone in [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_BRUISE, 5)
@@ -108,7 +108,7 @@
/datum/surgery_step/mend_skull/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.organ_tag == BP_HEAD && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2 && affected.stage == 1
/datum/surgery_step/mend_skull/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -117,13 +117,13 @@
..()
/datum/surgery_step/mend_skull/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] sets [target]'s skull with \the [tool]." , \
"You set [target]'s skull with \the [tool].")
affected.stage = 2
/datum/surgery_step/mend_skull/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, damaging [target]'s face with \the [tool]!" , \
"Your hand slips, damaging [target]'s face with \the [tool]!")
var/obj/item/organ/external/head/h = affected
@@ -150,24 +150,24 @@
/datum/surgery_step/finish_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open >= 2 && !(affected.robotic >= ORGAN_ROBOT) && affected.stage == 2
/datum/surgery_step/finish_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts to finish mending the damaged bones in [target]'s [affected.name] with \the [tool].", \
"You start to finish mending the damaged bones in [target]'s [affected.name] with \the [tool].")
..()
/datum/surgery_step/finish_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has mended the damaged bones in [target]'s [affected.name] with \the [tool]." , \
"You have mended the damaged bones in [target]'s [affected.name] with \the [tool]." )
affected.status &= ~ORGAN_BROKEN
affected.stage = 0
/datum/surgery_step/finish_bone/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, smearing [tool] in the incision in [target]'s [affected.name]!" , \
"Your hand slips, smearing [tool] in the incision in [target]'s [affected.name]!")
@@ -189,11 +189,11 @@
/datum/surgery_step/clamp_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2 && affected.stage == 0
/datum/surgery_step/clamp_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected.stage == 0)
user.visible_message("[user] starts repairing the damaged bones in [target]'s [affected.name] with \the [tool]." , \
"You starts repairing the damaged bones in [target]'s [affected.name] with \the [tool].")
@@ -201,13 +201,13 @@
..()
/datum/surgery_step/clamp_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] sets the bone in [target]'s [affected.name] with \the [tool].", \
"You sets [target]'s bone in [affected.name] with \the [tool].")
affected.status &= ~ORGAN_BROKEN
/datum/surgery_step/clamp_bone/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, damaging the bone in [target]'s [affected.name] with \the [tool]!" , \
"Your hand slips, damaging the bone in [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_BRUISE, 5)
diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm
index e64692c96d16..66b8937b4ffe 100644
--- a/code/modules/surgery/encased.dm
+++ b/code/modules/surgery/encased.dm
@@ -11,7 +11,7 @@
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && !(affected.robotic >= ORGAN_ROBOT) && affected.encased && affected.open >= 2
///////////////////////////////////////////////////////////////
@@ -31,13 +31,13 @@
/datum/surgery_step/open_encased/saw/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return ..() && affected && affected.open == 2
/datum/surgery_step/open_encased/saw/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] begins to cut through [target]'s [affected.encased] with \the [tool].", \
"You begin to cut through [target]'s [affected.encased] with \the [tool].")
@@ -47,7 +47,7 @@
/datum/surgery_step/open_encased/saw/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has cut [target]'s [affected.encased] open with \the [tool].", \
"You have cut [target]'s [affected.encased] open with \the [tool].")
@@ -56,7 +56,7 @@
/datum/surgery_step/open_encased/saw/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, cracking [target]'s [affected.encased] with \the [tool]!" , \
"Your hand slips, cracking [target]'s [affected.encased] with \the [tool]!" )
@@ -82,13 +82,13 @@
/datum/surgery_step/open_encased/retract/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return ..() && affected && affected.open == 2.5
/datum/surgery_step/open_encased/retract/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] starts to force open the [affected.encased] in [target]'s [affected.name] with \the [tool]."
var/self_msg = "You start to force open the [affected.encased] in [target]'s [affected.name] with \the [tool]."
@@ -99,7 +99,7 @@
/datum/surgery_step/open_encased/retract/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] forces open [target]'s [affected.encased] with \the [tool]."
var/self_msg = "You force open [target]'s [affected.encased] with \the [tool]."
user.visible_message(msg, self_msg)
@@ -109,7 +109,7 @@
/datum/surgery_step/open_encased/retract/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user]'s hand slips, cracking [target]'s [affected.encased]!"
var/self_msg = "Your hand slips, cracking [target]'s [affected.encased]!"
@@ -136,13 +136,13 @@
/datum/surgery_step/open_encased/close/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return (..() && affected && affected.open == 3)
/datum/surgery_step/open_encased/close/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] starts bending [target]'s [affected.encased] back into place with \the [tool]."
var/self_msg = "You start bending [target]'s [affected.encased] back into place with \the [tool]."
@@ -153,7 +153,7 @@
/datum/surgery_step/open_encased/close/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] bends [target]'s [affected.encased] back into place with \the [tool]."
var/self_msg = "You bend [target]'s [affected.encased] back into place with \the [tool]."
@@ -164,7 +164,7 @@
/datum/surgery_step/open_encased/close/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user]'s hand slips, bending [target]'s [affected.encased] the wrong way!"
var/self_msg = "Your hand slips, bending [target]'s [affected.encased] the wrong way!"
@@ -194,13 +194,13 @@
/datum/surgery_step/open_encased/mend/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return ..() && affected && affected.open == 2.5
/datum/surgery_step/open_encased/mend/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] starts applying \the [tool] to [target]'s [affected.encased]."
var/self_msg = "You start applying \the [tool] to [target]'s [affected.encased]."
@@ -211,7 +211,7 @@
/datum/surgery_step/open_encased/mend/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] applied \the [tool] to [target]'s [affected.encased]."
var/self_msg = "You applied \the [tool] to [target]'s [affected.encased]."
@@ -235,13 +235,13 @@
/datum/surgery_step/open_encased/advancedsaw_open/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return ..() && affected && affected.open >= 2 && affected.open < 3
/datum/surgery_step/open_encased/advancedsaw_open/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] begins to open [target]'s [affected.encased] with \the [tool].", \
"You begin to open [target]'s [affected.encased] with \the [tool].")
@@ -251,7 +251,7 @@
/datum/surgery_step/open_encased/advancedsaw_open/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has cut [target]'s [affected.encased] wide open with \the [tool].", \
"You have cut [target]'s [affected.encased] wide open with \the [tool].")
@@ -260,7 +260,7 @@
/datum/surgery_step/open_encased/advancedsaw_open/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, searing [target]'s [affected.encased] with \the [tool]!" , \
"Your hand slips, searing [target]'s [affected.encased] with \the [tool]!" )
@@ -284,13 +284,13 @@
/datum/surgery_step/open_encased/advancedsaw_mend/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return (..() && affected && affected.open == 3)
/datum/surgery_step/open_encased/advancedsaw_mend/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] starts sealing \the [target]'s [affected.encased] with \the [tool]."
var/self_msg = "You start sealing \the [target]'s [affected.encased] with \the [tool]."
@@ -301,7 +301,7 @@
/datum/surgery_step/open_encased/advancedsaw_mend/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] sealed \the [target]'s [affected.encased] with \the [tool]."
var/self_msg = "You sealed \the [target]'s [affected.encased] with \the [tool]."
diff --git a/code/modules/surgery/external_repair.dm b/code/modules/surgery/external_repair.dm
index 416c1ba6a109..ad39c3cfca8b 100644
--- a/code/modules/surgery/external_repair.dm
+++ b/code/modules/surgery/external_repair.dm
@@ -15,7 +15,7 @@
return 0
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected == null)
return 0
if (affected.is_stump())
@@ -44,20 +44,20 @@
/datum/surgery_step/repairflesh/scan_injury/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(affected.burn_stage || affected.brute_stage)
return 0
return 1
return 0
/datum/surgery_step/repairflesh/scan_injury/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] begins scanning [target]'s [affected] with \the [tool].", \
"You begin scanning [target]'s [affected] with \the [tool].")
..()
/datum/surgery_step/repairflesh/scan_injury/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] finishes scanning [target]'s [affected].", \
"You finish scanning [target]'s [affected].")
if(affected.brute_dam)
@@ -70,7 +70,7 @@
affected.burn_stage = max(1, affected.burn_stage)
/datum/surgery_step/repairflesh/scan_injury/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, dropping \the [tool] onto [target]'s [affected]!" , \
"Your hand slips, dropping \the [tool] onto [target]'s [affected]!" )
affected.create_wound(WOUND_TYPE_BRUISE, 10)
@@ -97,7 +97,7 @@
/datum/surgery_step/repairflesh/repair_burns/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(affected.burn_stage < 1 || !(affected.burn_dam))
return 0
if(affected.burn_dam < affected.brute_dam)
@@ -106,7 +106,7 @@
return 0
/datum/surgery_step/repairflesh/repair_burns/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(istype(tool, /obj/item/duct_tape_roll) || istype(tool, /obj/item/barrier_tape_roll))
user.visible_message("[user] begins taping up [target]'s [affected] with \the [tool].", \
"You begin taping up [target]'s [affected] with \the [tool].")
@@ -120,7 +120,7 @@
..()
/datum/surgery_step/repairflesh/repair_burns/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(istype(tool, /obj/item/duct_tape_roll) || istype(tool, /obj/item/barrier_tape_roll))
user.visible_message("[user] finishes taping up [target]'s [affected] with \the [tool].", \
"You finish taping up [target]'s [affected] with \the [tool].")
@@ -134,7 +134,7 @@
..()
/datum/surgery_step/repairflesh/repair_burns/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, tearing up [target]'s [affected] with \the [tool].", \
"Your hand slips, tearing up [target]'s [affected] with \the [tool].")
affected.create_wound(WOUND_TYPE_BRUISE, 10)
@@ -167,7 +167,7 @@
/datum/surgery_step/repairflesh/repair_brute/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(affected.brute_stage < 1 || !(affected.brute_dam))
return 0
if(affected.brute_dam < affected.burn_dam)
@@ -176,7 +176,7 @@
return 0
/datum/surgery_step/repairflesh/repair_brute/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(istype(tool, /obj/item/duct_tape_roll) || istype(tool, /obj/item/barrier_tape_roll))
user.visible_message("[user] begins taping up [target]'s [affected] with \the [tool].", \
"You begin taping up [target]'s [affected] with \the [tool].")
@@ -190,7 +190,7 @@
..()
/datum/surgery_step/repairflesh/repair_brute/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(istype(tool, /obj/item/duct_tape_roll) || istype(tool, /obj/item/barrier_tape_roll))
user.visible_message("[user] finishes taping up [target]'s [affected] with \the [tool].", \
"You finish taping up [target]'s [affected] with \the [tool].")
@@ -204,7 +204,7 @@
..()
/datum/surgery_step/repairflesh/repair_brute/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, tearing up [target]'s [affected] with \the [tool].", \
"Your hand slips, tearing up [target]'s [affected] with \the [tool].")
affected.create_wound(WOUND_TYPE_BRUISE, 10)
diff --git a/code/modules/surgery/face.dm b/code/modules/surgery/face.dm
index b44987d47cf8..ce9e317b2a19 100644
--- a/code/modules/surgery/face.dm
+++ b/code/modules/surgery/face.dm
@@ -11,7 +11,7 @@
/datum/surgery_step/face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (!affected || (affected.robotic >= ORGAN_ROBOT))
return 0
return target_zone == O_MOUTH
@@ -45,7 +45,7 @@
target.op_stage.face = 1
/datum/surgery_step/generic/cut_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!" , \
"Your hand slips, slicing [target]'s throat wth \the [tool]!" )
affected.create_wound(WOUND_TYPE_CUT, 60)
@@ -114,7 +114,7 @@
target.op_stage.face = 3
/datum/surgery_step/face/fix_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, tearing skin on [target]'s face with \the [tool]!", \
"Your hand slips, tearing skin on [target]'s face with \the [tool]!")
target.apply_damage(10, DAMAGE_TYPE_BRUTE, affected, sharp=1, sharp=1)
@@ -144,7 +144,7 @@
..()
/datum/surgery_step/face/cauterize/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] cauterizes the incision on [target]'s face and neck with \the [tool].", \
"You cauterize the incision on [target]'s face and neck with \the [tool].")
affected.open = 0
@@ -155,7 +155,7 @@
target.op_stage.face = 0
/datum/surgery_step/face/cauterize/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, leaving a small burn on [target]'s face with \the [tool]!", \
"Your hand slips, leaving a small burn on [target]'s face with \the [tool]!")
target.apply_damage(4, DAMAGE_TYPE_BURN, affected)
diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm
index 71be860aef84..0159655b884a 100644
--- a/code/modules/surgery/generic.dm
+++ b/code/modules/surgery/generic.dm
@@ -13,7 +13,7 @@
return 0
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected == null)
return 0
if (affected.is_stump())
@@ -40,18 +40,18 @@
/datum/surgery_step/generic/cut_open/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == 0 && target_zone != O_MOUTH
/datum/surgery_step/generic/cut_open/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts the incision on [target]'s [affected.name] with \the [tool].", \
"You start the incision on [target]'s [affected.name] with \the [tool].")
target.custom_pain("You feel a horrible pain as if from a sharp knife in your [affected.name]!", 40)
..()
/datum/surgery_step/generic/cut_open/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has made an incision on [target]'s [affected.name] with \the [tool].", \
"You have made an incision on [target]'s [affected.name] with \the [tool].",)
affected.open = 1
@@ -62,7 +62,7 @@
affected.create_wound(WOUND_TYPE_CUT, 1)
/datum/surgery_step/generic/cut_open/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, slicing open [target]'s [affected.name] in the wrong place with \the [tool]!", \
"Your hand slips, slicing open [target]'s [affected.name] in the wrong place with \the [tool]!")
affected.create_wound(WOUND_TYPE_CUT, 10)
@@ -85,18 +85,18 @@
/datum/surgery_step/generic/cut_with_laser/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == 0 && target_zone != O_MOUTH
/datum/surgery_step/generic/cut_with_laser/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts the bloodless incision on [target]'s [affected.name] with \the [tool].", \
"You start the bloodless incision on [target]'s [affected.name] with \the [tool].")
target.custom_pain("You feel a horrible, searing pain in your [affected.name]!", 50)
..()
/datum/surgery_step/generic/cut_with_laser/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has made a bloodless incision on [target]'s [affected.name] with \the [tool].", \
"You have made a bloodless incision on [target]'s [affected.name] with \the [tool].",)
//Could be cleaner ...
@@ -107,7 +107,7 @@
spread_germs_to_organ(affected, user)
/datum/surgery_step/generic/cut_with_laser/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips as the blade sputters, searing a long gash in [target]'s [affected.name] with \the [tool]!", \
"Your hand slips as the blade sputters, searing a long gash in [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_CUT, 7.5)
@@ -129,18 +129,18 @@
/datum/surgery_step/generic/incision_manager/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == 0 && target_zone != O_MOUTH
/datum/surgery_step/generic/incision_manager/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts to construct a prepared incision on and within [target]'s [affected.name] with \the [tool].", \
"You start to construct a prepared incision on and within [target]'s [affected.name] with \the [tool].")
target.custom_pain("You feel a horrible, searing pain in your [affected.name] as it is pushed apart!", 50)
..()
/datum/surgery_step/generic/incision_manager/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has constructed a prepared incision on and within [target]'s [affected.name] with \the [tool].", \
"You have constructed a prepared incision on and within [target]'s [affected.name] with \the [tool].",)
affected.open = 1
@@ -153,7 +153,7 @@
affected.open = 2
/datum/surgery_step/generic/incision_manager/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand jolts as the system sparks, ripping a gruesome hole in [target]'s [affected.name] with \the [tool]!", \
"Your hand jolts as the system sparks, ripping a gruesome hole in [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_CUT, 20)
@@ -176,25 +176,25 @@
/datum/surgery_step/generic/clamp_bleeders/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open && (affected.status & ORGAN_BLEEDING)
/datum/surgery_step/generic/clamp_bleeders/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts clamping bleeders in [target]'s [affected.name] with \the [tool].", \
"You start clamping bleeders in [target]'s [affected.name] with \the [tool].")
target.custom_pain("The pain in your [affected.name] is maddening!", 40)
..()
/datum/surgery_step/generic/clamp_bleeders/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] clamps bleeders in [target]'s [affected.name] with \the [tool].", \
"You clamp bleeders in [target]'s [affected.name] with \the [tool].")
affected.organ_clamp()
spread_germs_to_organ(affected, user)
/datum/surgery_step/generic/clamp_bleeders/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, tearing blood vessals and causing massive bleeding in [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, tearing blood vessels and causing massive bleeding in [target]'s [affected.name] with \the [tool]!",)
affected.create_wound(WOUND_TYPE_CUT, 10)
@@ -217,11 +217,11 @@
/datum/surgery_step/generic/retract_skin/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == 1 //&& !(affected.status & ORGAN_BLEEDING)
/datum/surgery_step/generic/retract_skin/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] starts to pry open the incision on [target]'s [affected.name] with \the [tool]."
var/self_msg = "You start to pry open the incision on [target]'s [affected.name] with \the [tool]."
if (target_zone == BP_TORSO)
@@ -235,7 +235,7 @@
..()
/datum/surgery_step/generic/retract_skin/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user] keeps the incision open on [target]'s [affected.name] with \the [tool]."
var/self_msg = "You keep the incision open on [target]'s [affected.name] with \the [tool]."
if (target_zone == BP_TORSO)
@@ -248,7 +248,7 @@
affected.open = 2
/datum/surgery_step/generic/retract_skin/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
var/msg = "[user]'s hand slips, tearing the edges of the incision on [target]'s [affected.name] with \the [tool]!"
var/self_msg = "Your hand slips, tearing the edges of the incision on [target]'s [affected.name] with \the [tool]!"
if (target_zone == BP_TORSO)
@@ -278,18 +278,18 @@
/datum/surgery_step/generic/cauterize/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open && target_zone != O_MOUTH
/datum/surgery_step/generic/cauterize/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] is beginning to cauterize the incision on [target]'s [affected.name] with \the [tool]." , \
"You are beginning to cauterize the incision on [target]'s [affected.name] with \the [tool].")
target.custom_pain("Your [affected.name] is being burned!", 40)
..()
/datum/surgery_step/generic/cauterize/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] cauterizes the incision on [target]'s [affected.name] with \the [tool].", \
"You cauterize the incision on [target]'s [affected.name] with \the [tool].")
affected.open = 0
@@ -297,7 +297,7 @@
affected.status &= ~ORGAN_BLEEDING
/datum/surgery_step/generic/cauterize/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, leaving a small burn on [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, leaving a small burn on [target]'s [affected.name] with \the [tool]!")
target.apply_damage(3, DAMAGE_TYPE_BURN, affected)
@@ -322,26 +322,26 @@
return 0
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected == null)
return 0
return !affected.cannot_amputate
/datum/surgery_step/generic/amputate/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] is beginning to amputate [target]'s [affected.name] with \the [tool]." , \
"You are beginning to cut through [target]'s [affected.amputation_point] with \the [tool].")
target.custom_pain("Your [affected.amputation_point] is being ripped apart!", 100)
..()
/datum/surgery_step/generic/amputate/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] amputates [target]'s [affected.name] at the [affected.amputation_point] with \the [tool].", \
"You amputate [target]'s [affected.name] with \the [tool].")
affected.droplimb(1,DROPLIMB_EDGE)
/datum/surgery_step/generic/amputate/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, sawing through the bone in [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, sawwing through the bone in [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_CUT, 30)
diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm
index b6c00fe16c6d..d8d89e9e3372 100644
--- a/code/modules/surgery/implant.dm
+++ b/code/modules/surgery/implant.dm
@@ -10,7 +10,7 @@
/datum/surgery_step/cavity/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == (affected.encased ? 3 : 2) && !(affected.status & ORGAN_BLEEDING)
/datum/surgery_step/cavity/proc/get_max_wclass(obj/item/organ/external/affected)
@@ -34,7 +34,7 @@
return ""
/datum/surgery_step/cavity/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/chest/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, scraping around inside [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, scraping around inside [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_CUT, 20)
@@ -55,11 +55,11 @@
/datum/surgery_step/cavity/make_space/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && !affected.cavity
/datum/surgery_step/cavity/make_space/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool].", \
"You start making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool]." )
target.custom_pain("The pain in your chest is living hell!",1)
@@ -67,7 +67,7 @@
..()
/datum/surgery_step/cavity/make_space/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/chest/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] makes some space inside [target]'s [get_cavity(affected)] cavity with \the [tool].", \
"You make some space inside [target]'s [get_cavity(affected)] cavity with \the [tool]." )
@@ -90,11 +90,11 @@
/datum/surgery_step/cavity/close_space/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.cavity
/datum/surgery_step/cavity/close_space/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts mending [target]'s [get_cavity(affected)] cavity wall with \the [tool].", \
"You start mending [target]'s [get_cavity(affected)] cavity wall with \the [tool]." )
target.custom_pain("The pain in your chest is living hell!",1)
@@ -102,7 +102,7 @@
..()
/datum/surgery_step/cavity/close_space/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/chest/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] mends [target]'s [get_cavity(affected)] cavity walls with \the [tool].", \
" You mend[target]'s [get_cavity(affected)] cavity walls with \the [tool]." )
@@ -119,7 +119,7 @@
/datum/surgery_step/cavity/place_item/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
//if(istype(user,/mob/living/silicon/robot))
//return
if(affected && affected.cavity)
@@ -131,14 +131,14 @@
return total_volume <= get_max_wclass(affected)
/datum/surgery_step/cavity/place_item/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts putting \the [tool] inside [target]'s [get_cavity(affected)] cavity.", \
"You start putting \the [tool] inside [target]'s [get_cavity(affected)] cavity." ) //Nobody will probably ever see this, but I made these two blue. ~CK
target.custom_pain("The pain in your chest is living hell!",1)
..()
/datum/surgery_step/cavity/place_item/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/chest/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] puts \the [tool] inside [target]'s [get_cavity(affected)] cavity.", \
"You put \the [tool] inside [target]'s [get_cavity(affected)] cavity." )
@@ -180,24 +180,24 @@
max_duration = 100
/datum/surgery_step/cavity/implant_removal/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!affected)
return FALSE
if(affected.organ_tag == BP_HEAD)
- var/obj/item/organ/internal/brain/sponge = target.internal_organs_by_name["brain"]
+ var/obj/item/organ/internal/brain/sponge = target.keyed_organs[ORGAN_KEY_BRAIN]
return ..() && (!sponge || !sponge.damage)
else
return ..()
/datum/surgery_step/cavity/implant_removal/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \
"You start poking around inside [target]'s [affected.name] with \the [tool]." )
target.custom_pain("The pain in your [affected.name] is living hell!",1)
..()
/datum/surgery_step/cavity/implant_removal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/chest/affected = target.legacy_organ_by_zone(target_zone)
if (affected.implants.len)
@@ -218,7 +218,7 @@
/datum/surgery_step/cavity/implant_removal/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
..()
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/chest/affected = target.legacy_organ_by_zone(target_zone)
if (affected.implants.len)
var/fail_prob = 10
fail_prob += 100 - tool_quality(tool)
diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm
index a2c2e78d804d..53e7ce57819c 100644
--- a/code/modules/surgery/limb_reattach.dm
+++ b/code/modules/surgery/limb_reattach.dm
@@ -11,7 +11,7 @@
/datum/surgery_step/limb/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected)
return 0
var/list/organ_data = target.species.has_limbs["[target_zone]"]
@@ -30,7 +30,7 @@
/datum/surgery_step/limb/attach/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/E = tool
var/obj/item/organ/external/P = target.organs_by_name[E.parent_organ]
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected)
to_chat(user, "Something is in the way! You can't attach [E] here!")
return 0
@@ -85,16 +85,16 @@
max_duration = 120
/datum/surgery_step/limb/connect/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/E = target.get_organ(target_zone)
+ var/obj/item/organ/external/E = target.legacy_organ_by_zone(target_zone)
return E && !E.is_stump() && (E.status & ORGAN_CUT_AWAY)
/datum/surgery_step/limb/connect/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/E = target.get_organ(target_zone)
+ var/obj/item/organ/external/E = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts connecting tendons and muscles in [target]'s [E.amputation_point] with [tool].", \
"You start connecting tendons and muscle in [target]'s [E.amputation_point].")
/datum/surgery_step/limb/connect/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/E = target.get_organ(target_zone)
+ var/obj/item/organ/external/E = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has connected tendons and muscles in [target]'s [E.amputation_point] with [tool].", \
"You have connected tendons and muscles in [target]'s [E.amputation_point] with [tool].")
E.status &= ~ORGAN_CUT_AWAY
@@ -124,7 +124,7 @@
if (p.part)
if (!(target_zone in p.part))
return 0
- return isnull(target.get_organ(target_zone))
+ return isnull(target.legacy_organ_by_zone(target_zone))
/datum/surgery_step/limb/mechanize/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] starts attaching \the [tool] to [target].", \
@@ -137,7 +137,7 @@
if(L.part)
for(var/part_name in L.part)
- if(!isnull(target.get_organ(part_name)))
+ if(!isnull(target.legacy_organ_by_zone(part_name)))
continue
var/list/organ_data = target.species.has_limbs["[part_name]"]
if(!organ_data)
diff --git a/code/modules/surgery/neck.dm b/code/modules/surgery/neck.dm
index 069187ac9438..47602b20f261 100644
--- a/code/modules/surgery/neck.dm
+++ b/code/modules/surgery/neck.dm
@@ -11,7 +11,7 @@
/datum/surgery_step/brainstem/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (!affected || (affected.robotic >= ORGAN_ROBOT) || !(affected.open >= 3))
return 0
return target_zone == BP_HEAD
@@ -45,7 +45,7 @@
target.op_stage.brainstem = 1
/datum/surgery_step/brainstem/mend_vessels/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, tearing at [target]'s brainstem with \the [tool]!" , \
"Your hand slips, tearing at [target]'s brainstem with \the [tool]!" )
affected.create_wound(WOUND_TYPE_PIERCE, 10)
@@ -77,7 +77,7 @@
..()
/datum/surgery_step/brainstem/drill_vertebrae/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has drilled around [target]'s brainstem with \the [tool]." , \
" You have drilled around [target]'s brainstem with \the [tool].",)
target.adjust_unconscious(20 * 10) //We're getting Invasive here. This only ticks down when the person is alive, so it's a good side-effect for this step. Rattling the braincase with a drill is not optimal.
@@ -85,7 +85,7 @@
affected.fracture() //Does not apply damage, simply breaks it if it wasn't already. Doesn't stop a defib on its own.
/datum/surgery_step/brainstem/drill_vertebrae/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- //var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ //var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] almost loses their grip on the [tool]!" , \
"Your hand slips and nearly shreds [target]'s brainstem with \the [tool]!" )
/*affected.create_wound(WOUND_TYPE_PIERCE, 10)
@@ -125,7 +125,7 @@
target.op_stage.brainstem = 3
/datum/surgery_step/brainstem/clean_chips/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- //var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ //var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, gouging [target]'s brainstem with \the [tool]!" , \
"Your hand slips, gouging [target]'s brainstem with \the [tool]!" )
/*affected.create_wound(WOUND_TYPE_CUT, 5)
@@ -165,7 +165,7 @@
target.add_modifier(/datum/modifier/franken_sickness, 20 MINUTES)
/datum/surgery_step/brainstem/mend_cord/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, tearing at [target]'s spinal cord with \the [tool]!" , \
"Your hand slips, tearing at [target]'s spinal cord with \the [tool]!" )
affected.create_wound(WOUND_TYPE_PIERCE, 5)
@@ -203,7 +203,7 @@
target.op_stage.brainstem = 5
/datum/surgery_step/brainstem/mend_vertebrae/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, tearing at [target]'s spinal cord with \the [tool]!" , \
"Your hand slips, tearing at [target]'s spinal cord with \the [tool]!" )
affected.create_wound(WOUND_TYPE_PIERCE, 5)
@@ -243,7 +243,7 @@
target.op_stage.brainstem = 0 //The cycle begins anew.
/datum/surgery_step/brainstem/realign_tissue/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, gouging [target]'s brainstem with \the [tool]!" , \
"Your hand slips, gouging [target]'s brainstem with \the [tool]!" )
affected.create_wound(WOUND_TYPE_CUT, 5)
diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm
index 39794ddcb5b5..edcb49f2d43f 100644
--- a/code/modules/surgery/organs_internal.dm
+++ b/code/modules/surgery/organs_internal.dm
@@ -9,7 +9,7 @@
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == (affected.encased ? 3 : 2)
@@ -37,7 +37,7 @@
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return ..() && affected && embryo && affected.open == 3 && target_zone == BP_TORSO
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -69,7 +69,7 @@
/datum/surgery_step/internal/fix_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!affected)
return
var/is_organ_damaged = 0
@@ -89,7 +89,7 @@
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
for(var/obj/item/organ/I in affected.internal_organs)
if(I && (I.damage > 0 || I.status == ORGAN_DEAD))
@@ -109,7 +109,7 @@
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
for(var/obj/item/organ/internal/I in affected.internal_organs)
if(I && (I.damage > 0 || I.status == ORGAN_DEAD))
@@ -123,7 +123,7 @@
/datum/surgery_step/internal/fix_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, getting mess and tearing the inside of [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, getting mess and tearing the inside of [target]'s [affected.name] with \the [tool]!")
@@ -144,13 +144,13 @@
// Organ Detaching Surgery
///////////////////////////////////////////////////////////////
-/datum/surgery_step/internal/detatch_organ/
+/datum/surgery_step/internal/detatch_organ
allowed_tools = list(
- /obj/item/surgical/scalpel = 100, \
- /obj/item/surgical/scalpel_primitive = 80, \
- /obj/item/material/knife = 75, \
- /obj/item/material/shard = 50, \
+ /obj/item/surgical/scalpel = 100,
+ /obj/item/surgical/scalpel_primitive = 80,
+ /obj/item/material/knife = 75,
+ /obj/item/material/shard = 50,
)
min_duration = 90
@@ -160,29 +160,31 @@
if (!..())
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!(affected && !(affected.robotic >= ORGAN_ROBOT)))
return 0
- target.op_stage.current_organ = null
-
var/list/attached_organs = list()
- for(var/organ in target.internal_organs_by_name)
- var/obj/item/organ/I = target.internal_organs_by_name[organ]
- if(I && !(I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
- attached_organs |= organ
-
- var/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs
+ for(var/obj/item/organ/internal/potential as anything in target.get_internal_organs_for_zone(target_zone))
+ if(potential.status & ORGAN_CUT_AWAY)
+ continue
+ if(potential.robotic >= ORGAN_ROBOT)
+ continue
+ attached_organs += potential
+
+ var/obj/item/organ/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs
if(!organ_to_remove)
return 0
- target.op_stage.current_organ = organ_to_remove
+ target.op_stage.current_organ_new = organ_to_remove
- return ..() && organ_to_remove
+ . = ..() && organ_to_remove
+ if(!.)
+ target.op_stage.current_organ_new = null
/datum/surgery_step/internal/detatch_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts to separate [target]'s [target.op_stage.current_organ] with \the [tool].", \
"You start to separate [target]'s [target.op_stage.current_organ] with \the [tool]." )
@@ -193,15 +195,17 @@
user.visible_message("[user] has separated [target]'s [target.op_stage.current_organ] with \the [tool]." , \
"You have separated [target]'s [target.op_stage.current_organ] with \the [tool].")
- var/obj/item/organ/I = target.internal_organs_by_name[target.op_stage.current_organ]
- if(I && istype(I))
+ var/obj/item/organ/I = target.op_stage.current_organ_new
+ if(I && I.owner == target)
I.status |= ORGAN_CUT_AWAY
+ target.op_stage.current_organ_new = null
/datum/surgery_step/internal/detatch_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, slicing an artery inside [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, slicing an artery inside [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_CUT, rand(30,50), 1)
+ target.op_stage.current_organ_new = null
///////////////////////////////////////////////////////////////
// Organ Removal Surgery
@@ -224,20 +228,21 @@
if (!..())
return 0
- target.op_stage.current_organ = null
-
- var/list/removable_organs = list()
- for(var/organ in target.internal_organs_by_name)
- var/obj/item/organ/internal/I = target.internal_organs_by_name[organ]
- if(istype(I) && (I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
- removable_organs |= organ
+ var/list/attached_organs = list()
+ for(var/obj/item/organ/internal/potential as anything in target.get_internal_organs_for_zone(target_zone))
+ if(!(potential.status & ORGAN_CUT_AWAY))
+ continue
+ attached_organs += potential
- var/organ_to_remove = input(user, "Which organ do you want to remove?") as null|anything in removable_organs
+ var/obj/item/organ/organ_to_remove = input(user, "Which organ do you want to remove?") as null|anything in attached_organs
if(!organ_to_remove)
return 0
- target.op_stage.current_organ = organ_to_remove
- return ..()
+ target.op_stage.current_organ_new = organ_to_remove
+
+ . = ..() && organ_to_remove
+ if(!.)
+ target.op_stage.current_organ_new = null
/datum/surgery_step/internal/remove_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] starts removing [target]'s [target.op_stage.current_organ] with \the [tool].", \
@@ -249,18 +254,17 @@
user.visible_message("[user] has removed [target]'s [target.op_stage.current_organ] with \the [tool].", \
"You have removed [target]'s [target.op_stage.current_organ] with \the [tool].")
- // Extract the organ!
- if(target.op_stage.current_organ)
- var/obj/item/organ/O = target.internal_organs_by_name[target.op_stage.current_organ]
- if(O && istype(O))
- O.removed(user)
- target.op_stage.current_organ = null
+ var/obj/item/organ/O = target.op_stage.current_organ_new
+ if(O && istype(O))
+ O.removed(user)
+ target.op_stage.current_organ_new = null
/datum/surgery_step/internal/remove_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, damaging [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_BRUISE, 20)
+ target.op_stage.current_organ_new = null
///////////////////////////////////////////////////////////////
// Organ Replacement Surgery
@@ -276,7 +280,7 @@
/datum/surgery_step/internal/replace_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/internal/O = tool
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!affected)
return
@@ -319,14 +323,14 @@
return ..() && organ_missing && organ_compatible
/datum/surgery_step/internal/replace_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts transplanting \the [tool] into [target]'s [affected.name].", \
"You start transplanting \the [tool] into [target]'s [affected.name].")
target.custom_pain("Someone's rooting around in your [affected.name]!", 100)
..()
/datum/surgery_step/internal/replace_organ/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has transplanted \the [tool] into [target]'s [affected.name].", \
"You have transplanted \the [tool] into [target]'s [affected.name].")
var/obj/item/organ/O = tool
@@ -360,18 +364,23 @@
target.op_stage.current_organ = null
- var/list/removable_organs = list()
- for(var/organ in target.internal_organs_by_name)
- var/obj/item/organ/I = target.internal_organs_by_name[organ]
- if(istype(I) && (I.status & ORGAN_CUT_AWAY) && !(I.robotic >= ORGAN_ROBOT) && I.parent_organ == target_zone)
- removable_organs |= organ
-
- var/organ_to_replace = input(user, "Which organ do you want to reattach?") as null|anything in removable_organs
+ var/list/attached_organs = list()
+ for(var/obj/item/organ/internal/potential as anything in target.get_internal_organs_for_zone(target_zone))
+ if(!(potential.status & ORGAN_CUT_AWAY))
+ continue
+ if(potential.robotic >= ORGAN_ROBOT)
+ continue
+ attached_organs += potential
+
+ var/obj/item/organ/organ_to_replace = input(user, "Which organ do you want to reattach?") as null|anything in attached_organs
if(!organ_to_replace)
return 0
- target.op_stage.current_organ = organ_to_replace
- return ..()
+ target.op_stage.current_organ_new = organ_to_remove
+
+ . = ..() && organ_to_remove
+ if(!.)
+ target.op_stage.current_organ_new = null
/datum/surgery_step/internal/attach_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] begins reattaching [target]'s [target.op_stage.current_organ] with \the [tool].", \
@@ -383,15 +392,17 @@
user.visible_message("[user] has reattached [target]'s [target.op_stage.current_organ] with \the [tool]." , \
"You have reattached [target]'s [target.op_stage.current_organ] with \the [tool].")
- var/obj/item/organ/I = target.internal_organs_by_name[target.op_stage.current_organ]
- if(I && istype(I))
+ var/obj/item/organ/I = target.op_stage.current_organ_new
+ if(I && I.owner == target)
I.status &= ~ORGAN_CUT_AWAY
+ target.op_stage.current_organ_new = null
/datum/surgery_step/internal/attach_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_BRUISE, 20)
+ target.op_stage.current_organ_new = null
///////////////////////////////////////////////////////////////
// Organ Ripping Surgery
@@ -414,20 +425,19 @@
if (!..())
return 0
- target.op_stage.current_organ = null
-
- var/list/removable_organs = list()
- for(var/organ in target.internal_organs_by_name)
- var/obj/item/organ/internal/I = target.internal_organs_by_name[organ]
- if(istype(I) && I.parent_organ == target_zone)
- removable_organs |= organ
+ var/list/attached_organs = list()
+ for(var/obj/item/organ/internal/potential as anything in target.get_internal_organs_for_zone(target_zone))
+ attached_organs += potential
- var/organ_to_remove = input(user, "Which organ do you want to remove?") as null|anything in removable_organs
+ var/obj/item/organ/organ_to_remove = input(user, "Which organ do you want to remove?") as null|anything in attached_organs
if(!organ_to_remove)
return 0
- target.op_stage.current_organ = organ_to_remove
- return ..()
+ target.op_stage.current_organ_new = organ_to_remove
+
+ . = ..() && organ_to_remove
+ if(!.)
+ target.op_stage.current_organ_new = null
/datum/surgery_step/internal/rip_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] starts ripping [target]'s [target.op_stage.current_organ] out with \the [tool].", \
@@ -439,18 +449,17 @@
user.visible_message("[user] has ripped [target]'s [target.op_stage.current_organ] out with \the [tool].", \
"You have ripped [target]'s [target.op_stage.current_organ] out with \the [tool].")
- // Extract the organ!
- if(target.op_stage.current_organ)
- var/obj/item/organ/O = target.internal_organs_by_name[target.op_stage.current_organ]
- if(O && istype(O))
- O.removed(user)
- target.op_stage.current_organ = null
+ var/obj/item/organ/O = target.op_stage.current_organ_new
+ if(O && istype(O))
+ O.removed(user)
+ target.op_stage.current_organ_new = null
/datum/surgery_step/internal/rip_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, damaging [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_BRUISE, 20)
+ target.op_stage.current_organ_new = null
//////////////////////////////////////////////////////////////////
// HEART SURGERY //
diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm
index d8a31dbd9b64..573cca749f70 100644
--- a/code/modules/surgery/other.dm
+++ b/code/modules/surgery/other.dm
@@ -23,7 +23,7 @@
if(!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!affected) return
var/internal_bleeding = 0
for(var/datum/wound/W as anything in affected.wounds)
@@ -34,14 +34,14 @@
return affected.open == (affected.encased ? 3 : 2) && internal_bleeding
/datum/surgery_step/fix_vein/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts patching the damaged vein in [target]'s [affected.name] with \the [tool]." , \
"You start patching the damaged vein in [target]'s [affected.name] with \the [tool].")
target.custom_pain("The pain in [affected.name] is unbearable!", 100)
..()
/datum/surgery_step/fix_vein/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has patched the damaged vein in [target]'s [affected.name] with \the [tool].", \
"You have patched the damaged vein in [target]'s [affected.name] with \the [tool].")
@@ -59,7 +59,7 @@
H.bloody_hands(target, 0)
/datum/surgery_step/fix_vein/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, smearing [tool] in the incision in [target]'s [affected.name]!" , \
"Your hand slips, smearing [tool] in the incision in [target]'s [affected.name]!")
affected.inflict_bodypart_damage(
@@ -91,25 +91,25 @@
if (target_zone == O_MOUTH || target_zone == O_EYES)
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open >= 2 && (affected.status & ORGAN_DEAD)
/datum/surgery_step/fix_dead_tissue/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts cutting away necrotic tissue in [target]'s [affected.name] with \the [tool]." , \
"You start cutting away necrotic tissue in [target]'s [affected.name] with \the [tool].")
target.custom_pain("The pain in [affected.name] is unbearable!", 100)
..()
/datum/surgery_step/fix_dead_tissue/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has cut away necrotic tissue in [target]'s [affected.name] with \the [tool].", \
"You have cut away necrotic tissue in [target]'s [affected.name] with \the [tool].")
affected.open = 3
/datum/surgery_step/fix_dead_tissue/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, slicing an artery inside [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, slicing an artery inside [target]'s [affected.name] with \the [tool]!")
affected.create_wound(WOUND_TYPE_CUT, 20, 1)
@@ -147,18 +147,18 @@
if (target_zone == O_MOUTH || target_zone == O_EYES)
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == 3 && (affected.status & ORGAN_DEAD)
/datum/surgery_step/treat_necrosis/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts applying medication to the affected tissue in [target]'s [affected.name] with \the [tool]." , \
"You start applying medication to the affected tissue in [target]'s [affected.name] with \the [tool].")
target.custom_pain("Something in your [affected.name] is causing you a lot of pain!", 50)
..()
/datum/surgery_step/treat_necrosis/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (!istype(tool, /obj/item/reagent_containers))
return
@@ -174,7 +174,7 @@
"You apply [trans] units of the solution to affected tissue in [target]'s [affected.name] with \the [tool].")
/datum/surgery_step/treat_necrosis/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (!istype(tool, /obj/item/reagent_containers))
return
@@ -252,7 +252,7 @@
/datum/surgery_step/dehusk/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (!affected || (affected.robotic >= ORGAN_ROBOT))
return 0
return target_zone == BP_TORSO && (MUTATION_HUSK in target.mutations)
@@ -279,7 +279,7 @@
..()
/datum/surgery_step/dehusk/structinitial/fail_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, and the mesh falls, with \the [tool] scraping [target]'s body.", \
"Your hand slips, and the mesh falls, with \the [tool] scraping [target]'s body.")
affected.create_wound(WOUND_TYPE_CUT, 15)
@@ -311,7 +311,7 @@
..()
/datum/surgery_step/dehusk/relocateflesh/fail_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] accidentally rips a massive chunk out of [target]'s flesh with \the [tool], causing massive damage.", \
"You accidentally rip a massive chunk out of [target]'s flesh with \the [tool], causing massive damage.")
affected.create_wound(WOUND_TYPE_CUT, 25)
@@ -347,7 +347,7 @@
..()
/datum/surgery_step/dehusk/structfinish/fail_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(istype(tool,/obj/item/surgical/bioregen))
user.visible_message("[user]'s hand slips, causing \the [tool] to scrape [target]'s body.", \
"Your hand slips, causing \the [tool] to scrape [target]'s body.")
@@ -386,7 +386,7 @@
..()
/datum/surgery_step/internal/detoxify/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, failing to finish the surgery, and damaging [target] with \the [tool].", \
"Your hand slips, failing to finish the surgery, and damaging [target] with \the [tool].")
affected.create_wound(WOUND_TYPE_CUT, 15)
diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm
index b24a7dca4162..1989453abb1f 100644
--- a/code/modules/surgery/robotics.dm
+++ b/code/modules/surgery/robotics.dm
@@ -14,7 +14,7 @@
return 0
if (!hasorgans(target))
return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (affected == null)
return 0
if (affected.status & ORGAN_DESTROYED)
@@ -42,23 +42,23 @@
/datum/surgery_step/robotics/unscrew_hatch/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == 0 && target_zone != O_MOUTH
/datum/surgery_step/robotics/unscrew_hatch/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts to unscrew the maintenance hatch on [target]'s [affected.name] with \the [tool].", \
"You start to unscrew the maintenance hatch on [target]'s [affected.name] with \the [tool].")
..()
/datum/surgery_step/robotics/unscrew_hatch/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has opened the maintenance hatch on [target]'s [affected.name] with \the [tool].", \
"You have opened the maintenance hatch on [target]'s [affected.name] with \the [tool].",)
affected.open = 1
/datum/surgery_step/robotics/unscrew_hatch/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s [tool.name] slips, failing to unscrew [target]'s [affected.name].", \
"Your [tool] slips, failing to unscrew [target]'s [affected.name].")
@@ -80,23 +80,23 @@
/datum/surgery_step/robotics/open_hatch/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open == 1
/datum/surgery_step/robotics/open_hatch/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts to pry open the maintenance hatch on [target]'s [affected.name] with \the [tool].",
"You start to pry open the maintenance hatch on [target]'s [affected.name] with \the [tool].")
..()
/datum/surgery_step/robotics/open_hatch/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] opens the maintenance hatch on [target]'s [affected.name] with \the [tool].", \
"You open the maintenance hatch on [target]'s [affected.name] with \the [tool].")
affected.open = 3
/datum/surgery_step/robotics/open_hatch/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s [tool.name] slips, failing to open the hatch on [target]'s [affected.name].",
"Your [tool] slips, failing to open the hatch on [target]'s [affected.name].")
@@ -118,24 +118,24 @@
/datum/surgery_step/robotics/close_hatch/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
return affected && affected.open && target_zone != O_MOUTH
/datum/surgery_step/robotics/close_hatch/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] begins to close and secure the hatch on [target]'s [affected.name] with \the [tool]." , \
"You begin to close and secure the hatch on [target]'s [affected.name] with \the [tool].")
..()
/datum/surgery_step/robotics/close_hatch/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] closes and secures the hatch on [target]'s [affected.name] with \the [tool].", \
"You close and secure the hatch on [target]'s [affected.name] with \the [tool].")
affected.open = 0
affected.germ_level = 0
/datum/surgery_step/robotics/close_hatch/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s [tool.name] slips, failing to close the hatch on [target]'s [affected.name].",
"Your [tool.name] slips, failing to close the hatch on [target]'s [affected.name].")
@@ -154,7 +154,7 @@
/datum/surgery_step/robotics/repair_brute/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(istype(tool, /obj/item/weldingtool))
var/obj/item/weldingtool/welder = tool
if(!welder.isOn() || !welder.remove_fuel(1,user))
@@ -162,20 +162,20 @@
return affected && affected.open == 3 && (affected.disfigured || affected.brute_dam > 0) && target_zone != O_MOUTH
/datum/surgery_step/robotics/repair_brute/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] begins to patch damage to [target]'s [affected.name]'s support structure with \the [tool]." , \
"You begin to patch damage to [target]'s [affected.name]'s support structure with \the [tool].")
..()
/datum/surgery_step/robotics/repair_brute/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] finishes patching damage to [target]'s [affected.name] with \the [tool].", \
"You finish patching damage to [target]'s [affected.name] with \the [tool].")
affected.heal_damage(20, 0, 1, 1)
affected.disfigured = 0
/datum/surgery_step/robotics/repair_brute/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s [tool.name] slips, damaging the internal structure of [target]'s [affected.name].",
"Your [tool.name] slips, damaging the internal structure of [target]'s [affected.name].")
target.apply_damage(rand(5,10), DAMAGE_TYPE_BURN, affected)
@@ -194,7 +194,7 @@
/datum/surgery_step/robotics/repair_burn/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(..())
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(istype(tool, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = tool
if(affected.burn_dam == 0)
@@ -210,20 +210,20 @@
return affected && affected.open == 3 && (affected.disfigured || affected.burn_dam > 0) && target_zone != O_MOUTH
/datum/surgery_step/robotics/repair_burn/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] begins to splice new cabling into [target]'s [affected.name]." , \
"You begin to splice new cabling into [target]'s [affected.name].")
..()
/datum/surgery_step/robotics/repair_burn/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] finishes splicing cable into [target]'s [affected.name].", \
"You finishes splicing new cable into [target]'s [affected.name].")
affected.heal_damage(0, 20, 1, 1)
affected.disfigured = 0
/datum/surgery_step/robotics/repair_burn/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] causes a short circuit in [target]'s [affected.name]!",
"You cause a short circuit in [target]'s [affected.name]!")
target.apply_damage(rand(5,10), DAMAGE_TYPE_BURN, affected)
@@ -246,7 +246,7 @@
/datum/surgery_step/robotics/fix_organ_robotic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!affected) return
var/is_organ_damaged = 0
for(var/obj/item/organ/I in affected.internal_organs)
@@ -258,7 +258,7 @@
/datum/surgery_step/robotics/fix_organ_robotic/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
for(var/obj/item/organ/I in affected.internal_organs)
if(I && I.damage > 0)
@@ -272,7 +272,7 @@
/datum/surgery_step/robotics/fix_organ_robotic/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
for(var/obj/item/organ/I in affected.internal_organs)
if(I && I.damage > 0)
@@ -284,7 +284,7 @@
/datum/surgery_step/robotics/fix_organ_robotic/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if (!hasorgans(target))
return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user]'s hand slips, gumming up the mechanisms inside of [target]'s [affected.name] with \the [tool]!", \
"Your hand slips, gumming up the mechanisms inside of [target]'s [affected.name] with \the [tool]!")
@@ -310,27 +310,29 @@
max_duration = 110
/datum/surgery_step/robotics/detatch_organ_robotic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!(affected && (affected.robotic >= ORGAN_ROBOT)))
return 0
if(affected.open < 3)
return 0
- target.op_stage.current_organ = null
-
var/list/attached_organs = list()
- for(var/organ in target.internal_organs_by_name)
- var/obj/item/organ/I = target.internal_organs_by_name[organ]
- if(I && !(I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
- attached_organs |= organ
-
- var/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs
+ for(var/obj/item/organ/internal/potential as anything in target.get_internal_organs_for_zone(target_zone))
+ if(potential.status & ORGAN_CUT_AWAY)
+ continue
+ if(potential.robotic < ORGAN_ROBOT)
+ continue
+ attached_organs += potential
+
+ var/obj/item/organ/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs
if(!organ_to_remove)
return 0
- target.op_stage.current_organ = organ_to_remove
+ target.op_stage.current_organ_new = organ_to_remove
- return ..() && organ_to_remove
+ . = ..() && organ_to_remove
+ if(!.)
+ target.op_stage.current_organ_new = null
/datum/surgery_step/robotics/detatch_organ_robotic/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] starts to decouple [target]'s [target.op_stage.current_organ] with \the [tool].", \
@@ -341,13 +343,15 @@
user.visible_message("[user] has decoupled [target]'s [target.op_stage.current_organ] with \the [tool]." , \
"You have decoupled [target]'s [target.op_stage.current_organ] with \the [tool].")
- var/obj/item/organ/internal/I = target.internal_organs_by_name[target.op_stage.current_organ]
- if(I && istype(I))
+ var/obj/item/organ/I = target.op_stage.current_organ_new
+ if(I)
I.status |= ORGAN_CUT_AWAY
+ target.op_stage.current_organ_new = null
/datum/surgery_step/robotics/detatch_organ_robotic/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user]'s hand slips, disconnecting \the [tool].", \
"Your hand slips, disconnecting \the [tool].")
+ target.op_stage.current_organ_new = null
///////////////////////////////////////////////////////////////
// Robot Organ Attaching Surgery
@@ -356,14 +360,14 @@
/datum/surgery_step/robotics/attach_organ_robotic
allowed_tools = list(
- /obj/item/surgical/FixOVein = 100
+ /obj/item/surgical/FixOVein = 100,
)
min_duration = 100
max_duration = 120
/datum/surgery_step/robotics/attach_organ_robotic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!(affected && (affected.robotic >= ORGAN_ROBOT)))
return 0
if(affected.open < 3)
@@ -418,7 +422,7 @@
return
var/obj/item/mmi/M = tool
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!(affected && affected.open == 3))
return 0
@@ -440,13 +444,13 @@
return 1
/datum/surgery_step/robotics/install_mmi/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] starts installing \the [tool] into [target]'s [affected.name].", \
"You start installing \the [tool] into [target]'s [affected.name].")
..()
/datum/surgery_step/robotics/install_mmi/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message("[user] has installed \the [tool] into [target]'s [affected.name].", \
"You have installed \the [tool] into [target]'s [affected.name].")
@@ -496,7 +500,7 @@
return
var/obj/item/holder/diona/N = tool
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if(!(affected && affected.open == 3))
return FALSE
@@ -527,7 +531,7 @@
return TRUE
/datum/surgery_step/robotics/install_nymph/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message(
SPAN_NOTICE("[user] starts setting \the [tool] into [target]'s [affected.name]."),
SPAN_NOTICE("You start setting \the [tool] into [target]'s [affected.name]."),
@@ -536,7 +540,7 @@
..()
/datum/surgery_step/robotics/install_nymph/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
user.visible_message(
SPAN_NOTICE("[user] has installed \the [tool] into [target]'s [affected.name]."),
SPAN_NOTICE("You have installed \the [tool] into [target]'s [affected.name]."),
diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm
index 8e430c51bd3d..46b1f3c39af0 100644
--- a/code/modules/surgery/surgery.dm
+++ b/code/modules/surgery/surgery.dm
@@ -79,7 +79,7 @@
// does stuff to begin the step, usually just printing messages. Moved germs transfering and bloodying here too
/datum/surgery_step/proc/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/obj/item/organ/external/affected = target.legacy_organ_by_zone(target_zone)
if (can_infect && affected)
spread_germs_to_organ(affected, user)
if (ishuman(user) && prob(60))
@@ -115,7 +115,7 @@
if(!ishuman(M))
return 1
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affected = H.legacy_organ_by_zone(user.zone_sel.selecting)
if(affected)
for(var/datum/surgery_step/S in GLOB.surgery_steps)
if(!affected.open && S.req_open)
@@ -178,10 +178,11 @@
. += new path
tim_sort(., cmp = GLOBAL_PROC_REF(cmp_surgery_priority_asc))
-/datum/surgery_status/
+/datum/surgery_status
var/eyes = 0
var/face = 0
var/brainstem = 0
var/head_reattach = 0
var/current_organ = "organ"
+ var/obj/item/organ/current_organ_new
var/list/in_progress = list()
diff --git a/code/modules/vehicles/sealed/mecha/subtypes/combat.dm b/code/modules/vehicles/sealed/mecha/subtypes/combat.dm
index dd8e2085ea30..b8862ec56a6b 100644
--- a/code/modules/vehicles/sealed/mecha/subtypes/combat.dm
+++ b/code/modules/vehicles/sealed/mecha/subtypes/combat.dm
@@ -59,7 +59,7 @@
var/mob/living/carbon/human/H = T
// if (M.integrity <= 0) return
- var/obj/item/organ/external/temp = H.get_organ(pick(BP_TORSO, BP_TORSO, BP_TORSO, BP_HEAD))
+ var/obj/item/organ/external/temp = H.legacy_organ_by_zone(pick(BP_TORSO, BP_TORSO, BP_TORSO, BP_HEAD))
if(temp)
var/update = 0
switch(damtype)
diff --git a/code/modules/vehicles/sealed/mecha/subtypes/micro.dm b/code/modules/vehicles/sealed/mecha/subtypes/micro.dm
index 51aede2066f6..f8c18d5f3d49 100644
--- a/code/modules/vehicles/sealed/mecha/subtypes/micro.dm
+++ b/code/modules/vehicles/sealed/mecha/subtypes/micro.dm
@@ -46,7 +46,7 @@
var/mob/living/carbon/human/H = target
// if (M.integrity <= 0) return
- var/obj/item/organ/external/temp = H.get_organ(pick(BP_TORSO, BP_TORSO, BP_TORSO, BP_HEAD))
+ var/obj/item/organ/external/temp = H.legacy_organ_by_zone(pick(BP_TORSO, BP_TORSO, BP_TORSO, BP_HEAD))
if(temp)
var/update = 0
switch(damtype)
diff --git a/code/modules/vehicles_legacy/skateboard.dm b/code/modules/vehicles_legacy/skateboard.dm
index 7b481283a238..58cf8de3fb66 100644
--- a/code/modules/vehicles_legacy/skateboard.dm
+++ b/code/modules/vehicles_legacy/skateboard.dm
@@ -94,7 +94,7 @@
if(!head_slot || !(istype(head_slot,/obj/item/clothing/head/helmet) || istype(head_slot,/obj/item/clothing/head/hardhat)))
//5% chance to suffer severe head trauma because you weren't wearing a helmet
if(prob(5))
- var/obj/item/organ/external/egg = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/egg = H.legacy_organ_by_zone(BP_HEAD)
egg?.fracture()
H.adjustBrainLoss(rand(5, 10))
visible_message("[src] crashes into [A], sending [H] flying! They land on their head, that doesn't look good...")
@@ -112,7 +112,7 @@
var/head_slot = SLOT_HEAD
if(!head_slot || !(istype(head_slot,/obj/item/clothing/head/helmet) || istype(head_slot,/obj/item/clothing/head/hardhat)))
if(prob(5))
- var/obj/item/organ/external/egg = H.get_organ(BP_HEAD)
+ var/obj/item/organ/external/egg = H.legacy_organ_by_zone(BP_HEAD)
egg?.fracture()
H.adjustBrainLoss(rand(5, 10))
visible_message("[src] crashes into [A], sending [H] flying! They land on their head, that doesn't look good...")
diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm
index 278a4667115d..299467bc9317 100644
--- a/code/modules/virus2/effect.dm
+++ b/code/modules/virus2/effect.dm
@@ -186,7 +186,7 @@
/datum/disease2/effect/organs/deactivate(var/mob/living/carbon/mob,var/multiplier)
if(istype(mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = mob
- for (var/obj/item/organ/external/E in H.organs)
+ for (var/obj/item/organ/external/E as anything in H.external_organs)
E.status &= ~ORGAN_DEAD
for (var/obj/item/organ/external/C in E.children)
C.status &= ~ORGAN_DEAD
@@ -218,7 +218,7 @@
/datum/disease2/effect/immortal/activate(var/mob/living/carbon/mob,var/multiplier)
if(istype(mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = mob
- for (var/obj/item/organ/external/E in H.organs)
+ for (var/obj/item/organ/external/E as anything in H.external_organs)
if (E.status & ORGAN_BROKEN && prob(30))
E.status ^= ORGAN_BROKEN
var/heal_amt = -5*multiplier
@@ -240,13 +240,13 @@
/datum/disease2/effect/better_bones/activate(var/mob/living/carbon/mob,var/multiplier)
if(istype(mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = mob
- for (var/obj/item/organ/external/E in H.organs)
+ for (var/obj/item/organ/external/E as anything in H.external_organs)
E.min_broken_damage = max(5, E.min_broken_damage + 30)
/datum/disease2/effect/better_bones/deactivate(var/mob/living/carbon/mob,var/multiplier)
if(istype(mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = mob
- for (var/obj/item/organ/external/E in H.organs)
+ for (var/obj/item/organ/external/E as anything in H.external_organs)
E.min_broken_damage = initial(E.min_broken_damage)
/datum/disease2/effect/bones
@@ -257,13 +257,13 @@
/datum/disease2/effect/bones/activate(var/mob/living/carbon/mob,var/multiplier)
if(istype(mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = mob
- for (var/obj/item/organ/external/E in H.organs)
+ for (var/obj/item/organ/external/E as anything in H.external_organs)
E.min_broken_damage = max(5, E.min_broken_damage - 30)
/datum/disease2/effect/bones/deactivate(var/mob/living/carbon/mob,var/multiplier)
if(istype(mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = mob
- for (var/obj/item/organ/external/E in H.organs)
+ for (var/obj/item/organ/external/E as anything in H.external_organs)
E.min_broken_damage = initial(E.min_broken_damage)
/datum/disease2/effect/combustion
@@ -355,7 +355,7 @@
/datum/disease2/effect/mind/activate(var/mob/living/carbon/mob,var/multiplier)
if(istype(mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = mob
- var/obj/item/organ/internal/brain/B = H.internal_organs_by_name["brain"]
+ var/obj/item/organ/internal/brain/B = H.keyed_organs[ORGAN_KEY_BRAIN]
if (B && B.damage < B.min_broken_damage)
B.take_damage(5)
else
diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm
index d32f1c3e53cf..724b228258e1 100644
--- a/code/modules/virus2/helpers.dm
+++ b/code/modules/virus2/helpers.dm
@@ -166,7 +166,7 @@
if (ishuman(victim))
var/mob/living/carbon/human/H = victim
- var/obj/item/organ/external/select_area = H.get_organ(src.zone_sel.selecting)
+ var/obj/item/organ/external/select_area = H.legacy_organ_by_zone(src.zone_sel.selecting)
var/list/clothes = list(H.head, H.wear_mask, H.wear_suit, H.w_uniform, H.gloves, H.shoes)
for(var/obj/item/clothing/C in clothes)
if(C && istype(C))
diff --git a/code/modules/vore/eating/transforming_vr.dm b/code/modules/vore/eating/transforming_vr.dm
index 2519eceb39e4..7b0fe4b823ef 100644
--- a/code/modules/vore/eating/transforming_vr.dm
+++ b/code/modules/vore/eating/transforming_vr.dm
@@ -64,7 +64,7 @@
M.r_skin = O.r_skin
M.g_skin = O.g_skin
M.b_skin = O.b_skin
- for(var/obj/item/organ/external/Z in M.organs)
+ for(var/obj/item/organ/external/Z as anything in M.external_organs)
Z.sync_colour_to_human(M)
M.update_icons_body()
if(message)
@@ -235,7 +235,7 @@
M.render_spriteacc_tail()
if(backup_implants.len)
- var/obj/item/organ/external/torso = M.get_organ(BP_TORSO)
+ var/obj/item/organ/external/torso = M.legacy_organ_by_zone(BP_TORSO)
for(var/obj/item/implant/backup/BI in backup_implants)
BI.forceMove(torso)
torso.implants += BI
diff --git a/code/modules/vore/lick_wounds.dm b/code/modules/vore/lick_wounds.dm
index 78625be23ef3..f663365c1a22 100644
--- a/code/modules/vore/lick_wounds.dm
+++ b/code/modules/vore/lick_wounds.dm
@@ -14,7 +14,7 @@
if (istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ(zone_sel.selecting)
+ var/obj/item/organ/external/affecting = H.legacy_organ_by_zone(zone_sel.selecting)
if(!affecting)
to_chat(src, "No body part there to work on!")
diff --git a/code/modules/vore/resizing/resize_vr.dm b/code/modules/vore/resizing/resize_vr.dm
index 33af9b05e594..532775b3ffa0 100644
--- a/code/modules/vore/resizing/resize_vr.dm
+++ b/code/modules/vore/resizing/resize_vr.dm
@@ -385,7 +385,7 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
//If they are a human, do damage (doesn't hurt other mobs...?)
if(Ht)
- for(var/obj/item/organ/external/I in Ht.organs)
+ for(var/obj/item/organ/external/I as anything in Ht.external_organs)
I.inflict_bodypart_damage(
brute = calculated_damage,
)
diff --git a/code/modules/xenoarcheaology/effects/heal.dm b/code/modules/xenoarcheaology/effects/heal.dm
index 4cd6acd9c215..9106cd7a1cdb 100644
--- a/code/modules/xenoarcheaology/effects/heal.dm
+++ b/code/modules/xenoarcheaology/effects/heal.dm
@@ -12,7 +12,7 @@
if(ishuman(toucher))
var/mob/living/carbon/human/H = toucher
- for(var/obj/item/organ/external/affecting in H.organs)
+ for(var/obj/item/organ/external/affecting as anything in H.external_organs)
if(affecting && istype(affecting))
affecting.heal_damage(25 * weakness, 25 * weakness)
//H:heal_organ_damage(25, 25)