diff --git a/code/__DEFINES/fish.dm b/code/__DEFINES/fish.dm
index 7d4b5e0d547..c64a50cd077 100644
--- a/code/__DEFINES/fish.dm
+++ b/code/__DEFINES/fish.dm
@@ -2,6 +2,8 @@
#define FISHING_DUD "dud"
///Used in the the hydro tray fishing spot to define a random seed reward
#define FISHING_RANDOM_SEED "Random seed"
+///Used in the surgery fishing spot to define a random organ reward
+#define FISHING_RANDOM_ORGAN "Random organ"
// Baseline fishing difficulty levels
#define FISHING_DEFAULT_DIFFICULTY 15
@@ -94,6 +96,7 @@
#define FISH_ICON_WEAPON "weapon"
#define FISH_ICON_CRITTER "critter"
#define FISH_ICON_SEED "seed"
+#define FISH_ICON_ORGAN "organ"
#define AQUARIUM_ANIMATION_FISH_SWIM "fish"
#define AQUARIUM_ANIMATION_FISH_DEAD "dead"
diff --git a/code/__DEFINES/organ_movement.dm b/code/__DEFINES/organ_movement.dm
index 16f003ede81..04e60eb92f0 100644
--- a/code/__DEFINES/organ_movement.dm
+++ b/code/__DEFINES/organ_movement.dm
@@ -2,3 +2,5 @@
#define DELETE_IF_REPLACED (1<<0)
/// When deleting a brain, we don't delete the identity and the player can keep playing
#define NO_ID_TRANSFER (1<<1)
+/// Organ inserted by the abductors surgery
+#define FROM_ABDUCTOR_SURGERY (1<<2)
diff --git a/code/__DEFINES/surgery.dm b/code/__DEFINES/surgery.dm
index f510d7a1a94..814c8fed9e5 100644
--- a/code/__DEFINES/surgery.dm
+++ b/code/__DEFINES/surgery.dm
@@ -93,6 +93,12 @@
#define SURGERY_REQUIRES_REAL_LIMB (1<<4)
///Will grant a bonus during surgery steps to users with TRAIT_MORBID while they're using tools with CRUEL_IMPLEMENT
#define SURGERY_MORBID_CURIOSITY (1<<5)
+/**
+ * Instead of checking if the tool used is an actual surgery tool to avoid accidentally whacking patients with the wrong tool,
+ * it'll check if it has a defined tool behaviour instead. Useful for surgeries that use mechanical tools instead of medical ones,
+ * like hardware manipulation.
+ */
+#define SURGERY_CHECK_TOOL_BEHAVIOUR (1<<6)
///Return true if target is not in a valid body position for the surgery
#define IS_IN_INVALID_SURGICAL_POSITION(target, surgery) ((surgery.surgery_flags & SURGERY_REQUIRE_RESTING) && (target.mobility_flags & MOBILITY_LIEDOWN && target.body_position != LYING_DOWN))
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index 32929ccdb9f..f2faf6ae81f 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -32,9 +32,13 @@ GLOBAL_LIST_EMPTY(deliverybeacontags)
GLOBAL_LIST_EMPTY_TYPED(singularities, /datum/component/singularity)
GLOBAL_LIST_EMPTY(item_to_design_list)
+
/// list of all surgeries by name, associated with their path.
GLOBAL_LIST_INIT(surgeries_list, init_surgeries())
+/// list of all surgery steps, associated by their path.
+GLOBAL_LIST_INIT(surgery_steps, init_subtypes_w_path_keys(/datum/surgery_step, list()))
+
/// Global list of all non-cooking related crafting recipes.
GLOBAL_LIST_EMPTY(crafting_recipes)
/// This is a global list of typepaths, these typepaths are atoms or reagents that are associated with crafting recipes.
@@ -80,3 +84,22 @@ GLOBAL_LIST_EMPTY(roundstart_station_borgcharger_areas)
/// List of area names of roundstart station mech rechargers, for the low charge/no charge mech screen alert tooltips.
GLOBAL_LIST_EMPTY(roundstart_station_mechcharger_areas)
+
+// List of organ typepaths that are not unit test-able, and shouldn't be spawned by some things, such as certain class prototypes.
+GLOBAL_LIST_INIT(prototype_organs, typecacheof(list(
+ /obj/item/organ,
+ /obj/item/organ/wings,
+ /obj/item/organ/wings/functional,
+ /obj/item/organ/wings/functional/moth,
+ /obj/item/organ/cyberimp,
+ /obj/item/organ/cyberimp/brain,
+ /obj/item/organ/cyberimp/mouth,
+ /obj/item/organ/cyberimp/arm,
+ /obj/item/organ/cyberimp/chest,
+ /obj/item/organ/cyberimp/eyes,
+ /obj/item/organ/alien,
+ /obj/item/organ/brain/dullahan,
+ /obj/item/organ/ears/dullahan,
+ /obj/item/organ/tongue/dullahan,
+ /obj/item/organ/eyes/dullahan,
+), only_root_path = TRUE))
diff --git a/code/datums/components/shell.dm b/code/datums/components/shell.dm
index 9c74920a862..feb6e572bfd 100644
--- a/code/datums/components/shell.dm
+++ b/code/datums/components/shell.dm
@@ -346,7 +346,11 @@
))
if(attached_circuit.loc == parent || (!QDELETED(attached_circuit) && attached_circuit.loc == null))
var/atom/parent_atom = parent
- attached_circuit.forceMove(parent_atom.drop_location())
+ var/drop_location = parent_atom.drop_location()
+ if(drop_location)
+ attached_circuit.forceMove(drop_location)
+ else
+ attached_circuit.moveToNullspace()
for(var/obj/item/circuit_component/to_remove as anything in unremovable_circuit_components)
attached_circuit.remove_component(to_remove)
diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm
index 83a2a08d986..3cba3ad2078 100644
--- a/code/game/machinery/computer/operating_computer.dm
+++ b/code/game/machinery/computer/operating_computer.dm
@@ -140,7 +140,7 @@
data["patient"]["oxyLoss"] = patient.getOxyLoss()
if(patient.surgeries.len)
for(var/datum/surgery/procedure in patient.surgeries)
- var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
+ var/datum/surgery_step/surgery_step = GLOB.surgery_steps[procedure.steps[procedure.status]]
var/chems_needed = surgery_step.get_chem_list()
var/alternative_step
var/alt_chems_needed = ""
diff --git a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm
index 82c9c9fc8e8..805277b3d9c 100644
--- a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm
@@ -34,7 +34,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah...
AddElement(/datum/element/noticable_organ, "%PRONOUN_They radiate%PRONOUN_s an aura of serenity.")
AddElement(/datum/element/update_icon_blocker)
-/obj/item/organ/heart/gondola/mob_insert(mob/living/carbon/receiver, special, movement_flags)
+/obj/item/organ/heart/gondola/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
. = ..()
if(!(FACTION_HOSTILE in receiver.faction))
factions_to_remove += FACTION_HOSTILE
@@ -42,7 +42,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah...
factions_to_remove += FACTION_MINING
receiver.faction |= list(FACTION_HOSTILE, FACTION_MINING)
-/obj/item/organ/heart/gondola/mob_remove(mob/living/carbon/heartless, special, movement_flags)
+/obj/item/organ/heart/gondola/on_mob_remove(mob/living/carbon/heartless, special, movement_flags)
. = ..()
for(var/faction in factions_to_remove)
heartless.faction -= faction
@@ -64,11 +64,11 @@ Fluoride Stare: After someone says 5 words, blah blah blah...
AddElement(/datum/element/noticable_organ, "%PRONOUN_Their mouth is permanently affixed into a relaxed smile.", BODY_ZONE_PRECISE_MOUTH)
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/gondola)
-/obj/item/organ/tongue/gondola/mob_insert(mob/living/carbon/tongue_owner, special, movement_flags)
+/obj/item/organ/tongue/gondola/on_mob_insert(mob/living/carbon/tongue_owner, special, movement_flags)
. = ..()
tongue_owner.add_mood_event("gondola_zen", /datum/mood_event/gondola_serenity)
-/obj/item/organ/tongue/gondola/mob_remove(mob/living/carbon/tongue_owner, special, movement_flags)
+/obj/item/organ/tongue/gondola/on_mob_remove(mob/living/carbon/tongue_owner, special, movement_flags)
tongue_owner.clear_mood_event("gondola_zen")
return ..()
@@ -87,7 +87,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah...
AddElement(/datum/element/noticable_organ, "%PRONOUN_Their left arm has small needles breaching the skin all over it.", BODY_ZONE_L_ARM)
AddElement(/datum/element/noticable_organ, "%PRONOUN_Their right arm has small needles breaching the skin all over it.", BODY_ZONE_R_ARM)
-/obj/item/organ/liver/gondola/mob_insert(mob/living/carbon/liver_owner, special, movement_flags)
+/obj/item/organ/liver/gondola/on_mob_insert(mob/living/carbon/liver_owner, special, movement_flags)
. = ..()
var/has_left = liver_owner.has_left_hand(check_disabled = FALSE)
var/has_right = liver_owner.has_right_hand(check_disabled = FALSE)
@@ -102,7 +102,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah...
RegisterSignal(liver_owner, COMSIG_LIVING_TRY_PULL, PROC_REF(on_owner_try_pull))
RegisterSignal(liver_owner, COMSIG_CARBON_HELPED, PROC_REF(on_hug))
-/obj/item/organ/liver/gondola/mob_remove(mob/living/carbon/liver_owner, special, movement_flags)
+/obj/item/organ/liver/gondola/on_mob_remove(mob/living/carbon/liver_owner, special, movement_flags)
. = ..()
UnregisterSignal(liver_owner, list(COMSIG_HUMAN_EQUIPPING_ITEM, COMSIG_LIVING_TRY_PULL, COMSIG_CARBON_HELPED))
diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
index f10dcefb0d5..251c5c35a49 100644
--- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
@@ -74,7 +74,7 @@
//but 1.5 damage
human_receiver.physiology?.damage_resistance -= 50
-/obj/item/organ/heart/rat/on_mob_remove(mob/living/carbon/heartless, special)
+/obj/item/organ/heart/rat/on_mob_remove(mob/living/carbon/heartless, special, movement_flags)
. = ..()
if(!ishuman(heartless))
return
diff --git a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm
index 2b32ad85702..03955f06ffe 100644
--- a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm
@@ -72,7 +72,7 @@
QDEL_NULL(roach_shell)
return ..()
-/obj/item/organ/heart/roach/on_mob_insert(mob/living/carbon/organ_owner, special)
+/obj/item/organ/heart/roach/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(!ishuman(organ_owner))
return
@@ -87,7 +87,7 @@
. = ..()
limb.add_bodypart_overlay(roach_shell)
-/obj/item/organ/heart/roach/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/heart/roach/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(!ishuman(organ_owner) || QDELETED(organ_owner))
return
@@ -195,7 +195,7 @@
. = ..()
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/roach)
-/obj/item/organ/liver/roach/on_mob_insert(mob/living/carbon/organ_owner, special)
+/obj/item/organ/liver/roach/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(!ishuman(organ_owner))
return
@@ -203,7 +203,7 @@
var/mob/living/carbon/human/human_owner = owner
human_owner.physiology.tox_mod *= 2
-/obj/item/organ/liver/roach/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/liver/roach/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(!ishuman(organ_owner) || QDELETED(organ_owner))
return
diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm
index d5769ceb8d7..7a8d70888f0 100644
--- a/code/game/objects/items/body_egg.dm
+++ b/code/game/objects/items/body_egg.dm
@@ -15,14 +15,14 @@
if(iscarbon(loc))
Insert(loc)
-/obj/item/organ/body_egg/mob_insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED)
+/obj/item/organ/body_egg/on_mob_insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags)
. = ..()
egg_owner.add_traits(list(TRAIT_XENO_HOST, TRAIT_XENO_IMMUNE), ORGAN_TRAIT)
egg_owner.med_hud_set_status()
INVOKE_ASYNC(src, PROC_REF(AddInfectionImages), egg_owner)
-/obj/item/organ/body_egg/mob_remove(mob/living/carbon/egg_owner, special, movement_flags)
+/obj/item/organ/body_egg/on_mob_remove(mob/living/carbon/egg_owner, special, movement_flags)
. = ..()
egg_owner.remove_traits(list(TRAIT_XENO_HOST, TRAIT_XENO_IMMUNE), ORGAN_TRAIT)
egg_owner.med_hud_set_status()
diff --git a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
index 296eef07e81..790dd0f8e53 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
@@ -60,5 +60,5 @@
user.visible_message(span_notice("[user] inserts [tool] into [target]."), span_notice("You insert [tool] into [target]."))
user.temporarilyRemoveItemFromInventory(tool, TRUE)
var/obj/item/organ/heart/gland/gland = tool
- gland.Insert(target, 2)
- return 1
+ gland.Insert(target, special = TRUE, movement_flags = FROM_ABDUCTOR_SURGERY)
+ return TRUE
diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm
index b991a16b831..9f5bae7aad5 100644
--- a/code/modules/antagonists/abductor/equipment/gland.dm
+++ b/code/modules/antagonists/abductor/equipment/gland.dm
@@ -84,7 +84,7 @@
active_mind_control = FALSE
return TRUE
-/obj/item/organ/heart/gland/mob_remove(mob/living/carbon/gland_owner, special, movement_flags)
+/obj/item/organ/heart/gland/on_mob_remove(mob/living/carbon/gland_owner, special, movement_flags)
. = ..()
active = FALSE
if(initial(uses) == 1)
@@ -93,10 +93,10 @@
hud.remove_atom_from_hud(gland_owner)
clear_mind_control()
-/obj/item/organ/heart/gland/mob_insert(mob/living/carbon/gland_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED)
+/obj/item/organ/heart/gland/on_mob_insert(mob/living/carbon/gland_owner, special = FALSE, movement_flags)
. = ..()
- if(special != 2 && uses) // Special 2 means abductor surgery
+ if(!(movement_flags & FROM_ABDUCTOR_SURGERY) && uses)
Start()
var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR]
hud.add_atom_to_hud(gland_owner)
diff --git a/code/modules/antagonists/changeling/headslug_eggs.dm b/code/modules/antagonists/changeling/headslug_eggs.dm
index e2238d9d7e7..5c237b11560 100644
--- a/code/modules/antagonists/changeling/headslug_eggs.dm
+++ b/code/modules/antagonists/changeling/headslug_eggs.dm
@@ -11,11 +11,11 @@
/// When this egg last got removed from a body. If -1, the egg hasn't been removed from a body.
var/removal_time = -1
-/obj/item/organ/body_egg/changeling_egg/mob_insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED)
+/obj/item/organ/body_egg/changeling_egg/on_mob_insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags)
. = ..()
hatch_time = world.time + (removal_time == -1 ? EGG_INCUBATION_TIME : (hatch_time - removal_time))
-/obj/item/organ/body_egg/changeling_egg/mob_remove(mob/living/carbon/egg_owner, special, movement_flags)
+/obj/item/organ/body_egg/changeling_egg/on_mob_remove(mob/living/carbon/egg_owner, special, movement_flags)
. = ..()
removal_time = world.time
diff --git a/code/modules/antagonists/heretic/items/corrupted_organs.dm b/code/modules/antagonists/heretic/items/corrupted_organs.dm
index fec25094bb7..0e8699f6771 100644
--- a/code/modules/antagonists/heretic/items/corrupted_organs.dm
+++ b/code/modules/antagonists/heretic/items/corrupted_organs.dm
@@ -28,7 +28,7 @@
if (LAZYLEN(hallucinations))
organ_owner.client.images |= hallucinations
-/obj/item/organ/eyes/corrupt/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/eyes/corrupt/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if (!LAZYLEN(hallucinations))
return
@@ -51,7 +51,7 @@
. = ..()
RegisterSignal(organ_owner, COMSIG_MOB_SAY, PROC_REF(on_spoken))
-/obj/item/organ/tongue/corrupt/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/tongue/corrupt/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
UnregisterSignal(organ_owner, COMSIG_MOB_SAY)
@@ -87,11 +87,11 @@
. = ..()
AddElement(/datum/element/corrupted_organ)
-/obj/item/organ/liver/corrupt/on_mob_insert(mob/living/carbon/organ_owner, special)
+/obj/item/organ/liver/corrupt/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
RegisterSignal(organ_owner, COMSIG_ATOM_EXPOSE_REAGENTS, PROC_REF(on_drank))
-/obj/item/organ/liver/corrupt/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/liver/corrupt/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
UnregisterSignal(organ_owner, COMSIG_ATOM_EXPOSE_REAGENTS)
@@ -124,11 +124,11 @@
AddElement(/datum/element/corrupted_organ)
AddElement(/datum/element/noticable_organ, "%PRONOUN_They %PRONOUN_have an unhealthy pallor.")
-/obj/item/organ/stomach/corrupt/on_mob_insert(mob/living/carbon/organ_owner, special)
+/obj/item/organ/stomach/corrupt/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
RegisterSignal(organ_owner, COMSIG_ATOM_EXPOSE_REAGENTS, PROC_REF(on_drank))
-/obj/item/organ/stomach/corrupt/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/stomach/corrupt/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
UnregisterSignal(organ_owner, COMSIG_ATOM_EXPOSE_REAGENTS)
diff --git a/code/modules/antagonists/nightmare/nightmare_organs.dm b/code/modules/antagonists/nightmare/nightmare_organs.dm
index ddfe675d412..e4b4528d616 100644
--- a/code/modules/antagonists/nightmare/nightmare_organs.dm
+++ b/code/modules/antagonists/nightmare/nightmare_organs.dm
@@ -94,13 +94,13 @@
user.temporarilyRemoveItemFromInventory(src, TRUE)
Insert(user)
-/obj/item/organ/heart/nightmare/on_mob_insert(mob/living/carbon/heart_owner, special)
+/obj/item/organ/heart/nightmare/on_mob_insert(mob/living/carbon/heart_owner, special, movement_flags)
. = ..()
if(special != HEART_SPECIAL_SHADOWIFY)
blade = new/obj/item/light_eater
heart_owner.put_in_hands(blade)
-/obj/item/organ/heart/nightmare/on_mob_remove(mob/living/carbon/heart_owner, special)
+/obj/item/organ/heart/nightmare/on_mob_remove(mob/living/carbon/heart_owner, special, movement_flags)
. = ..()
respawn_progress = 0
if(blade && special != HEART_SPECIAL_SHADOWIFY)
diff --git a/code/modules/antagonists/voidwalker/voidwalker_organs.dm b/code/modules/antagonists/voidwalker/voidwalker_organs.dm
index 23f1c6fb2fe..760caf3c8d8 100644
--- a/code/modules/antagonists/voidwalker/voidwalker_organs.dm
+++ b/code/modules/antagonists/voidwalker/voidwalker_organs.dm
@@ -26,7 +26,7 @@
/// Speed modifier given when in gravity
var/datum/movespeed_modifier/speed_modifier = /datum/movespeed_modifier/grounded_voidwalker
/// The void eater weapon
- var/obj/item/glass_breaker = /obj/item/void_eater
+ var/obj/item/glass_breaker
/// Our brain transmit telepathy spell
var/datum/action/transmit = /datum/action/cooldown/spell/list_target/telepathy/voidwalker
@@ -52,7 +52,7 @@
glass_breaker = new/obj/item/void_eater
organ_owner.put_in_hands(glass_breaker)
-/obj/item/organ/brain/voidwalker/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/brain/voidwalker/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
UnregisterSignal(organ_owner, COMSIG_ENTER_AREA)
@@ -72,8 +72,7 @@
transmit.Remove(organ_owner)
transmit = initial(transmit)
- if(glass_breaker)
- qdel(glass_breaker)
+ QDEL_NULL(glass_breaker)
/obj/item/organ/brain/voidwalker/proc/on_atom_entering(mob/living/carbon/organ_owner, atom/entering)
SIGNAL_HANDLER
diff --git a/code/modules/fishing/fish/chasm_detritus.dm b/code/modules/fishing/fish/chasm_detritus.dm
index 9595c552e18..50b35f7d074 100644
--- a/code/modules/fishing/fish/chasm_detritus.dm
+++ b/code/modules/fishing/fish/chasm_detritus.dm
@@ -43,11 +43,11 @@ GLOBAL_LIST_INIT_TYPED(chasm_detritus_types, /datum/chasm_detritus, init_chasm_d
),
)
-/datum/chasm_detritus/proc/dispense_detritus(atom/spawn_location, turf/fishing_spot)
+/datum/chasm_detritus/proc/dispense_detritus(atom/spawn_location, atom/fishing_spot)
if(prob(default_contents_chance))
var/default_spawn = pick(default_contents[default_contents_key])
return new default_spawn(spawn_location)
- return find_chasm_contents(fishing_spot, spawn_location)
+ return find_chasm_contents(get_turf(fishing_spot), spawn_location)
/// Returns the chosen detritus from the given list of things to choose from
/datum/chasm_detritus/proc/determine_detritus(list/chasm_stuff)
diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm
index a3e9f255e16..a8fa4d26ad8 100644
--- a/code/modules/fishing/fishing_minigame.dm
+++ b/code/modules/fishing/fishing_minigame.dm
@@ -49,11 +49,13 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
var/reward_path = FISHING_DUD
/// Minigame difficulty
var/difficulty = FISHING_DEFAULT_DIFFICULTY
- // Current phase
+ /// Current phase
var/phase = WAIT_PHASE
- // Timer for the next phase
+ /// Timer for the next phase
var/next_phase_timer
- // The last time we clicked during the baiting phase
+ /// The lower and upper bounds of the waiting phase timer
+ var/list/wait_time_range = list(3 SECONDS, 25 SECONDS)
+ /// The last time we clicked during the baiting phase
var/last_baiting_click
/// Fishing mob
var/mob/user
@@ -126,6 +128,10 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
RegisterSignal(fish_source, COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE, PROC_REF(interrupt_challenge))
fish_source.RegisterSignal(user, COMSIG_MOB_COMPLETE_FISHING, TYPE_PROC_REF(/datum/fish_source, on_challenge_completed))
background = comp.fish_source.background
+ if(comp.fish_source.wait_time_range)
+ wait_time_range = comp.fish_source.wait_time_range
+ if(float.spin_frequency) //Using a fishing lure narrows the range a bit, for better or worse.
+ wait_time_range = list(wait_time_range[1] + 8 SECONDS, wait_time_range[2] - 8 SECONDS)
SEND_SIGNAL(user, COMSIG_MOB_BEGIN_FISHING, src)
SEND_SIGNAL(rod, COMSIG_ROD_BEGIN_FISHING, src)
GLOB.fishing_challenges_by_user[user] = src
@@ -209,7 +215,7 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
/datum/fishing_challenge/proc/start(mob/living/user)
/// Create fishing line visuals
if(!used_rod.internal)
- fishing_line = used_rod.create_fishing_line(float, user, target_py = 5)
+ fishing_line = used_rod.create_fishing_line(float, user, target_py = float.pixel_y + 4)
if(isnull(fishing_line)) //couldn't create a fishing line, probably because we don't have a good line of sight.
qdel(src)
return
@@ -369,7 +375,7 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
if(penalty)
wait_time = min(timeleft(next_phase_timer) + rand(3 SECONDS, 5 SECONDS), 30 SECONDS)
else
- wait_time = float.spin_frequency ? rand(11 SECONDS, 17 SECONDS) : rand(3 SECONDS, 25 SECONDS)
+ wait_time = rand(wait_time_range[1], wait_time_range[2])
if(special_effects & FISHING_MINIGAME_AUTOREEL && wait_time >= 15 SECONDS)
wait_time = max(wait_time - 7.5 SECONDS, 15 SECONDS)
deltimer(next_phase_timer)
@@ -423,6 +429,8 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
send_alert("seed!!!")
if(FISH_ICON_BOTTLE)
send_alert("bottle!!!")
+ if(FISH_ICON_ORGAN)
+ send_alert("organ!!!")
else
send_alert("!!!")
animate(float, pixel_y = 3, time = 5, loop = -1, flags = ANIMATION_RELATIVE)
diff --git a/code/modules/fishing/fishing_portal_machine.dm b/code/modules/fishing/fishing_portal_machine.dm
index 8b2f1a34e93..ad637031556 100644
--- a/code/modules/fishing/fishing_portal_machine.dm
+++ b/code/modules/fishing/fishing_portal_machine.dm
@@ -19,6 +19,8 @@
var/long_range_link = FALSE
/// contains ALL fishing destinations.
var/all_destinations = FALSE
+ /// If the current active fishing spot is from multitool linkage, this value is the atom it would originally belong to.
+ var/atom/current_linked_atom
/obj/machinery/fishing_portal_generator/Initialize(mapload)
. = ..()
@@ -202,7 +204,7 @@
if(machine_stat & NOPOWER)
balloon_alert(user, "no power!")
return ITEM_INTERACT_BLOCKING
- if(!istype(selected_source, /datum/fish_source/portal)) //likely from a linked fishing spot
+ if(!all_destinations && !istype(selected_source, /datum/fish_source/portal)) //likely from a linked fishing spot
var/abort = TRUE
for(var/atom/spot as anything in linked_fishing_spots)
if(linked_fishing_spots[spot] != selected_source)
@@ -215,6 +217,7 @@
abort = FALSE
if(!abort)
RegisterSignal(spot, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_fishing_spot_z_level_changed))
+ current_linked_atom = spot
break
if(abort && !all_destinations)
balloon_alert(user, "cannot reach linked!")
@@ -233,6 +236,7 @@
for(var/atom/spot as anything in linked_fishing_spots)
if(linked_fishing_spots[spot] == active.fish_source)
UnregisterSignal(spot, COMSIG_MOVABLE_Z_CHANGED)
+ current_linked_atom = null
QDEL_NULL(active)
REMOVE_TRAIT(src, TRAIT_CATCH_AND_RELEASE, INNATE_TRAIT)
diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm
index 09ef60c1ff6..9cde6df476a 100644
--- a/code/modules/fishing/sources/_fish_source.dm
+++ b/code/modules/fishing/sources/_fish_source.dm
@@ -60,6 +60,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
))
return_list[FISHING_RANDOM_SEED] = FISH_ICON_SEED
+ return_list[FISHING_RANDOM_ORGAN] = FISH_ICON_ORGAN
return return_list
/**
@@ -93,6 +94,8 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
var/radial_state = "default"
///When selected by the fishing portal, this will be the icon_state of the overlay shown on the machine.
var/overlay_state = "portal_aquarium"
+ ///If set, this overrides the upper and lower bounds of how long you should wait during the waiting phase of the minigame.
+ var/list/wait_time_range
/// Mindless mobs that can fish will never pull up items on this list
var/static/list/profound_fisher_blacklist = typecacheof(list(
@@ -119,6 +122,8 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
for(var/path in fish_counts)
if(!(path in fish_table))
stack_trace("path [path] found in the 'fish_counts' list but not in the 'fish_table'")
+ if(wait_time_range && length(wait_time_range) != 2)
+ stack_trace("wait_time_range for [type] is set but has length different than two")
/datum/fish_source/Destroy()
exploded_turfs = null
@@ -242,15 +247,14 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
UnregisterSignal(user, COMSIG_MOB_COMPLETE_FISHING)
if(!success)
return
- var/turf/fishing_spot = get_turf(challenge.float)
- var/atom/movable/reward = dispense_reward(challenge.reward_path, user, fishing_spot)
+ var/atom/movable/reward = dispense_reward(challenge.reward_path, user, challenge.location)
if(reward)
user.add_mob_memory(/datum/memory/caught_fish, protagonist = user, deuteragonist = reward.name)
SEND_SIGNAL(challenge.used_rod, COMSIG_FISHING_ROD_CAUGHT_FISH, reward, user)
challenge.used_rod.on_reward_caught(reward, user)
/// Gives out the reward if possible
-/datum/fish_source/proc/dispense_reward(reward_path, mob/fisherman, turf/fishing_spot)
+/datum/fish_source/proc/dispense_reward(reward_path, mob/fisherman, atom/fishing_spot)
var/atom/movable/reward = simple_dispense_reward(reward_path, get_turf(fisherman), fishing_spot)
if(!reward) //balloon alert instead
fisherman.balloon_alert(fisherman, pick(duds))
@@ -267,7 +271,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
return reward
///Simplified version of dispense_reward that doesn't need a fisherman.
-/datum/fish_source/proc/simple_dispense_reward(reward_path, atom/spawn_location, turf/fishing_spot)
+/datum/fish_source/proc/simple_dispense_reward(reward_path, atom/spawn_location, atom/fishing_spot)
if(isnull(reward_path))
return null
var/area/area = get_area(fishing_spot)
@@ -298,7 +302,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
addtimer(CALLBACK(src, PROC_REF(regen_count), reward_path), regen_time)
/// Spawns a reward from a atom path right where the fisherman is. Part of the dispense_reward() logic.
-/datum/fish_source/proc/spawn_reward(reward_path, atom/spawn_location, turf/fishing_spot)
+/datum/fish_source/proc/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
if(reward_path == FISHING_DUD)
return
if(ispath(reward_path, /datum/chasm_detritus))
diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm
index e15f290cefe..1828091f061 100644
--- a/code/modules/fishing/sources/source_types.dm
+++ b/code/modules/fishing/sources/source_types.dm
@@ -294,7 +294,7 @@
mover.long_jump_velocity_limit += rand(-100, 100)
///Cherry on top, fish caught from the randomizer portal also have (almost completely) random traits
-/datum/fish_source/portal/random/spawn_reward(reward_path, atom/movable/spawn_location, turf/fishing_spot)
+/datum/fish_source/portal/random/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
if(!ispath(reward_path, /obj/item/fish))
return ..()
@@ -580,7 +580,7 @@
return
return ..()
-/datum/fish_source/hydro_tray/spawn_reward(reward_path, mob/fisherman, turf/fishing_spot)
+/datum/fish_source/hydro_tray/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
if(reward_path != FISHING_RANDOM_SEED)
var/mob/living/created_reward = ..()
if(istype(created_reward))
@@ -649,6 +649,55 @@
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 13
+/datum/fish_source/surgery
+ catalog_description = "Surgery"
+ radial_state = "innards"
+ overlay_state = "portal_syndicate" //Didn't feel like spriting a new overlay. It's just all red anyway.
+ background = "background_lavaland" //Kinda red.
+ fish_table = list(FISHING_RANDOM_ORGAN = 10)
+ //This should get you below zero difficulty and skip the minigame phase, unless you're wearing something that counteracts this.
+ fishing_difficulty = -20
+ //The range for waiting is also a bit narrower, so it cannot take as few as 3 seconds or as many as 25 to snatch an organ.
+ wait_time_range = list(6 SECONDS, 12 SECONDS)
+
+/datum/fish_source/surgery/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
+ if(istype(fishing_spot, /obj/machinery/fishing_portal_generator))
+ var/obj/machinery/fishing_portal_generator/portal = fishing_spot
+ fishing_spot = portal.current_linked_atom
+ if(!iscarbon(fishing_spot))
+ var/random_type = pick(subtypesof(/obj/item/organ) - GLOB.prototype_organs)
+ return new random_type(spawn_location)
+
+ var/mob/living/carbon/carbon = fishing_spot
+ var/list/possible_organs = list()
+ for(var/datum/surgery/organ_manipulation/operation in carbon.surgeries)
+ var/datum/surgery_step/manipulate_organs/manip_step = GLOB.surgery_steps[operation.steps[operation.status]]
+ if(!istype(manip_step))
+ continue
+ for(var/obj/item/organ/organ in operation.operated_bodypart)
+ if(organ.organ_flags & ORGAN_UNREMOVABLE || !manip_step.can_use_organ(organ))
+ continue
+ possible_organs |= organ
+
+ if(!length(possible_organs))
+ return null
+ var/obj/item/organ/chosen = pick(possible_organs)
+ chosen.Remove(chosen.owner)
+ chosen.forceMove(spawn_location)
+ return chosen
+
+/datum/fish_source/surgery/generate_wiki_contents(datum/autowiki/fish_sources/wiki)
+ var/list/data = list()
+
+ data += LIST_VALUE_WRAP_LISTS(list(
+ FISH_SOURCE_AUTOWIKI_NAME = "Organs",
+ FISH_SOURCE_AUTOWIKI_DUD = "",
+ FISH_SOURCE_AUTOWIKI_WEIGHT = 100,
+ FISH_SOURCE_AUTOWIKI_NOTES = "A random organ from an ongoing organ manipulation surgery.",
+ ))
+
+ return data
+
/datum/fish_source/hot_spring
catalog_description = "Hot Springs"
radial_state = "onsen"
diff --git a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm
index d2f6f61251d..2debc004e4d 100644
--- a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm
+++ b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm
@@ -9,11 +9,7 @@ If the scythe isn't empowered when you sheath it, you take a heap of damage and
name = "sinister shard"
desc = "This shard seems to be directly linked to some sinister entity. It might be your god! It also gives you a really horrible rash when you hold onto it for too long."
items_to_create = list(/obj/item/vorpalscythe)
-
-/obj/item/organ/cyberimp/arm/shard/scythe/mob_insert(mob/living/carbon/receiver, special, movement_flags)
- . = ..()
- if(receiver.mind)
- ADD_TRAIT(receiver.mind, TRAIT_MORBID, ORGAN_TRAIT)
+ organ_traits = list(TRAIT_MORBID)
/obj/item/organ/cyberimp/arm/shard/scythe/Retract()
var/obj/item/vorpalscythe/scythe = active_item
diff --git a/code/modules/mining/equipment/monster_organs/monster_organ.dm b/code/modules/mining/equipment/monster_organs/monster_organ.dm
index b6bd54a361e..ccd3a08c19c 100644
--- a/code/modules/mining/equipment/monster_organs/monster_organ.dm
+++ b/code/modules/mining/equipment/monster_organs/monster_organ.dm
@@ -83,7 +83,7 @@
deltimer(decay_timer)
return ..()
-/obj/item/organ/monster_core/mob_insert(mob/living/carbon/target_carbon, special = FALSE, movement_flags)
+/obj/item/organ/monster_core/on_mob_insert(mob/living/carbon/target_carbon, special = FALSE, movement_flags)
. = ..()
if (inert)
@@ -96,7 +96,7 @@
target_carbon.visible_message(span_notice("[src] stabilizes as it's inserted."))
return TRUE
-/obj/item/organ/monster_core/mob_remove(mob/living/carbon/target_carbon, special, movement_flags)
+/obj/item/organ/monster_core/on_mob_remove(mob/living/carbon/target_carbon, special, movement_flags)
if (!inert && !special)
owner.visible_message(span_notice("[src] rapidly decays as it's removed."))
go_inert()
diff --git a/code/modules/mining/equipment/monster_organs/rush_gland.dm b/code/modules/mining/equipment/monster_organs/rush_gland.dm
index cf901269e90..8012286975a 100644
--- a/code/modules/mining/equipment/monster_organs/rush_gland.dm
+++ b/code/modules/mining/equipment/monster_organs/rush_gland.dm
@@ -25,7 +25,7 @@
. = ..()
RegisterSignal(organ_owner, COMSIG_GOLIATH_TENTACLED_GRABBED, PROC_REF(trigger_organ_action_on_sig))
-/obj/item/organ/monster_core/rush_gland/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/monster_core/rush_gland/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
UnregisterSignal(organ_owner, COMSIG_GOLIATH_TENTACLED_GRABBED)
diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm b/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm
index fdc92d06f66..2af3a42c26d 100644
--- a/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm
+++ b/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm
@@ -39,7 +39,7 @@
var/datum/action/cooldown/spell/jaunt/bloodcrawl/crawl = new(heart_owner)
crawl.Grant(heart_owner)
-/obj/item/organ/heart/demon/on_mob_remove(mob/living/carbon/heart_owner, special = FALSE)
+/obj/item/organ/heart/demon/on_mob_remove(mob/living/carbon/heart_owner, special = FALSE, movement_flags)
. = ..()
var/datum/action/cooldown/spell/jaunt/bloodcrawl/crawl = locate() in heart_owner.actions
qdel(crawl)
diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm
index 629d79a76b8..97080bc85f9 100644
--- a/code/modules/mob/living/brain/brain_item.dm
+++ b/code/modules/mob/living/brain/brain_item.dm
@@ -50,7 +50,7 @@
// Brain size logic
transform = transform.Scale(brain_size)
-/obj/item/organ/brain/mob_insert(mob/living/carbon/brain_owner, special = FALSE, movement_flags)
+/obj/item/organ/brain/on_mob_insert(mob/living/carbon/brain_owner, special = FALSE, movement_flags)
. = ..()
if(!.)
return
@@ -106,7 +106,7 @@
if(!special && !(brain_owner.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
brain_owner.update_body_parts()
-/obj/item/organ/brain/mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
+/obj/item/organ/brain/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
// Delete skillchips first as parent proc sets owner to null, and skillchips need to know the brain's owner.
if(!QDELETED(organ_owner) && length(skillchips))
if(!special)
@@ -123,7 +123,7 @@
BT.on_lose(TRUE)
BT.owner = null
- if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !(movement_flags & NO_ID_TRANSFER))
+ if((!QDELETED(src) || !QDELETED(owner)) && !(movement_flags & NO_ID_TRANSFER))
transfer_identity(organ_owner)
if(!special)
if(!(organ_owner.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
@@ -457,12 +457,12 @@
owner.RemoveElement(/datum/element/tenacious)
. = ..()
-/obj/item/organ/brain/lustrous/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/brain/lustrous/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
organ_owner.cure_trauma_type(/datum/brain_trauma/special/bluespace_prophet, TRAUMA_RESILIENCE_ABSOLUTE)
organ_owner.RemoveElement(/datum/element/tenacious)
-/obj/item/organ/brain/lustrous/on_mob_insert(mob/living/carbon/organ_owner, special)
+/obj/item/organ/brain/lustrous/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
organ_owner.gain_trauma(/datum/brain_trauma/special/bluespace_prophet, TRAUMA_RESILIENCE_ABSOLUTE)
organ_owner.AddElement(/datum/element/tenacious)
diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm
index 7db1bb103cc..46bd7bb04f9 100644
--- a/code/modules/mob/living/carbon/alien/organs.dm
+++ b/code/modules/mob/living/carbon/alien/organs.dm
@@ -103,7 +103,7 @@
. = ..()
organ_owner.faction |= ROLE_ALIEN
-/obj/item/organ/alien/hivenode/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE)
+/obj/item/organ/alien/hivenode/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags)
if(organ_owner)
organ_owner.faction -= ROLE_ALIEN
return ..()
@@ -221,11 +221,11 @@
stomach_contents -= source
UnregisterSignal(source, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_DEATH, COMSIG_QDELETING))
-/obj/item/organ/stomach/alien/mob_insert(mob/living/carbon/stomach_owner, special, movement_flags)
+/obj/item/organ/stomach/alien/on_mob_insert(mob/living/carbon/stomach_owner, special, movement_flags)
RegisterSignal(stomach_owner, COMSIG_ATOM_RELAYMOVE, PROC_REF(something_moved))
return ..()
-/obj/item/organ/stomach/alien/mob_remove(mob/living/carbon/stomach_owner, special, movement_flags)
+/obj/item/organ/stomach/alien/on_mob_remove(mob/living/carbon/stomach_owner, special, movement_flags)
UnregisterSignal(stomach_owner, COMSIG_ATOM_RELAYMOVE)
return ..()
diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
index b70139cee05..be65a9a1d3d 100644
--- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
+++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
@@ -78,7 +78,7 @@
for(var/datum/surgery/operations as anything in owner.surgeries)
if(operations.location != BODY_ZONE_CHEST)
continue
- if(!istype(operations.get_surgery_step(), /datum/surgery_step/manipulate_organs/internal))
+ if(!ispath(operations.steps[operations.status], /datum/surgery_step/manipulate_organs/internal))
continue
attempt_grow(gib_on_success = FALSE)
return
diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm
index 9970d973a7d..8e078f9fb80 100644
--- a/code/modules/mob/living/carbon/human/dummy.dm
+++ b/code/modules/mob/living/carbon/human/dummy.dm
@@ -119,6 +119,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
target.dna.features["tail_lizard"] = get_consistent_feature_entry(SSaccessories.tails_list_lizard)
target.dna.features["tail_monkey"] = get_consistent_feature_entry(SSaccessories.tails_list_monkey)
target.dna.features["pod_hair"] = get_consistent_feature_entry(SSaccessories.pod_hair_list)
+ target.dna.features["caps"] = get_consistent_feature_entry(SSaccessories.caps_list)
target.dna.initialize_dna(create_mutation_blocks = FALSE, randomize_features = FALSE)
// UF and UI are nondeterministic, even though the features are the same some blocks will randomize slightly
// In practice this doesn't matter, but this is for the sake of 100%(ish) consistency
diff --git a/code/modules/mod/modules/modules_medical.dm b/code/modules/mod/modules/modules_medical.dm
index 7c0e1c85b05..7c4650ff81a 100644
--- a/code/modules/mod/modules/modules_medical.dm
+++ b/code/modules/mod/modules/modules_medical.dm
@@ -200,13 +200,10 @@
var/mob/living/carbon/human/organ_receiver = target
var/succeed = FALSE
if(organ_receiver.surgeries.len)
- for(var/datum/surgery/procedure as anything in organ_receiver.surgeries)
+ for(var/datum/surgery/organ_manipulation/procedure in organ_receiver.surgeries)
if(procedure.location != organ.zone)
continue
- if(!istype(procedure, /datum/surgery/organ_manipulation))
- continue
- var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
- if(!istype(surgery_step, /datum/surgery_step/manipulate_organs))
+ if(!ispath(procedure.steps[procedure.status], /datum/surgery_step/manipulate_organs))
continue
succeed = TRUE
break
diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm
index a5f4a0505f6..5e6b4bb4b51 100644
--- a/code/modules/surgery/organ_manipulation.dm
+++ b/code/modules/surgery/organ_manipulation.dm
@@ -12,6 +12,38 @@
/datum/surgery_step/close,
)
+//So far, this surgery type should be the only way carbon mobs can be fishing spots, also because the comp doesn't allow dupes.
+/datum/surgery/organ_manipulation/next_step(mob/living/user, modifiers)
+ . = ..()
+ if(!.)
+ return
+ if(!ispath(steps[status], /datum/surgery_step/manipulate_organs))
+ //The manipulate_organs step either hasn't been reached yet or we're already past it.
+ if(!HAS_TRAIT(target, TRAIT_FISHING_SPOT))
+ return
+ remove_fishing_spot()
+ return
+
+ if(HAS_TRAIT(target, TRAIT_FISHING_SPOT))
+ return
+ target.AddComponent(/datum/component/fishing_spot, /datum/fish_source/surgery)
+
+/datum/surgery/organ_manipulation/Destroy()
+ if(HAS_TRAIT(target, TRAIT_FISHING_SPOT) && ispath(steps[status], /datum/surgery_step/manipulate_organs))
+ remove_fishing_spot()
+ return ..()
+
+/**
+ * The target is a fishing spot, but we're past the step that allows us to fish organs from him, so we need
+ * to check if there are other organ manipulation surgeries that still meet this criteria before we remove
+ * the component
+ */
+/datum/surgery/organ_manipulation/proc/remove_fishing_spot()
+ for(var/datum/surgery/organ_manipulation/manipulation in target.surgeries)
+ if(ispath(manipulation.steps[manipulation.status], /datum/surgery_step/manipulate_organs))
+ return
+ qdel(target.GetComponent(/datum/component/fishing_spot))
+
/datum/surgery/organ_manipulation/soft
possible_locs = list(BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
steps = list(
@@ -57,7 +89,7 @@
/datum/surgery/organ_manipulation/mechanic
name = "Hardware Manipulation"
requires_bodypart_type = BODYTYPE_ROBOTIC
- surgery_flags = SURGERY_SELF_OPERABLE | SURGERY_REQUIRE_LIMB
+ surgery_flags = SURGERY_SELF_OPERABLE | SURGERY_REQUIRE_LIMB | SURGERY_CHECK_TOOL_BEHAVIOUR
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)
steps = list(
/datum/surgery_step/mechanic_open,
@@ -69,32 +101,6 @@
/datum/surgery_step/mechanic_close,
)
-/datum/surgery/organ_manipulation/mechanic/next_step(mob/living/user, modifiers)
- if(location != user.zone_selected)
- return FALSE
- if(user.combat_mode)
- return FALSE
- if(step_in_progress)
- return TRUE
-
- var/try_to_fail = FALSE
- if(LAZYACCESS(modifiers, RIGHT_CLICK))
- try_to_fail = TRUE
-
- var/datum/surgery_step/step = get_surgery_step()
- if(isnull(step))
- return FALSE
- var/obj/item/tool = user.get_active_held_item()
- if(tool)
- tool = tool.get_proxy_attacker_for(target, user)
- if(step.try_op(user, target, user.zone_selected, tool, src, try_to_fail))
- return TRUE
- if(tool && tool.tool_behaviour) //Mechanic organ manipulation isn't done with just surgery tools
- to_chat(user, span_warning("This step requires a different tool!"))
- return TRUE
-
- return FALSE
-
/datum/surgery/organ_manipulation/mechanic/soft
possible_locs = list(
BODY_ZONE_PRECISE_GROIN,
@@ -176,7 +182,7 @@
to_chat(user, span_warning("[target_organ] seems to have been chewed on, you can't use this!"))
return SURGERY_STEP_FAIL
- if(!can_use_organ(user, meatslab))
+ if(!can_use_organ(meatslab))
return SURGERY_STEP_FAIL
if (target_zone == BODY_ZONE_PRECISE_EYES)
@@ -196,7 +202,7 @@
var/list/unfiltered_organs = target.get_organs_for_zone(target_zone)
var/list/organs = list()
for(var/organ in unfiltered_organs)
- if(can_use_organ(user, organ))
+ if(can_use_organ(organ))
organs.Add(organ)
if (target_zone == BODY_ZONE_PRECISE_EYES)
target_zone = check_zone(target_zone)
@@ -295,7 +301,7 @@
return ..()
///You can never use this MUHAHAHAHAHAHAH (because its the byond version of abstract)
-/datum/surgery_step/manipulate_organs/proc/can_use_organ(mob/user, obj/item/organ/organ)
+/datum/surgery_step/manipulate_organs/proc/can_use_organ(obj/item/organ/organ)
return FALSE
///Surgery step for internal organs, like hearts and brains
@@ -304,7 +310,7 @@
name = "manipulate organs (hemostat/organ)"
///only operate on internal organs
-/datum/surgery_step/manipulate_organs/internal/can_use_organ(mob/user, obj/item/organ/organ)
+/datum/surgery_step/manipulate_organs/internal/can_use_organ(obj/item/organ/organ)
return !(organ.organ_flags & ORGAN_EXTERNAL)
///prosthetic surgery gives full effectiveness to crowbars (and hemostats)
@@ -318,7 +324,7 @@
name = "manipulate features (hemostat/feature)"
///Only operate on external organs
-/datum/surgery_step/manipulate_organs/external/can_use_organ(mob/user, obj/item/organ/organ)
+/datum/surgery_step/manipulate_organs/external/can_use_organ(obj/item/organ/organ)
return (organ.organ_flags & ORGAN_EXTERNAL)
///prosthetic surgery gives full effectiveness to crowbars (and hemostats)
diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm
index e2f05a9ed56..b8784dfdea0 100644
--- a/code/modules/surgery/organs/_organ.dm
+++ b/code/modules/surgery/organs/_organ.dm
@@ -126,10 +126,6 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
return
owner.remove_status_effect(status, type)
-/obj/item/organ/proc/on_owner_examine(datum/source, mob/user, list/examine_list)
- SIGNAL_HANDLER
- return
-
/obj/item/organ/proc/on_find(mob/living/finder)
return
diff --git a/code/modules/surgery/organs/external/_visual_organs.dm b/code/modules/surgery/organs/external/_visual_organs.dm
index 0b01a174d09..26b089333b2 100644
--- a/code/modules/surgery/organs/external/_visual_organs.dm
+++ b/code/modules/surgery/organs/external/_visual_organs.dm
@@ -212,13 +212,13 @@ Unlike normal organs, we're actually inside a persons limbs at all times
///Store our old datum here for if our antennae are healed
var/original_sprite_datum
-/obj/item/organ/antennae/mob_insert(mob/living/carbon/receiver, special, movement_flags)
+/obj/item/organ/antennae/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
. = ..()
RegisterSignal(receiver, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_antennae))
RegisterSignal(receiver, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_antennae))
-/obj/item/organ/antennae/mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
+/obj/item/organ/antennae/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL))
diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm
index 23c29358a0d..77e0f63e6b0 100644
--- a/code/modules/surgery/organs/external/spines.dm
+++ b/code/modules/surgery/organs/external/spines.dm
@@ -16,13 +16,13 @@
organ_flags = parent_type::organ_flags | ORGAN_EXTERNAL
-/obj/item/organ/spines/mob_insert(mob/living/carbon/receiver, special, movement_flags)
+/obj/item/organ/spines/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
// If we have a tail, attempt to add a tail spines overlay
var/obj/item/organ/tail/our_tail = receiver.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL)
our_tail?.try_insert_tail_spines(our_tail.bodypart_owner)
return ..()
-/obj/item/organ/spines/mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
+/obj/item/organ/spines/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
// If we have a tail, remove any tail spines overlay
var/obj/item/organ/tail/our_tail = organ_owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL)
our_tail?.remove_tail_spines(our_tail.bodypart_owner)
diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm
index 8004f88a680..e6c382387a2 100644
--- a/code/modules/surgery/organs/external/tails.dm
+++ b/code/modules/surgery/organs/external/tails.dm
@@ -22,11 +22,10 @@
///The overlay for tail spines, if any
var/datum/bodypart_overlay/mutant/tail_spines/tail_spines_overlay
-/obj/item/organ/tail/mob_insert(mob/living/carbon/receiver, special, movement_flags)
+/obj/item/organ/tail/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
. = ..()
- if(.)
- receiver.clear_mood_event("tail_lost")
- receiver.clear_mood_event("tail_balance_lost")
+ receiver.clear_mood_event("tail_lost")
+ receiver.clear_mood_event("tail_balance_lost")
if(!special) // if some admin wants to give someone tail moodles for tail shenanigans, they can spawn it and do it by hand
original_owner ||= WEAKREF(receiver)
@@ -77,7 +76,7 @@
bodypart.remove_bodypart_overlay(tail_spines_overlay)
QDEL_NULL(tail_spines_overlay)
-/obj/item/organ/tail/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/tail/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(wag_flags & WAG_WAGGING)
diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm
index f773630f8bf..77589445834 100644
--- a/code/modules/surgery/organs/external/wings/functional_wings.dm
+++ b/code/modules/surgery/organs/external/wings/functional_wings.dm
@@ -33,14 +33,14 @@
QDEL_NULL(fly)
return ..()
-/obj/item/organ/wings/functional/mob_insert(mob/living/carbon/receiver, special, movement_flags)
+/obj/item/organ/wings/functional/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
. = ..()
if(QDELETED(fly))
fly = new
fly.Grant(receiver)
-/obj/item/organ/wings/functional/mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
+/obj/item/organ/wings/functional/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
fly?.Remove(organ_owner)
if(wings_open)
diff --git a/code/modules/surgery/organs/internal/_internal_organ.dm b/code/modules/surgery/organs/internal/_internal_organ.dm
index 0527e6d7980..20b9f8f90f1 100644
--- a/code/modules/surgery/organs/internal/_internal_organ.dm
+++ b/code/modules/surgery/organs/internal/_internal_organ.dm
@@ -14,7 +14,7 @@
STOP_PROCESSING(SSobj, src)
-/obj/item/organ/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE)
+/obj/item/organ/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags)
. = ..()
if((organ_flags & ORGAN_VITAL) && !special && !HAS_TRAIT(organ_owner, TRAIT_GODMODE))
diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm
index 6a1e4272cd5..8b77ef5ec78 100644
--- a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm
+++ b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm
@@ -292,7 +292,7 @@
organ_owner.AddElement(/datum/element/forced_gravity, 1)
add_organ_trait(TRAIT_STURDY_FRAME)
-/obj/item/organ/cyberimp/chest/spine/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/cyberimp/chest/spine/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
remove_organ_trait(TRAIT_BOULDER_BREAKER)
if(stone_overlay)
diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm
index d720953a24c..204247e4de8 100644
--- a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm
+++ b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm
@@ -27,13 +27,13 @@
eye_owner.remove_traits(HUD_traits, ORGAN_TRAIT)
balloon_alert(eye_owner, "hud enabled")
-/obj/item/organ/cyberimp/eyes/hud/mob_insert(mob/living/carbon/eye_owner, special = FALSE, movement_flags)
+/obj/item/organ/cyberimp/eyes/hud/on_mob_insert(mob/living/carbon/eye_owner, special = FALSE, movement_flags)
. = ..()
eye_owner.add_traits(HUD_traits, ORGAN_TRAIT)
toggled_on = TRUE
-/obj/item/organ/cyberimp/eyes/hud/mob_remove(mob/living/carbon/eye_owner, special, movement_flags)
+/obj/item/organ/cyberimp/eyes/hud/on_mob_remove(mob/living/carbon/eye_owner, special, movement_flags)
. = ..()
eye_owner.remove_traits(HUD_traits, ORGAN_TRAIT)
toggled_on = FALSE
diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm
index 850d45df016..3443cf9249e 100644
--- a/code/modules/surgery/organs/internal/ears/_ears.dm
+++ b/code/modules/surgery/organs/internal/ears/_ears.dm
@@ -52,7 +52,7 @@
. = ..()
update_temp_deafness()
-/obj/item/organ/ears/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/ears/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
UnregisterSignal(organ_owner, COMSIG_MOB_SAY)
REMOVE_TRAIT(organ_owner, TRAIT_DEAF, EAR_DAMAGE)
diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm
index d7acaa496da..34ce46bc88b 100644
--- a/code/modules/surgery/organs/internal/eyes/_eyes.dm
+++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm
@@ -50,12 +50,14 @@
/// Scarring on this organ
var/scarring = NONE
-/obj/item/organ/eyes/mob_insert(mob/living/carbon/receiver, special, movement_flags)
+/obj/item/organ/eyes/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
. = ..()
receiver.cure_blind(NO_EYES)
apply_damaged_eye_effects()
refresh(receiver, call_update = TRUE)
RegisterSignal(receiver, COMSIG_ATOM_BULLET_ACT, PROC_REF(on_bullet_act))
+ if (scarring)
+ apply_scarring_effects()
/// Refreshes the visuals of the eyes
/// If call_update is TRUE, we also will call update_body
@@ -80,7 +82,7 @@
if(call_update)
affected_human.update_body()
-/obj/item/organ/eyes/mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
+/obj/item/organ/eyes/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(ishuman(organ_owner))
@@ -260,11 +262,6 @@
owner.cure_blind(EYE_SCARRING_TRAIT)
owner.update_body()
-/obj/item/organ/eyes/on_mob_insert(mob/living/carbon/eye_owner)
- . = ..()
- if (scarring)
- apply_scarring_effects()
-
/obj/item/organ/eyes/on_mob_remove(mob/living/carbon/eye_owner)
. = ..()
if (scarring)
@@ -550,14 +547,11 @@
deactivate(close_ui = TRUE)
/// Set the initial color of the eyes on insert to be the mob's previous eye color.
-/obj/item/organ/eyes/robotic/glow/mob_insert(mob/living/carbon/eye_recipient, special = FALSE, movement_flags = DELETE_IF_REPLACED)
+/obj/item/organ/eyes/robotic/glow/on_mob_insert(mob/living/carbon/eye_recipient, special = FALSE, movement_flags)
. = ..()
left_eye_color_string = eye_color_left
right_eye_color_string = eye_color_right
update_mob_eye_color(eye_recipient)
-
-/obj/item/organ/eyes/robotic/glow/on_mob_insert(mob/living/carbon/eye_recipient)
- . = ..()
deactivate(close_ui = TRUE)
eye.forceMove(eye_recipient)
@@ -860,6 +854,6 @@
apply_organ_damage(-10) //heal quickly
. = ..()
-/obj/item/organ/eyes/night_vision/maintenance_adapted/on_mob_remove(mob/living/carbon/unadapted, special = FALSE)
+/obj/item/organ/eyes/night_vision/maintenance_adapted/on_mob_remove(mob/living/carbon/unadapted, special = FALSE, movement_flags)
REMOVE_TRAIT(unadapted, TRAIT_UNNATURAL_RED_GLOWY_EYES, ORGAN_TRAIT)
return ..()
diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm
index 20ad378529f..c1ebed9afbf 100644
--- a/code/modules/surgery/organs/internal/heart/_heart.dm
+++ b/code/modules/surgery/organs/internal/heart/_heart.dm
@@ -163,7 +163,7 @@
accursed.AddComponent(/datum/component/manual_heart, pump_delay = pump_delay, blood_loss = blood_loss, heal_brute = heal_brute, heal_burn = heal_burn, heal_oxy = heal_oxy)
-/obj/item/organ/heart/cursed/on_mob_remove(mob/living/carbon/accursed, special = FALSE)
+/obj/item/organ/heart/cursed/on_mob_remove(mob/living/carbon/accursed, special = FALSE, movement_flags)
. = ..()
qdel(accursed.GetComponent(/datum/component/manual_heart))
@@ -247,7 +247,7 @@
addtimer(VARSET_CALLBACK(src, stabilization_available, TRUE), 5 MINUTES, TIMER_DELETE_ME)
// Largely a sanity check
-/obj/item/organ/heart/cybernetic/on_mob_remove(mob/living/carbon/heart_owner, special = FALSE)
+/obj/item/organ/heart/cybernetic/on_mob_remove(mob/living/carbon/heart_owner, special = FALSE, movement_flags)
. = ..()
if(HAS_TRAIT_FROM(heart_owner, TRAIT_NOSOFTCRIT, ORGAN_TRAIT))
REMOVE_TRAIT(heart_owner, TRAIT_NOSOFTCRIT, ORGAN_TRAIT)
diff --git a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm
index df60b8243ef..19f0aef7a52 100644
--- a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm
+++ b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm
@@ -28,6 +28,10 @@
///If the core is removable once socketed.
var/core_removable = TRUE
+/obj/item/organ/heart/cybernetic/anomalock/Destroy()
+ QDEL_NULL(core)
+ return ..()
+
/obj/item/organ/heart/cybernetic/anomalock/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(!core)
@@ -39,7 +43,7 @@
RegisterSignal(organ_owner, SIGNAL_ADDTRAIT(TRAIT_CRITICAL_CONDITION), PROC_REF(activate_survival))
RegisterSignal(organ_owner, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act))
-/obj/item/organ/heart/cybernetic/anomalock/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/heart/cybernetic/anomalock/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(!core)
return
diff --git a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm
index 5c6602834cb..0e34fc581c3 100644
--- a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm
+++ b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm
@@ -21,14 +21,14 @@
add_atom_colour(ethereal_color, FIXED_COLOUR_PRIORITY)
update_appearance()
-/obj/item/organ/heart/ethereal/mob_insert(mob/living/carbon/heart_owner, special = FALSE, movement_flags)
+/obj/item/organ/heart/ethereal/on_mob_insert(mob/living/carbon/heart_owner, special = FALSE, movement_flags)
. = ..()
RegisterSignal(heart_owner, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_change))
RegisterSignal(heart_owner, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(on_owner_fully_heal))
RegisterSignal(heart_owner, COMSIG_QDELETING, PROC_REF(owner_deleted))
-/obj/item/organ/heart/ethereal/mob_remove(mob/living/carbon/heart_owner, special, movement_flags)
+/obj/item/organ/heart/ethereal/on_mob_remove(mob/living/carbon/heart_owner, special, movement_flags)
UnregisterSignal(heart_owner, list(COMSIG_MOB_STATCHANGE, COMSIG_LIVING_POST_FULLY_HEAL, COMSIG_QDELETING))
REMOVE_TRAIT(heart_owner, TRAIT_CORPSELOCKED, SPECIES_TRAIT)
stop_crystalization_process(heart_owner)
diff --git a/code/modules/surgery/organs/internal/liver/_liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm
index 866813d02aa..e3d6d517044 100755
--- a/code/modules/surgery/organs/internal/liver/_liver.dm
+++ b/code/modules/surgery/organs/internal/liver/_liver.dm
@@ -60,14 +60,15 @@
qdel(GetComponent(/datum/component/squeak))
/// Registers COMSIG_SPECIES_HANDLE_CHEMICAL from owner
-/obj/item/organ/liver/on_mob_insert(mob/living/carbon/organ_owner, special)
+/obj/item/organ/liver/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
RegisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL, PROC_REF(handle_chemical))
+ RegisterSignal(organ_owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_owner_examine))
/// Unregisters COMSIG_SPECIES_HANDLE_CHEMICAL from owner
-/obj/item/organ/liver/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/liver/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
- UnregisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL)
+ UnregisterSignal(organ_owner, list(COMSIG_SPECIES_HANDLE_CHEMICAL, COMSIG_ATOM_EXAMINE))
/**
* This proc can be overriden by liver subtypes so they can handle certain chemicals in special ways.
@@ -188,7 +189,7 @@
if(SPT_PROB(3, seconds_per_tick))
owner.emote("drool")
-/obj/item/organ/liver/on_owner_examine(datum/source, mob/user, list/examine_list)
+/obj/item/organ/liver/proc/on_owner_examine(datum/source, mob/user, list/examine_list)
if(!ishuman(owner) || !(organ_flags & ORGAN_FAILING))
return
diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm
index 53535cfe131..2a604c46cbc 100644
--- a/code/modules/surgery/organs/internal/lungs/_lungs.dm
+++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm
@@ -154,7 +154,7 @@
add_gas_reaction(/datum/gas/zauker, while_present = PROC_REF(too_much_zauker))
///Simply exists so that you don't keep any alerts from your previous lack of lungs.
-/obj/item/organ/lungs/mob_insert(mob/living/carbon/receiver, special = FALSE, movement_flags)
+/obj/item/organ/lungs/on_mob_insert(mob/living/carbon/receiver, special = FALSE, movement_flags)
. = ..()
receiver.clear_alert(ALERT_NOT_ENOUGH_OXYGEN)
@@ -163,7 +163,7 @@
receiver.clear_alert(ALERT_NOT_ENOUGH_PLASMA)
receiver.clear_alert(ALERT_NOT_ENOUGH_N2O)
-/obj/item/organ/lungs/mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
+/obj/item/organ/lungs/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
// This is very "manual" I realize, but it's useful to ensure cleanup for gases we're removing happens
// Avoids stuck alerts and such
diff --git a/code/modules/surgery/organs/internal/stomach/_stomach.dm b/code/modules/surgery/organs/internal/stomach/_stomach.dm
index 768f3483c03..40d3265684d 100644
--- a/code/modules/surgery/organs/internal/stomach/_stomach.dm
+++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm
@@ -246,13 +246,13 @@
disgusted.throw_alert(ALERT_DISGUST, /atom/movable/screen/alert/disgusted)
disgusted.add_mood_event("disgust", /datum/mood_event/disgusted)
-/obj/item/organ/stomach/mob_insert(mob/living/carbon/receiver, special, movement_flags)
+/obj/item/organ/stomach/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
. = ..()
receiver.hud_used?.hunger?.update_appearance()
-/obj/item/organ/stomach/mob_remove(mob/living/carbon/stomach_owner, special, movement_flags)
+/obj/item/organ/stomach/on_mob_remove(mob/living/carbon/stomach_owner, special, movement_flags)
if(ishuman(stomach_owner))
- var/mob/living/carbon/human/human_owner = owner
+ var/mob/living/carbon/human/human_owner = stomach_owner
human_owner.clear_alert(ALERT_DISGUST)
human_owner.clear_mood_event("disgust")
stomach_owner.hud_used?.hunger?.update_appearance()
diff --git a/code/modules/surgery/organs/internal/stomach/stomach_golem.dm b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm
index c4fa888f6cb..dc6f28787aa 100644
--- a/code/modules/surgery/organs/internal/stomach/stomach_golem.dm
+++ b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm
@@ -11,11 +11,11 @@
/// How slow are you if you have absolutely nothing in the tank?
var/max_hunger_slowdown = 4
-/obj/item/organ/stomach/golem/on_mob_insert(mob/living/carbon/organ_owner, special)
+/obj/item/organ/stomach/golem/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
RegisterSignal(owner, COMSIG_CARBON_ATTEMPT_EAT, PROC_REF(try_eating))
-/obj/item/organ/stomach/golem/on_mob_remove(mob/living/carbon/organ_owner, special)
+/obj/item/organ/stomach/golem/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
UnregisterSignal(organ_owner, COMSIG_CARBON_ATTEMPT_EAT)
organ_owner.remove_movespeed_modifier(/datum/movespeed_modifier/golem_hunger)
diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm
index b94d434a186..dda3530e6b4 100644
--- a/code/modules/surgery/organs/internal/tongue/_tongue.dm
+++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm
@@ -124,7 +124,7 @@
food_taste_reaction = FOOD_LIKED
return food_taste_reaction
-/obj/item/organ/tongue/mob_insert(mob/living/carbon/receiver, special, movement_flags)
+/obj/item/organ/tongue/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
. = ..()
if(modifies_speech)
@@ -138,7 +138,7 @@
REMOVE_TRAIT(receiver, TRAIT_AGEUSIA, NO_TONGUE_TRAIT)
apply_tongue_effects()
-/obj/item/organ/tongue/mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
+/obj/item/organ/tongue/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
temp_say_mod = ""
diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm
index 5d9e9b36f46..fa76c8180cd 100644
--- a/code/modules/surgery/organs/organ_movement.dm
+++ b/code/modules/surgery/organs/organ_movement.dm
@@ -15,12 +15,15 @@
/obj/item/organ/proc/Insert(mob/living/carbon/receiver, special = FALSE, movement_flags)
SHOULD_CALL_PARENT(TRUE)
- mob_insert(receiver, special, movement_flags)
+ if(!mob_insert(receiver, special, movement_flags))
+ return FALSE
bodypart_insert(limb_owner = receiver, movement_flags = movement_flags)
if(!special && !(receiver.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
receiver.update_body_parts()
+ return TRUE
+
/*
* Remove the organ from the select mob.
*
@@ -44,15 +47,17 @@
* movement_flags - Flags for how we behave in movement. See DEFINES/organ_movement for flags
*/
/obj/item/organ/proc/mob_insert(mob/living/carbon/receiver, special, movement_flags)
- SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_OVERRIDE(TRUE)
if(!iscarbon(receiver))
- stack_trace("Tried to insert organ into non-carbon: [receiver.type]")
- return
+ //We try to insert the organ in a corgi when running the test, expecting it to return FALSE.
+ if(!PERFORM_ALL_TESTS(organ_sanity))
+ stack_trace("Tried to insert organ into non-carbon: [receiver.type]")
+ return FALSE
if(owner == receiver)
stack_trace("Organ receiver is already organ owner")
- return
+ return FALSE
var/obj/item/organ/replaced = receiver.get_organ_slot(slot)
if(replaced)
@@ -78,7 +83,7 @@
receiver.organs_slot[slot] = src
owner = receiver
- on_mob_insert(receiver, special)
+ on_mob_insert(receiver, special, movement_flags)
return TRUE
@@ -99,7 +104,6 @@
if(!special)
organ_owner.hud_used?.update_locked_slots()
- RegisterSignal(owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_owner_examine))
SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, organ_owner)
SEND_SIGNAL(organ_owner, COMSIG_CARBON_GAIN_ORGAN, src, special)
@@ -141,7 +145,7 @@
* * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment
*/
/obj/item/organ/proc/mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags)
- SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_OVERRIDE(TRUE)
if(organ_owner)
if(organ_owner.organs_slot[slot] == src)
@@ -150,7 +154,7 @@
owner = null
- on_mob_remove(organ_owner, special)
+ on_mob_remove(organ_owner, special, movement_flags)
return TRUE
@@ -172,7 +176,6 @@
for(var/datum/status_effect/effect as anything in organ_effects)
organ_owner.remove_status_effect(effect, type)
- UnregisterSignal(organ_owner, COMSIG_ATOM_EXAMINE)
SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner)
SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special)
ADD_TRAIT(src, TRAIT_USED_ORGAN, ORGAN_TRAIT)
diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm
index d23267fa326..8b869d3e20b 100644
--- a/code/modules/surgery/surgery.dm
+++ b/code/modules/surgery/surgery.dm
@@ -4,8 +4,7 @@
///The description of the surgery, what it does.
var/desc
- ///From __DEFINES/surgery.dm
- ///Selection: SURGERY_IGNORE_CLOTHES | SURGERY_SELF_OPERABLE | SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB | SURGERY_MORBID_CURIOSITY
+ ///Bitfield for flags that determine different behaviors and requirement for the surgery. See __DEFINES/surgery.dm
var/surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB
///The surgery step we're currently on, increases each time we do a step.
var/status = 1
@@ -120,7 +119,7 @@
if(LAZYACCESS(modifiers, RIGHT_CLICK))
try_to_fail = TRUE
- var/datum/surgery_step/step = get_surgery_step()
+ var/datum/surgery_step/step = GLOB.surgery_steps[steps[status]]
if(isnull(step))
return FALSE
var/obj/item/tool = user.get_active_held_item()
@@ -128,16 +127,15 @@
tool = tool.get_proxy_attacker_for(target, user)
if(step.try_op(user, target, user.zone_selected, tool, src, try_to_fail))
return TRUE
- if(tool && tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it
+ if(!tool)
+ return FALSE
+ //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it
+ if((surgery_flags & SURGERY_CHECK_TOOL_BEHAVIOUR) ? tool.tool_behaviour : (tool.item_flags & SURGICAL_TOOL))
to_chat(user, span_warning("This step requires a different tool!"))
return TRUE
return FALSE
-/datum/surgery/proc/get_surgery_step()
- var/step_type = steps[status]
- return new step_type
-
/datum/surgery/proc/get_surgery_next_step()
if(status < steps.len)
var/step_type = steps[status + 1]
diff --git a/code/modules/unit_tests/organs.dm b/code/modules/unit_tests/organs.dm
index 8f05a284058..cf01436796d 100644
--- a/code/modules/unit_tests/organs.dm
+++ b/code/modules/unit_tests/organs.dm
@@ -10,22 +10,9 @@
var/static/list/species_changing_organs = typecacheof(list(
/obj/item/organ/brain/shadow/nightmare,
))
- // List of organ typepaths which are not test-able, such as certain class prototypes.
- var/static/list/test_organ_blacklist = typecacheof(list(
- /obj/item/organ,
- /obj/item/organ,
- /obj/item/organ/wings,
- /obj/item/organ/cyberimp,
- /obj/item/organ/cyberimp/brain,
- /obj/item/organ/cyberimp/mouth,
- /obj/item/organ/cyberimp/arm,
- /obj/item/organ/cyberimp/chest,
- /obj/item/organ/cyberimp/eyes,
- /obj/item/organ/alien,
- ))
/datum/unit_test/organ_sanity/Run()
- for(var/obj/item/organ/organ_type as anything in subtypesof(/obj/item/organ) - test_organ_blacklist)
+ for(var/obj/item/organ/organ_type as anything in subtypesof(/obj/item/organ) - GLOB.prototype_organs)
organ_test_insert(organ_type)
/datum/unit_test/organ_sanity/proc/organ_test_insert(obj/item/organ/organ_type)
diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm
index 29147aefa94..b31f3ce151b 100644
--- a/code/modules/wiremod/shell/brain_computer_interface.dm
+++ b/code/modules/wiremod/shell/brain_computer_interface.dm
@@ -93,8 +93,6 @@
var/datum/port/output/user_port
- var/datum/weakref/user
-
var/obj/item/organ/cyberimp/bci/bci
/obj/item/circuit_component/bci_core/populate_ports()
@@ -111,19 +109,18 @@
/obj/item/circuit_component/bci_core/proc/update_charge_action()
CIRCUIT_TRIGGER
- var/mob/living/carbon/resolved_owner = user?.resolve()
if (show_charge_meter.value)
if (charge_action)
return
charge_action = new(src)
- if (resolved_owner)
- charge_action.Grant(resolved_owner)
+ if (bci.owner)
+ charge_action.Grant(bci.owner)
bci.actions += charge_action
else
if (!charge_action)
return
- if (resolved_owner)
- charge_action.Remove(resolved_owner)
+ if (bci.owner)
+ charge_action.Remove(bci.owner)
bci.actions -= charge_action
QDEL_NULL(charge_action)
@@ -139,9 +136,8 @@
bci = shell
if (charge_action)
- var/mob/living/carbon/resolved_owner = user?.resolve()
- if (resolved_owner)
- charge_action.Remove(resolved_owner)
+ if (bci.owner)
+ charge_action.Remove(bci.owner)
bci.actions -= charge_action
QDEL_NULL(charge_action)
@@ -158,14 +154,13 @@
if (!sent_message)
return
- var/mob/living/carbon/resolved_owner = user?.resolve()
- if (isnull(resolved_owner))
+ if (isnull(bci.owner))
return
- if (resolved_owner.stat == DEAD)
+ if (bci.owner.stat == DEAD)
return
- to_chat(resolved_owner, "You hear a strange, robotic voice in your head... \"[span_robot("[html_encode(sent_message)]")]\"")
+ to_chat(bci.owner, "You hear a strange, robotic voice in your head... \"[span_robot("[html_encode(sent_message)]")]\"")
/obj/item/circuit_component/bci_core/proc/on_organ_implanted(datum/source, mob/living/carbon/owner)
SIGNAL_HANDLER
@@ -173,7 +168,6 @@
update_charge_action()
user_port.set_output(owner)
- user = WEAKREF(owner)
RegisterSignal(owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
RegisterSignal(owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(on_borg_charge))
@@ -183,7 +177,6 @@
SIGNAL_HANDLER
user_port.set_output(null)
- user = null
UnregisterSignal(owner, list(
COMSIG_ATOM_EXAMINE,
diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm
index f6f21b7e1ee..e524bdee5cb 100644
--- a/code/modules/zombie/organs.dm
+++ b/code/modules/zombie/organs.dm
@@ -23,26 +23,19 @@
GLOB.zombie_infection_list -= src
. = ..()
-/obj/item/organ/zombie_infection/on_mob_insert(mob/living/carbon/M, special = FALSE, movement_flags)
+/obj/item/organ/zombie_infection/on_mob_insert(mob/living/carbon/new_owner, special = FALSE, movement_flags)
. = ..()
-
+ RegisterSignal(new_owner, COMSIG_LIVING_DEATH, PROC_REF(organ_owner_died))
START_PROCESSING(SSobj, src)
-/obj/item/organ/zombie_infection/on_mob_remove(mob/living/carbon/M, special = FALSE)
+/obj/item/organ/zombie_infection/on_mob_remove(mob/living/carbon/new_owner, special = FALSE, movement_flags)
. = ..()
STOP_PROCESSING(SSobj, src)
- if(iszombie(M) && old_species && !special)
- M.set_species(old_species)
+ if(iszombie(new_owner) && old_species && !special)
+ new_owner.set_species(old_species)
if(timer_id)
deltimer(timer_id)
-
-/obj/item/organ/zombie_infection/on_mob_insert(mob/living/carbon/organ_owner, special)
- . = ..()
- RegisterSignal(organ_owner, COMSIG_LIVING_DEATH, PROC_REF(organ_owner_died))
-
-/obj/item/organ/zombie_infection/on_mob_remove(mob/living/carbon/organ_owner, special)
- . = ..()
- UnregisterSignal(organ_owner, COMSIG_LIVING_DEATH)
+ UnregisterSignal(new_owner, COMSIG_LIVING_DEATH)
/obj/item/organ/zombie_infection/proc/organ_owner_died(mob/living/carbon/source, gibbed)
SIGNAL_HANDLER
diff --git a/icons/hud/fishing_hud.dmi b/icons/hud/fishing_hud.dmi
index f9d2d2ff9c4..84f739f9db2 100644
Binary files a/icons/hud/fishing_hud.dmi and b/icons/hud/fishing_hud.dmi differ
diff --git a/icons/hud/radial_fishing.dmi b/icons/hud/radial_fishing.dmi
index 8b914f32613..daa4ce8abda 100644
Binary files a/icons/hud/radial_fishing.dmi and b/icons/hud/radial_fishing.dmi differ
diff --git a/strings/fishing_tips.txt b/strings/fishing_tips.txt
index af67d15e27e..836cab85da5 100644
--- a/strings/fishing_tips.txt
+++ b/strings/fishing_tips.txt
@@ -54,3 +54,4 @@ Fish can grow in size and weight if you fed them somewhat frequently. Giving the
Feeding a fish mutagen can triple the probability of generating evolved offsprings, provided it has an evolution.
You can print fishing rods of different materials from an autolathe, which can inrease or decrease fishing difficulty, casting range, experience gained and can have other, special effects.
Albeit scarcely, it's possible to catch fish made of the same materials of a custom material fishing rod. Equipping a shiny fishing hook and the quality of the bait can improve your odds.
+You can use a fishing rod to snatch random organs during the "manipulate organs" step of the "organ manipulation" surgery.
\ No newline at end of file