mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 04:30:44 +01:00
Merge branch 'master' into movespeed_modifiers_take_two
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
|
||||
/datum/surgery_step/sever_limb
|
||||
name = "sever limb"
|
||||
implements = list(/obj/item/shears = 300, TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/arm_blade = 80, /obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25)
|
||||
implements = list(/obj/item/shears = 300, TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/arm_blade = 80, /obj/item/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25)
|
||||
time = 64
|
||||
experience_given = MEDICAL_SKILL_ORGAN_FIX
|
||||
|
||||
|
||||
@@ -87,14 +87,16 @@
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(HAS_TRAIT(C, TRAIT_LIMBATTACHMENT))
|
||||
if(!H.get_bodypart(body_zone) && !animal_origin)
|
||||
user.temporarilyRemoveItemFromInventory(src, TRUE)
|
||||
if(!attach_limb(C))
|
||||
to_chat(user, "<span class='warning'>[H]'s body rejects [src]!</span>")
|
||||
forceMove(H.loc)
|
||||
if(H == user)
|
||||
H.visible_message("<span class='warning'>[H] jams [src] into [H.p_their()] empty socket!</span>",\
|
||||
"<span class='notice'>You force [src] into your empty socket, and it locks into place!</span>")
|
||||
else
|
||||
H.visible_message("<span class='warning'>[user] jams [src] into [H]'s empty socket!</span>",\
|
||||
"<span class='notice'>[user] forces [src] into your empty socket, and it locks into place!</span>")
|
||||
user.temporarilyRemoveItemFromInventory(src, TRUE)
|
||||
attach_limb(C)
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
@@ -90,8 +90,11 @@
|
||||
C.bodyparts -= src
|
||||
|
||||
if(held_index)
|
||||
C.dropItemToGround(owner.get_item_for_held_index(held_index), 1)
|
||||
C.hand_bodyparts[held_index] = null
|
||||
if(C.hand_bodyparts[held_index] == src)
|
||||
// We only want to do this if the limb being removed is the active hand part.
|
||||
// This catches situations where limbs are "hot-swapped" such as augmentations and roundstart prosthetics.
|
||||
C.dropItemToGround(owner.get_item_for_held_index(held_index), 1)
|
||||
C.hand_bodyparts[held_index] = null
|
||||
|
||||
owner = null
|
||||
|
||||
@@ -259,23 +262,25 @@
|
||||
/obj/item/bodypart/proc/replace_limb(mob/living/carbon/C, special)
|
||||
if(!istype(C))
|
||||
return
|
||||
var/obj/item/bodypart/O = C.get_bodypart(body_zone)
|
||||
var/obj/item/bodypart/O = C.get_bodypart(body_zone) //needs to happen before attach because multiple limbs in same zone breaks helpers
|
||||
if(!attach_limb(C, special))//we can attach this limb and drop the old after because of our robust bodyparts system. you know, just for a sec.
|
||||
return
|
||||
if(O)
|
||||
O.drop_limb(1)
|
||||
attach_limb(C, special)
|
||||
|
||||
/obj/item/bodypart/head/replace_limb(mob/living/carbon/C, special)
|
||||
if(!istype(C))
|
||||
return
|
||||
var/obj/item/bodypart/head/O = C.get_bodypart(body_zone)
|
||||
if(!attach_limb(C, special))
|
||||
return
|
||||
if(O)
|
||||
if(!special)
|
||||
return
|
||||
else
|
||||
O.drop_limb(1)
|
||||
attach_limb(C, special)
|
||||
O.drop_limb(1)
|
||||
|
||||
/obj/item/bodypart/proc/attach_limb(mob/living/carbon/C, special)
|
||||
if(SEND_SIGNAL(C, COMSIG_LIVING_ATTACH_LIMB, src, special) & COMPONENT_NO_ATTACH)
|
||||
return FALSE
|
||||
. = TRUE
|
||||
moveToNullspace()
|
||||
owner = C
|
||||
C.bodyparts += src
|
||||
@@ -312,7 +317,10 @@
|
||||
C.update_mobility()
|
||||
|
||||
|
||||
/obj/item/bodypart/head/attach_limb(mob/living/carbon/C, special)
|
||||
/obj/item/bodypart/head/attach_limb(mob/living/carbon/C, special = FALSE, abort = FALSE)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return .
|
||||
//Transfer some head appearance vars over
|
||||
if(brain)
|
||||
if(brainmob)
|
||||
@@ -350,19 +358,22 @@
|
||||
AP.Grant(C)
|
||||
break
|
||||
|
||||
..()
|
||||
|
||||
C.updatehealth()
|
||||
C.update_body()
|
||||
C.update_hair()
|
||||
C.update_damage_overlays()
|
||||
C.update_mobility()
|
||||
|
||||
//Regenerates all limbs. Returns amount of limbs regenerated
|
||||
/mob/living/proc/regenerate_limbs(noheal = FALSE, list/excluded_limbs = list())
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_REGENERATE_LIMBS, noheal, excluded_limbs)
|
||||
/mob/living/proc/regenerate_limbs(noheal = FALSE, list/excluded_zones = list())
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_REGENERATE_LIMBS, noheal, excluded_zones)
|
||||
|
||||
/mob/living/carbon/regenerate_limbs(noheal = FALSE, list/excluded_limbs = list())
|
||||
/mob/living/carbon/regenerate_limbs(noheal = FALSE, list/excluded_zones = list())
|
||||
. = ..()
|
||||
var/list/limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
|
||||
if(length(excluded_limbs))
|
||||
limb_list -= excluded_limbs
|
||||
for(var/Z in limb_list)
|
||||
var/list/zone_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
|
||||
if(length(excluded_zones))
|
||||
zone_list -= excluded_zones
|
||||
for(var/Z in zone_list)
|
||||
. += regenerate_limb(Z, noheal)
|
||||
|
||||
/mob/living/proc/regenerate_limb(limb_zone, noheal)
|
||||
@@ -371,7 +382,7 @@
|
||||
/mob/living/carbon/regenerate_limb(limb_zone, noheal)
|
||||
var/obj/item/bodypart/L
|
||||
if(get_bodypart(limb_zone))
|
||||
return 0
|
||||
return FALSE
|
||||
L = newBodyPart(limb_zone, 0, 0)
|
||||
if(L)
|
||||
if(!noheal)
|
||||
@@ -380,5 +391,7 @@
|
||||
L.brutestate = 0
|
||||
L.burnstate = 0
|
||||
|
||||
L.attach_limb(src, 1)
|
||||
return 1
|
||||
if(!L.attach_limb(src, 1))
|
||||
qdel(L)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
body_plan_changed = TRUE
|
||||
O.drop_limb(1)
|
||||
qdel(O)
|
||||
N.attach_limb(src)
|
||||
N.attach_limb(src) //no sanity for if this fails here because we just dropped out a limb of the same zone, SHOULD be okay
|
||||
if(body_plan_changed && ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
if(H.w_uniform)
|
||||
|
||||
@@ -48,12 +48,11 @@
|
||||
"<span class='notice'>[user] attempts to patch some of [target]'s [woundtype].</span>")
|
||||
|
||||
/datum/surgery_step/heal/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
|
||||
if(..())
|
||||
experience_given = min(experience_given+1,PER_ITERATION_XP_CAP)
|
||||
while((brutehealing && target.getBruteLoss()) || (burnhealing && target.getFireLoss()))
|
||||
if(!..())
|
||||
break
|
||||
experience_given = min(experience_given+1,PER_ITERATION_XP_CAP)
|
||||
if(!..())
|
||||
return
|
||||
while((brutehealing && target.getBruteLoss()) || (burnhealing && target.getFireLoss()))
|
||||
if(!..())
|
||||
break
|
||||
|
||||
/datum/surgery_step/heal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
|
||||
var/umsg = "You succeed in fixing some of [target]'s wounds" //no period, add initial space to "addons"
|
||||
@@ -72,7 +71,7 @@
|
||||
urhealedamt_burn *= 0.55
|
||||
umsg += " as best as you can while they have clothing on"
|
||||
tmsg += " as best as they can while [target] has clothing on"
|
||||
target.heal_bodypart_damage(urhealedamt_brute,urhealedamt_burn)
|
||||
experience_given = CEILING((target.heal_bodypart_damage(urhealedamt_brute,urhealedamt_burn)/5),1)
|
||||
display_results(user, target, "<span class='notice'>[umsg].</span>",
|
||||
"[tmsg].",
|
||||
"[tmsg].")
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
/datum/surgery_step/saw
|
||||
name = "saw bone"
|
||||
implements = list(TOOL_SAW = 100,/obj/item/melee/arm_blade = 75,
|
||||
/obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 35, /obj/item/kitchen/knife/butcher = 25, /obj/item = 20) //20% success (sort of) with any sharp item with a force>=10
|
||||
/obj/item/fireaxe = 50, /obj/item/hatchet = 35, /obj/item/kitchen/knife/butcher = 25, /obj/item = 20) //20% success (sort of) with any sharp item with a force>=10
|
||||
time = 54
|
||||
|
||||
/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
if(M)
|
||||
M.adjustToxLoss(4, TRUE, TRUE) //forced to ensure people don't use it to gain tox as slime person
|
||||
|
||||
/obj/item/organ/appendix/get_availability(datum/species/S)
|
||||
return !(TRAIT_NOHUNGER in S.species_traits)
|
||||
|
||||
/obj/item/organ/appendix/Remove(mob/living/carbon/M, special = 0)
|
||||
for(var/datum/disease/appendicitis/A in M.diseases)
|
||||
A.cure()
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
. = ..()
|
||||
if(!ion_trail)
|
||||
ion_trail = new
|
||||
ion_trail.auto_process = FALSE
|
||||
ion_trail.set_up(M)
|
||||
|
||||
/obj/item/organ/cyberimp/chest/thrusters/Remove(mob/living/carbon/M, special = 0)
|
||||
@@ -148,17 +149,19 @@
|
||||
if(!silent)
|
||||
to_chat(owner, "<span class='warning'>Your thrusters set seems to be broken!</span>")
|
||||
return 0
|
||||
on = TRUE
|
||||
if(allow_thrust(0.01))
|
||||
on = TRUE
|
||||
ion_trail.start()
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/move_react)
|
||||
owner.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/cybernetic)
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE, .proc/pre_move_react)
|
||||
if(!silent)
|
||||
to_chat(owner, "<span class='notice'>You turn your thrusters set on.</span>")
|
||||
else
|
||||
ion_trail.stop()
|
||||
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
|
||||
owner.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/cybernetic)
|
||||
UnregisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE)
|
||||
if(!silent)
|
||||
to_chat(owner, "<span class='notice'>You turn your thrusters set off.</span>")
|
||||
on = FALSE
|
||||
@@ -171,26 +174,44 @@
|
||||
icon_state = "imp_jetpack"
|
||||
|
||||
/obj/item/organ/cyberimp/chest/thrusters/proc/move_react()
|
||||
allow_thrust(0.01)
|
||||
if(!on)//If jet dont work, it dont work
|
||||
return
|
||||
if(!owner)//Don't allow jet self using
|
||||
return
|
||||
if(!isturf(owner.loc))//You can't use jet in nowhere or in mecha/closet
|
||||
return
|
||||
if(!(owner.is_flying() || owner.is_floating()) || owner.buckled)//You don't want use jet in gravity or while buckled.
|
||||
return
|
||||
if(owner.pulledby)//You don't must use jet if someone pull you
|
||||
return
|
||||
if(owner.throwing)//You don't must use jet if you thrown
|
||||
return
|
||||
if(length(owner.client.keys_held & owner.client.movement_keys))//You use jet when press keys. yes.
|
||||
allow_thrust(0.01)
|
||||
|
||||
/obj/item/organ/cyberimp/chest/thrusters/proc/pre_move_react()
|
||||
ion_trail.oldposition = get_turf(owner)
|
||||
|
||||
/obj/item/organ/cyberimp/chest/thrusters/proc/allow_thrust(num)
|
||||
if(!on || !owner)
|
||||
return 0
|
||||
if(!owner)
|
||||
return FALSE
|
||||
|
||||
var/turf/T = get_turf(owner)
|
||||
if(!T) // No more runtimes from being stuck in nullspace.
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
// Priority 1: use air from environment.
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
if(environment && environment.return_pressure() > 30)
|
||||
return 1
|
||||
ion_trail.generate_effect()
|
||||
return TRUE
|
||||
|
||||
// Priority 2: use plasma from internal plasma storage.
|
||||
// (just in case someone would ever use this implant system to make cyber-alien ops with jetpacks and taser arms)
|
||||
if(owner.getPlasma() >= num*100)
|
||||
owner.adjustPlasma(-num*100)
|
||||
return 1
|
||||
ion_trail.generate_effect()
|
||||
return TRUE
|
||||
|
||||
// Priority 3: use internals tank.
|
||||
var/obj/item/tank/I = owner.internal
|
||||
@@ -198,9 +219,11 @@
|
||||
var/datum/gas_mixture/removed = I.air_contents.remove(num)
|
||||
if(removed.total_moles() > 0.005)
|
||||
T.assume_air(removed)
|
||||
return 1
|
||||
ion_trail.generate_effect()
|
||||
return TRUE
|
||||
else
|
||||
T.assume_air(removed)
|
||||
ion_trail.generate_effect()
|
||||
|
||||
toggle(silent = TRUE)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
@@ -83,7 +83,6 @@
|
||||
C.clear_fullscreen("eye_damage")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/organ/eyes/night_vision
|
||||
name = "shadow eyes"
|
||||
desc = "A spooky set of eyes that can see in the dark."
|
||||
|
||||
@@ -91,6 +91,9 @@
|
||||
owner.set_heartattack(TRUE)
|
||||
failed = TRUE
|
||||
|
||||
/obj/item/organ/heart/get_availability(datum/species/S)
|
||||
return !(NOBLOOD in S.species_traits)
|
||||
|
||||
/obj/item/organ/heart/cursed
|
||||
name = "cursed heart"
|
||||
desc = "A heart that, when inserted, will force you to pump it manually."
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
/mob/proc/getorganszone(zone)
|
||||
return
|
||||
/**
|
||||
* Get an organ relating to a specific slot
|
||||
* Returns a list of all organs in specified slot
|
||||
*
|
||||
* Arguments:
|
||||
* * slot Slot to get the organ from
|
||||
* * slot Slot to get the organs from
|
||||
*/
|
||||
/mob/proc/getorganslot(slot)
|
||||
return
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
#undef HAS_NO_TOXIN
|
||||
#undef HAS_PAINFUL_TOXIN
|
||||
|
||||
/obj/item/organ/liver/get_availability(datum/species/S)
|
||||
return !(TRAIT_NOMETABOLISM in S.species_traits)
|
||||
|
||||
/obj/item/organ/liver/fly
|
||||
name = "insectoid liver"
|
||||
icon_state = "liver-x" //xenomorph liver? It's just a black liver so it fits.
|
||||
|
||||
@@ -409,6 +409,8 @@
|
||||
owner.visible_message("<span class='danger'>[owner] grabs [owner.p_their()] throat, struggling for breath!</span>", "<span class='userdanger'>You suddenly feel like you can't breathe!</span>")
|
||||
failed = TRUE
|
||||
|
||||
/obj/item/organ/lungs/get_availability(datum/species/S)
|
||||
return !(TRAIT_NOBREATH in S.species_traits)
|
||||
|
||||
/obj/item/organ/lungs/plasmaman
|
||||
name = "plasma filter"
|
||||
|
||||
@@ -203,3 +203,15 @@
|
||||
if(!getorganslot(ORGAN_SLOT_EARS))
|
||||
var/obj/item/organ/ears/ears = new()
|
||||
ears.Insert(src)
|
||||
|
||||
|
||||
/** get_availability
|
||||
* returns whether the species should innately have this organ.
|
||||
*
|
||||
* regenerate organs works with generic organs, so we need to get whether it can accept certain organs just by what this returns.
|
||||
* This is set to return true or false, depending on if a species has a specific organless trait. stomach for example checks if the species has NOSTOMACH and return based on that.
|
||||
* Arguments:
|
||||
* S - species, needed to return whether the species has an organ specific trait
|
||||
*/
|
||||
/obj/item/organ/proc/get_availability(datum/species/S)
|
||||
return TRUE
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
H.vomit(damage)
|
||||
to_chat(H, "<span class='warning'>Your stomach reels in pain as you're incapable of holding down all that food!</span>")
|
||||
|
||||
/obj/item/organ/stomach/get_availability(datum/species/S)
|
||||
return !(NOSTOMACH in S.species_traits)
|
||||
|
||||
/obj/item/organ/stomach/proc/handle_disgust(mob/living/carbon/human/H)
|
||||
if(H.disgust)
|
||||
var/pukeprob = 5 + 0.05 * H.disgust
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/datum/surgery_step/add_prosthetic
|
||||
name = "add prosthetic"
|
||||
implements = list(/obj/item/bodypart = 100, /obj/item/organ_storage = 100, /obj/item/twohanded/required/chainsaw = 100, /obj/item/melee/synthetic_arm_blade = 100)
|
||||
implements = list(/obj/item/bodypart = 100, /obj/item/organ_storage = 100, /obj/item/chainsaw = 100, /obj/item/melee/synthetic_arm_blade = 100)
|
||||
time = 32
|
||||
experience_given = MEDICAL_SKILL_ORGAN_FIX //won't get full XP if rejected
|
||||
var/organ_rejection_dam = 0
|
||||
@@ -72,7 +72,11 @@
|
||||
tool = tool.contents[1]
|
||||
if(istype(tool, /obj/item/bodypart) && user.temporarilyRemoveItemFromInventory(tool))
|
||||
var/obj/item/bodypart/L = tool
|
||||
L.attach_limb(target)
|
||||
if(!L.attach_limb(target))
|
||||
display_results(user, target, "<span class='warning'>You fail in replacing [target]'s [parse_zone(target_zone)]! Their body has rejected [L]!</span>",
|
||||
"<span class='warning'>[user] fails to replace [target]'s [parse_zone(target_zone)]!</span>",
|
||||
"<span class='warning'>[user] fails to replaces [target]'s [parse_zone(target_zone)]!</span>")
|
||||
return
|
||||
if(organ_rejection_dam)
|
||||
target.adjustToxLoss(organ_rejection_dam)
|
||||
experience_given -= (round(organ_rejection_dam/10))
|
||||
@@ -83,13 +87,18 @@
|
||||
else
|
||||
var/obj/item/bodypart/L = target.newBodyPart(target_zone, FALSE, FALSE)
|
||||
L.is_pseudopart = TRUE
|
||||
L.attach_limb(target)
|
||||
if(!L.attach_limb(target))
|
||||
display_results(user, target, "<span class='warning'>You fail in attaching [target]'s [parse_zone(target_zone)]! Their body has rejected [L]!</span>",
|
||||
"<span class='warning'>[user] fails to attach [target]'s [parse_zone(target_zone)]!</span>",
|
||||
"<span class='warning'>[user] fails to attach [target]'s [parse_zone(target_zone)]!</span>")
|
||||
L.forceMove(target.loc)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] finishes attaching [tool]!</span>", "<span class='notice'>You attach [tool].</span>")
|
||||
display_results(user, target, "<span class='notice'>You attach [tool].</span>",
|
||||
"<span class='notice'>[user] finishes attaching [tool]!</span>",
|
||||
"<span class='notice'>[user] finishes the attachment procedure!</span>")
|
||||
qdel(tool)
|
||||
if(istype(tool, /obj/item/twohanded/required/chainsaw))
|
||||
if(istype(tool, /obj/item/chainsaw))
|
||||
var/obj/item/mounted_chainsaw/new_arm = new(target)
|
||||
target_zone == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm)
|
||||
return
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/datum/surgery/advanced/revival
|
||||
/datum/surgery/revival
|
||||
name = "Revival"
|
||||
desc = "An experimental surgical procedure which involves reconstruction and reactivation of the patient's brain even long after death. The body must still be able to sustain life."
|
||||
steps = list(/datum/surgery_step/incise,
|
||||
@@ -13,7 +13,7 @@
|
||||
possible_locs = list(BODY_ZONE_HEAD)
|
||||
requires_bodypart_type = 0
|
||||
|
||||
/datum/surgery/advanced/revival/can_start(mob/user, mob/living/carbon/target)
|
||||
/datum/surgery/revival/can_start(mob/user, mob/living/carbon/target)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(target.stat != DEAD)
|
||||
@@ -27,15 +27,15 @@
|
||||
|
||||
/datum/surgery_step/revive
|
||||
name = "shock body"
|
||||
implements = list(/obj/item/twohanded/shockpaddles = 100, /obj/item/melee/baton = 75, /obj/item/gun/energy = 60)
|
||||
implements = list(/obj/item/shockpaddles = 100, /obj/item/melee/baton = 75, /obj/item/gun/energy = 60)
|
||||
repeatable = TRUE
|
||||
time = 120
|
||||
experience_given = MEDICAL_SKILL_ADVANCED
|
||||
|
||||
/datum/surgery_step/revive/tool_check(mob/user, obj/item/tool)
|
||||
. = TRUE
|
||||
if(istype(tool, /obj/item/twohanded/shockpaddles))
|
||||
var/obj/item/twohanded/shockpaddles/S = tool
|
||||
if(istype(tool, /obj/item/shockpaddles))
|
||||
var/obj/item/shockpaddles/S = tool
|
||||
if((S.req_defib && !S.defib.powered) || !S.wielded || S.cooldown || S.busy)
|
||||
to_chat(user, "<span class='warning'>You need to wield both paddles, and [S.defib] must be powered!</span>")
|
||||
return FALSE
|
||||
Reference in New Issue
Block a user