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

🆑
Add: You can use a fishing rod to snatch organs during organ
manipulation surgery
/🆑
This commit is contained in:
Ghom
2024-11-20 22:13:18 +00:00
committed by GitHub
parent 538463ffbc
commit 6272b3680c
57 changed files with 286 additions and 215 deletions
+3
View File
@@ -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"
+2
View File
@@ -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)
+6
View File
@@ -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))
+23
View File
@@ -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))
+5 -1
View File
@@ -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)
@@ -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 = ""
@@ -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))
@@ -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
@@ -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
+2 -2
View File
@@ -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()
@@ -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
@@ -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)
@@ -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
@@ -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)
@@ -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)
@@ -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
+2 -2
View File
@@ -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)
+13 -5
View File
@@ -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)
@@ -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)
+9 -5
View File
@@ -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))
+51 -2
View File
@@ -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"
@@ -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
@@ -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()
@@ -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)
@@ -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)
+5 -5
View File
@@ -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)
@@ -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 ..()
@@ -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
@@ -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
+2 -5
View File
@@ -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
+38 -32
View File
@@ -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)
-4
View File
@@ -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
+2 -2
View File
@@ -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))
+2 -2
View File
@@ -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)
+4 -5
View File
@@ -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)
@@ -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)
@@ -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))
@@ -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)
@@ -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
@@ -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)
@@ -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 ..()
@@ -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)
@@ -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
@@ -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)
@@ -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
@@ -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
@@ -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()
@@ -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)
@@ -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 = ""
+13 -10
View File
@@ -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)
+6 -8
View File
@@ -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]
+1 -14
View File
@@ -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)
@@ -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, "<i>You hear a strange, robotic voice in your head...</i> \"[span_robot("[html_encode(sent_message)]")]\"")
to_chat(bci.owner, "<i>You hear a strange, robotic voice in your head...</i> \"[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,
+6 -13
View File
@@ -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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

+1
View File
@@ -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.