From 6272b3680c09b6df7ccecefc10b60978404c4e75 Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Wed, 20 Nov 2024 23:13:18 +0100 Subject: [PATCH] You can use a fishing rod to snatch organs during organ manipulation surgery (feat organs sanity fix) (#87774) ## About The Pull Request This allows you to use a fishing rod during the "manipulate organs" step of the aforementioned surgery to snatch organs from a target. Unlike other fish sources, this one has a negative fishing difficulty of -20, which when summed with the default minigame difficulty should still result in a negative difficulty. In layman terms, this means the minigame is skipped here (unless you're wearing some clunky stuff like insulated or boxing gloves). It also has a wait time of 8 to 13 seconds versus the more random standard 3 to 25 seconds. A small side-effect of this is that explosions during the "manipulate organs" step will basically disembowel you, but it kinda fits anyway. By the by, because of this, there is a tiny chance bluespace fishing rods can yield you random organs. Worry not, they're newly generated, so you won't be snatching it from another player by accident (at least for now). ## Why It's Good For The Game It adds more possible weird and rare shenanigans involving surgery. ## Changelog :cl: Add: You can use a fishing rod to snatch organs during organ manipulation surgery /:cl: --- code/__DEFINES/fish.dm | 3 + code/__DEFINES/organ_movement.dm | 2 + code/__DEFINES/surgery.dm | 6 ++ code/_globalvars/lists/objects.dm | 23 ++++++ code/datums/components/shell.dm | 6 +- .../machinery/computer/operating_computer.dm | 2 +- .../dna_infuser/organ_sets/gondola_organs.dm | 12 +-- .../dna_infuser/organ_sets/rat_organs.dm | 2 +- .../dna_infuser/organ_sets/roach_organs.dm | 8 +- code/game/objects/items/body_egg.dm | 4 +- .../abductor/equipment/abduction_surgery.dm | 4 +- .../antagonists/abductor/equipment/gland.dm | 6 +- .../antagonists/changeling/headslug_eggs.dm | 4 +- .../heretic/items/corrupted_organs.dm | 12 +-- .../antagonists/nightmare/nightmare_organs.dm | 4 +- .../voidwalker/voidwalker_organs.dm | 7 +- code/modules/fishing/fish/chasm_detritus.dm | 4 +- code/modules/fishing/fishing_minigame.dm | 18 +++-- .../modules/fishing/fishing_portal_machine.dm | 6 +- code/modules/fishing/sources/_fish_source.dm | 14 ++-- code/modules/fishing/sources/source_types.dm | 53 ++++++++++++- .../chaplain/chaplain_vorpal_scythe.dm | 6 +- .../equipment/monster_organs/monster_organ.dm | 4 +- .../equipment/monster_organs/rush_gland.dm | 2 +- .../basic/space_fauna/demon/demon_items.dm | 2 +- code/modules/mob/living/brain/brain_item.dm | 10 +-- .../modules/mob/living/carbon/alien/organs.dm | 6 +- .../carbon/alien/special/alien_embryo.dm | 2 +- code/modules/mob/living/carbon/human/dummy.dm | 1 + code/modules/mod/modules/modules_medical.dm | 7 +- code/modules/surgery/organ_manipulation.dm | 70 ++++++++++-------- code/modules/surgery/organs/_organ.dm | 4 - .../surgery/organs/external/_visual_organs.dm | 4 +- .../modules/surgery/organs/external/spines.dm | 4 +- code/modules/surgery/organs/external/tails.dm | 9 +-- .../organs/external/wings/functional_wings.dm | 4 +- .../organs/internal/_internal_organ.dm | 2 +- .../internal/cyberimp/augments_chest.dm | 2 +- .../organs/internal/cyberimp/augments_eyes.dm | 4 +- .../surgery/organs/internal/ears/_ears.dm | 2 +- .../surgery/organs/internal/eyes/_eyes.dm | 18 ++--- .../surgery/organs/internal/heart/_heart.dm | 4 +- .../organs/internal/heart/heart_anomalock.dm | 6 +- .../organs/internal/heart/heart_ethereal.dm | 4 +- .../surgery/organs/internal/liver/_liver.dm | 9 ++- .../surgery/organs/internal/lungs/_lungs.dm | 4 +- .../organs/internal/stomach/_stomach.dm | 6 +- .../organs/internal/stomach/stomach_golem.dm | 4 +- .../surgery/organs/internal/tongue/_tongue.dm | 4 +- code/modules/surgery/organs/organ_movement.dm | 23 +++--- code/modules/surgery/surgery.dm | 14 ++-- code/modules/unit_tests/organs.dm | 15 +--- .../wiremod/shell/brain_computer_interface.dm | 25 +++---- code/modules/zombie/organs.dm | 19 ++--- icons/hud/fishing_hud.dmi | Bin 4920 -> 5503 bytes icons/hud/radial_fishing.dmi | Bin 9844 -> 9928 bytes strings/fishing_tips.txt | 1 + 57 files changed, 286 insertions(+), 215 deletions(-) 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 f9d2d2ff9c4570781f123e4b92feedec8d478bcf..84f739f9db22873aa9e84180bbde481ce0134cd4 100644 GIT binary patch literal 5503 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 GEB^$48L4Fe literal 4920 zcmc&%dpOi--=7&Yb_RoTsAOn6I1Hmrh>TORR;&sk4E0#4mdPP!GojcdHX`IuYHL%W z!zMK2oHf;igq&t#9C8>2!yL>!_l(`%-RIipy59G%*LD5O?{|NX_vd@M@1I;<9OMz3 z5D*AN-tpW0hrur$0)ZLHt^;o+mxIP35U5?On`gxS!0;1c!Gwt5&=3eD`o^_uw2($4 zxmMcD5jR57FRD5@O@`}Felqfd=70FnvQv8dy5@dtze0aN+tM3HoQN%2Fpe7}&v5$2 z67u{y;9(|lzpK(>3I^^ma3*6b+^a|&|0IuM9b zrQ?1Zx9E>EgEnc$me0SM7pX@@HH;YLY_#jV9nf$<9er+o@7%t-$34G0sSUO3x9fwa z_c|r?HT_`s8*aMARmaZePU;T<$x^dBT#YWg>qu^Vr+H?eP`%04(dV1p>Pl4l9r|p5 z!x66qv@T&XQSd?ZpqY2vPe?0qej^%*BBKpN`Ygel_X4Zc zx!|XQe=W7Y7o2(L`;!;>;lsl9)b0>GS|{Meje&??{R#)n_a!BMO`i@b_v{@o*pqy zEeo=H&35>(t5|6l747vZ`am;=_^&M^8YM_NFU0YTJ1j({2AV`+Q{E|haWQl$l>))}I{w&G92m1k`>Pzv| z_l#J5;BSXq`8>QDzOpFHL>9HuOURt1xon!yb;5XED1|*pm}2lRxSTNJZ8GX|>3AoD z@ow})dOl65Qms7s)d>Ut4rQ@B5);6kQknmYm!*G78qhn>E?(WhBJ-(@*q`Qx;zX`I zr*GmH(Ja-s#0C72zNJWQSX4<6K2PL$Omgx3Zi?z#(e!51x^4Dds)Xt!dw{9W^WeKx z>W})Lc6rM6{P68yn-B_a8OeOe3iX*qp#&x2dh zm89#gWb?Ca!B7MI8|H%TK~;ioek$9`R;Kxe#yP#4FvA(`$vQLb4Fp|ZBi4xLzUtN1 zUE@>>6rwkJxx75(Ug|bS-UvEVc%**QcWF#afFI*{jw|$g9Y(a0O8DM9qZCE+B9|Ox zy;65MZGnjTCXXBQguM_o`(TlUlf%cbd)AAVShxo>Eiqlj8EjG9;*g^DhB#uHIt#h$ zb{pTWIU1j)Z9jzG+RC?;(`5@41IgItEC$~$MbRZb6V&H%GIoDa#bryM=NRgT9R|L+ zfu}nVY0SWaT-nR0toLA2E#mO{RDZB7BSZTLO)+gq)P6E$5^y0Q(wy*m10vp3ji z73F%s*zE_wc@){;f{Pex7-hNRbq6gy(jn`Y$*Kj5BA1iTyidCi=&;G6`yo;b1cw{H zOxnl>Buw8*cDeh+k3*xspSXsr`;@(HGRnMYJaMHg&zT2pse?AZ)$rqv4D% zs6CSrSA_EE_!i!nFRiJf>{3a?#E)kL_zWgeJ7vk(8PzV_cti7LR3Rs$)u*(h;^vh& z1_(!|@l58>M5nQQS>Qe&%7ng=ca2_tL{a9D?(N`@nK4@q)<~HN%y}w4qABf^m_ zS!&TkkJB@^mo{qdXsK2{5dI1!Rjy}Sq+pULTM#96nY(9$hzoAFB_3*7GD-|m z*Wdk|1QD|J?_R%PHFIj+4vTbwcLMw{reuq6q$=N1V9mxhm!=p^=Dt$HYwU`;SmkX6trk%DO`{wGPHt-(yotTbLh zmS7Fh$dYOwC(*6hK#hhX$<9?Ql$3lHP!#EF`pnef(m>~$zQ2>;qy7^8Yx>%tdjTsb z6yVF%3X+B^4lZq`1p$Js&;}?o+?pf>13H1oe<5jPC3pWU;=Kwj{=Ig3x@>hPq7BM) zcq?k?SF`igJaggvlW3^r{)lQ*Cc_hhwj9Lp{b=uzu-02rtx!AM7%Y zFfU3h_~jL@s%uit>Mr_;T=u1sZH|;r%8xRO!s>Oo<3j$a*}!qVb`d>0V`q9U@ilaz zJ*tx{zi-sXis8cW_v@()f%n(07!OpRo9yK-bIvu+9Q&TBW> zTVssja5ST`RKX0>_f+NeW6TdEWKz1W&$*LM)xGcHVN(tNF$8(^F%g$HuxFZd32Kg%THP z1REEQ)(p-L3|_yO*?OhKV=}2Mef($F=HrG)Sqw5!3HAQlUx}AKg!Dwo8RCUo$4U%$ z$H(zqW&;ZgkHV`eq`7RhU6e(u*0+3n!nL+M%C}q%#gj==vABYG?jEw?z45Z&^H`BK z=P%fT{LsPU;G+=spK%tyC}@E-Ne=w4h!)Z^;(QVF=3qhY(m^V%Y2<>u28l!vYZQ(O zdaM!`4h{tdp=YcZB=$e2NI`-u0%NhfOjK(`z;kGS%aLFKEDXX;p8%;yC)J0UtBV;< zMHqqPUrT+B%Ti%l3cu|GiNp*Cr9_g{ghFe>DA?2viEA1M!FK&Mz6JlaB;K{zNQii$ zkC_%cOYA>&lB8ix7Hry*CDoQkgEFb(BnT)xE-1RceZL8>N8$R~Rtst2Dwb$hvcR5- zeMpK^E4jG2$8d{EIJHxC%DsHyr{++@42S;o`?$ z9un_mJ2TE%-QNpkb3QO=a`Z3#P^F4XESLRq(JllQ{@eXHn5+H z4(MJIK-HBDdYafh+CP0uSU~{(l2L0>`b#uGv?Og&lDFa%T(eXEKl;S>{!xk8_!?21 z_z;ORo&xoiKB{$qv-4;X zLql6HWXkQ7cydhXGK!5Wx4RK1t{JLrZDA*zOk_T)+wB zrGYFkEp`mF7RejzFJE8S|Eo(9Qw!&0FNKK@jckTZZs2&{Qq9Ct>?%^tFy+Wymxu0x z-O-A+o+#}UFlfeVNE(%Of*Pu6Y*YEv>1fV$Uq>W?(RiVS8saVJ z@RBq8z|0#cTm4Ssfi5@IYQr$R$QG!yDxzTD#d&|~q_ z(%N97)=Cvj!DfBqH--4rMobGpS72}+-t8dzJGavwPYc@Q{Vm;SyvySb26$QR>Dk$f z9_8+RjF79_;O+xo@hs^#zTrusk2UKl)HY7=G7^25J>S$My6^Jo11G@5>exe>*54hg zcPgQ%&d$sntizZ%Q_*MZ@1tx|^`i*UUu&q&mA2b!8VoXc?w=A~`c+uP_HMC=y3;?C z%OQUFOV;XF=yIE`{W^7sHqU;QxXp;A7!eh<+^gsARqs*$%!Ef#1IL(C=F+}yk9=Ny z@*sT#CvYPya-~HLFNpa_oa=PLa>GxQPRn2plf7`LdZb3u(95{x7e^o}s&i~6l~x41 zS4zrOr76QyHV`^LdD+&(V5*ANw_#VX#Z0MFI;9Svfg#tc2t=vImEtT5 zaBDT4+^AHHl10jbD-n3=!JSSl|4ys}Tvx$E0=FcRj5N5ZN@GBt8fY0Uz*K#$^kw(! z(3#Y{roq}MWDzW_l4S2BD={r*)`Ez&LB#S9u@qFS8U`+E&^1eL?Hx{sBWed5v5se% z?J8JDXwC~#lL{sbp=AqwsVN5}kYAW3vSLT1#mj#&LQ4AM8gj3Sq!|r8g(-#mkv1XB zg6A>XV5>U~{Cu5y!36iHr=*3l#={#3 z@$;WO$xZAFij6gBrQFA)$bE={qht*A0lENRe~Y#3+Q7GcppVYIP-YsGuXYht=jM(J meVb&y*D@5J)!p>XJn^@6ezm^|d%_{$&(Ypx|07%fq<;g6BgRDl diff --git a/icons/hud/radial_fishing.dmi b/icons/hud/radial_fishing.dmi index 8b914f32613bed4211f442e0051185600325c9a2..daa4ce8abda3e0cb0b16b8a0252808e20c8c390a 100644 GIT binary patch literal 9928 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 literal 9844 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 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