mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-09 15:15:34 +01:00
152 lines
6.3 KiB
Plaintext
152 lines
6.3 KiB
Plaintext
/// Item can be applied to mobs to prepare them for surgery (allowing people to operate on them)
|
|
/datum/element/surgery_aid
|
|
element_flags = ELEMENT_BESPOKE
|
|
argument_hash_start_idx = 2
|
|
/// The name of the aid, for examine and messages, in plural form
|
|
var/aid_name
|
|
|
|
/datum/element/surgery_aid/Attach(datum/target, aid_name = "things")
|
|
. = ..()
|
|
if(!isitem(target))
|
|
return ELEMENT_INCOMPATIBLE
|
|
|
|
src.aid_name = aid_name
|
|
RegisterSignal(target, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, PROC_REF(on_context))
|
|
RegisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(on_item_interaction))
|
|
|
|
var/obj/item/realtarget = target
|
|
realtarget.item_flags |= ITEM_HAS_CONTEXTUAL_SCREENTIPS
|
|
|
|
/datum/element/surgery_aid/Detach(datum/target)
|
|
. = ..()
|
|
UnregisterSignal(target, list(COMSIG_ITEM_INTERACTING_WITH_ATOM, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET))
|
|
|
|
/datum/element/surgery_aid/proc/on_context(obj/item/source, list/context, atom/target, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!isliving(target))
|
|
return NONE
|
|
|
|
var/mob/living/target_mob = target
|
|
if(!target_mob.has_limbs)
|
|
context[SCREENTIP_CONTEXT_LMB] = HAS_TRAIT(source, TRAIT_READY_TO_OPERATE) ? "Remove [aid_name]" : "Prepare for surgery"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
var/obj/item/bodypart/precise_part = target_mob.get_bodypart(deprecise_zone(user.zone_selected)) || target_mob.get_bodypart(BODY_ZONE_CHEST)
|
|
context[SCREENTIP_CONTEXT_LMB] = HAS_TRAIT(precise_part, TRAIT_READY_TO_OPERATE) ? "Remove [aid_name]" : "Prepare [precise_part.plaintext_zone] for surgery"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/datum/element/surgery_aid/proc/on_item_interaction(datum/source, mob/living/user, atom/target, ...)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!isliving(target))
|
|
return NONE
|
|
|
|
var/mob/living/target_mob = target
|
|
var/obj/item/bodypart/precise_part = target_mob.get_bodypart(deprecise_zone(user.zone_selected)) || target_mob.get_bodypart(BODY_ZONE_CHEST)
|
|
surgery_prep(target_mob, user, precise_part?.body_zone || BODY_ZONE_CHEST, aid_name)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/datum/element/surgery_aid/proc/surgery_prep(mob/living/target_mob, mob/living/surgeon, body_zone)
|
|
var/datum/status_effect/surgery_prepped/prep = target_mob.has_status_effect(__IMPLIED_TYPE__)
|
|
if(isnull(prep) || !(body_zone in prep.zones))
|
|
target_mob.apply_status_effect(/datum/status_effect/surgery_prepped, body_zone, aid_name)
|
|
target_mob.balloon_alert(surgeon, "[parse_zone(body_zone)] surgery prepared")
|
|
return
|
|
prep.untrack_surgery(body_zone)
|
|
target_mob.balloon_alert(surgeon, "surgery cleared")
|
|
|
|
/// Tracks which body zones have been prepped for surgery
|
|
/datum/status_effect/surgery_prepped
|
|
id = "surgery_prepped"
|
|
alert_type = null
|
|
status_type = STATUS_EFFECT_REFRESH
|
|
processing_speed = STATUS_EFFECT_NORMAL_PROCESS
|
|
tick_interval = 2 SECONDS
|
|
|
|
/// Lazylist of zones being prepped, if empty we should not exist
|
|
var/list/zones
|
|
/// Lazylist of the names of all surgical aids used, for examine
|
|
var/list/surgical_aids
|
|
/// Counts movements while standing up - removes the effect if we move too much
|
|
var/movement_counter = 0
|
|
|
|
/datum/status_effect/surgery_prepped/on_creation(mob/living/new_owner, target_zone, aid_name = "things")
|
|
. = ..()
|
|
track_surgery(target_zone)
|
|
LAZYOR(surgical_aids, aid_name)
|
|
ADD_TRAIT(owner, TRAIT_READY_TO_OPERATE, TRAIT_STATUS_EFFECT(id)) // needs to happen after tracking starts
|
|
|
|
/datum/status_effect/surgery_prepped/refresh(mob/living/new_owner, target_zone, aid_name = "things")
|
|
track_surgery(target_zone)
|
|
LAZYOR(surgical_aids, aid_name)
|
|
|
|
/datum/status_effect/surgery_prepped/on_apply()
|
|
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
|
|
RegisterSignal(owner, COMSIG_CARBON_POST_ATTACH_LIMB, PROC_REF(on_attach_limb))
|
|
RegisterSignal(owner, COMSIG_CARBON_POST_REMOVE_LIMB, PROC_REF(on_detach_limb))
|
|
return TRUE
|
|
|
|
/datum/status_effect/surgery_prepped/on_remove()
|
|
for(var/zone in zones)
|
|
untrack_surgery(zone)
|
|
REMOVE_TRAIT(owner, TRAIT_READY_TO_OPERATE, TRAIT_STATUS_EFFECT(id))
|
|
UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_POST_ATTACH_LIMB, COMSIG_CARBON_POST_REMOVE_LIMB))
|
|
|
|
/datum/status_effect/surgery_prepped/get_examine_text()
|
|
var/list/zones_readable = list()
|
|
// give the body zones a consistent order, the same order as GLOB.all_body_zones
|
|
for(var/zone in GLOB.all_body_zones & zones)
|
|
zones_readable += parse_zone(zone)
|
|
|
|
var/list/aid_readable = list()
|
|
for(var/aid in surgical_aids)
|
|
aid_readable += copytext_char(aid, -1) == "s" ? aid : "\a [aid]"
|
|
|
|
// "They have surgial drapes and a bedsheet adorning their chest, arms, and legs."
|
|
return "[owner.p_They()] [owner.p_have()] [english_list(aid_readable)] adorning [owner.p_their()] [english_list(zones_readable)]."
|
|
|
|
/datum/status_effect/surgery_prepped/proc/on_move(datum/source, ...)
|
|
SIGNAL_HANDLER
|
|
|
|
if(owner.body_position == STANDING_UP)
|
|
movement_counter += 1
|
|
if(movement_counter < 4)
|
|
return
|
|
// "The surgical drapes and bedsheets adorning John fall off!"
|
|
owner.visible_message(span_warning("The [english_list(surgical_aids)] adorning [owner] fall off!"))
|
|
qdel(src)
|
|
|
|
/datum/status_effect/surgery_prepped/proc/on_attach_limb(datum/source, obj/item/bodypart/limb)
|
|
SIGNAL_HANDLER
|
|
|
|
if(limb.body_zone in zones)
|
|
ADD_TRAIT(limb, TRAIT_READY_TO_OPERATE, TRAIT_STATUS_EFFECT(id))
|
|
|
|
/datum/status_effect/surgery_prepped/proc/on_detach_limb(datum/source, obj/item/bodypart/limb)
|
|
SIGNAL_HANDLER
|
|
|
|
REMOVE_TRAIT(limb, TRAIT_READY_TO_OPERATE, TRAIT_STATUS_EFFECT(id))
|
|
|
|
/datum/status_effect/surgery_prepped/tick(seconds_between_ticks)
|
|
if(owner.body_position == LYING_DOWN && movement_counter > 0)
|
|
movement_counter -= 1
|
|
|
|
/datum/status_effect/surgery_prepped/proc/track_surgery(body_zone)
|
|
LAZYADD(zones, body_zone)
|
|
if(iscarbon(owner))
|
|
var/obj/item/bodypart/precise_part = owner.get_bodypart(body_zone)
|
|
if(precise_part)
|
|
ADD_TRAIT(precise_part, TRAIT_READY_TO_OPERATE, TRAIT_STATUS_EFFECT(id))
|
|
else if(body_zone != BODY_ZONE_CHEST)
|
|
stack_trace("Attempting to track surgery on a non-carbon mob with a non-chest body zone! This should not happen.")
|
|
|
|
/datum/status_effect/surgery_prepped/proc/untrack_surgery(body_zone)
|
|
LAZYREMOVE(zones, body_zone)
|
|
if(iscarbon(owner))
|
|
var/obj/item/bodypart/precise_part = owner.get_bodypart(body_zone)
|
|
if(precise_part)
|
|
REMOVE_TRAIT(precise_part, TRAIT_READY_TO_OPERATE, TRAIT_STATUS_EFFECT(id))
|
|
if(!LAZYLEN(zones) && !QDELETED(src))
|
|
qdel(src) // no more zones to track, remove the status effect
|