[MIRROR] limb disabled refactor (#757)

* limb disabled refactor (#53374)

    Fixes #53219
    Nukes is_disabled()
    Turns several variable value changes into events.
    bodypart_disabled turned into a boolean value.
    BODYPART_DISABLED_WOUND turned into TRAIT_DISABLED_BY_WOUND. Not the cleanest thing out there, but it works.
    Cleans some code and reduces number of updates, as only the extremities have a disabled effect.

* limb disabled refactor

Co-authored-by: Rohesie <rohesie@gmail.com>
This commit is contained in:
SkyratBot
2020-09-11 23:21:46 +02:00
committed by GitHub
co-authored by Rohesie
parent 47be9246e6
commit 7c4b7cdb9a
14 changed files with 485 additions and 177 deletions
+1 -5
View File
@@ -967,7 +967,7 @@
var/r_arm_index_next = 0
for(var/bodypart_path in bodyparts)
var/obj/item/bodypart/bodypart_instance = new bodypart_path()
bodypart_instance.owner = src
bodypart_instance.set_owner(src)
bodyparts.Remove(bodypart_path)
add_bodypart(bodypart_instance)
switch(bodypart_instance.body_part)
@@ -1016,10 +1016,6 @@
var/obj/item/organ/I = X
I.Insert(src)
/mob/living/carbon/proc/update_disabled_bodyparts()
for(var/B in bodyparts)
var/obj/item/bodypart/BP = B
BP.update_disabled()
/mob/living/carbon/vv_get_dropdown()
. = ..()
@@ -157,12 +157,13 @@
for(var/X in disabled)
var/obj/item/bodypart/body_part = X
var/damage_text
if(body_part.is_disabled() != BODYPART_DISABLED_WOUND) // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!)
if(!(body_part.get_damage(include_stamina = FALSE) >= body_part.max_damage)) //we don't care if it's stamcritted
damage_text = "limp and lifeless"
else
damage_text = (body_part.brute_dam >= body_part.burn_dam) ? body_part.heavy_brute_msg : body_part.heavy_burn_msg
msg += "<B>[capitalize(t_his)] [body_part.name] is [damage_text]!</B>\n"
if(HAS_TRAIT(body_part, TRAIT_DISABLED_BY_WOUND))
continue // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!)
if(!(body_part.get_damage(include_stamina = FALSE) >= body_part.max_damage)) //we don't care if it's stamcritted
damage_text = "limp and lifeless"
else
damage_text = (body_part.brute_dam >= body_part.burn_dam) ? body_part.heavy_brute_msg : body_part.heavy_burn_msg
msg += "<B>[capitalize(t_his)] [body_part.name] is [damage_text]!</B>\n"
//stores missing limbs
var/l_limbs_missing = 0
@@ -717,7 +717,7 @@
if(status == "OK" || status == "no damage")
no_damage = TRUE
var/isdisabled = ""
if(LB.is_disabled())
if(LB.bodypart_disabled)
isdisabled = " is disabled"
if(no_damage)
isdisabled += " but otherwise"
+225 -60
View File
@@ -22,7 +22,12 @@
var/held_index = 0 //are we a hand? if so, which one!
var/is_pseudopart = FALSE //For limbs that don't really exist, eg chainsaws
var/bodypart_disabled = BODYPART_NOT_DISABLED //If disabled, limb is as good as missing
///If disabled, limb is as good as missing.
var/bodypart_disabled = FALSE
///Multiplied by max_damage it returns the threshold which defines a limb being disabled or not. From 0 to 1.
var/disable_threshold = 1
///Controls whether bodypart_disabled makes sense or not for this limb.
var/can_be_disabled = FALSE
var/body_damage_coeff = 1 //Multiplier of the limb's damage that gets applied to the mob
var/stam_damage_coeff = 0.75
var/brutestate = 0
@@ -91,6 +96,25 @@
var/obj/item/self_grasp/grasped_by
/obj/item/bodypart/Initialize(mapload)
. = ..()
if(can_be_disabled)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS), .proc/on_paralysis_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS), .proc/on_paralysis_trait_loss)
/obj/item/bodypart/Destroy()
if(owner)
owner.remove_bodypart(src)
set_owner(null)
for(var/wound in wounds)
qdel(wound) // wounds is a lazylist, and each wound removes itself from it on deletion.
if(length(wounds))
stack_trace("[type] qdeleted with [length(wounds)] uncleared wounds")
wounds.Cut()
return ..()
/obj/item/bodypart/examine(mob/user)
. = ..()
if(brute_dam > DAMAGE_PRECISION)
@@ -98,14 +122,10 @@
if(burn_dam > DAMAGE_PRECISION)
. += "<span class='warning'>This limb has [burn_dam > 30 ? "severe" : "minor"] burns.</span>"
/obj/item/bodypart/blob_act()
take_damage(max_damage)
/obj/item/bodypart/Destroy()
if(owner)
owner.remove_bodypart(src)
owner = null
return ..()
/obj/item/bodypart/attack(mob/living/carbon/C, mob/user)
if(ishuman(C))
@@ -171,13 +191,6 @@
return bodypart_organs
/obj/item/bodypart/proc/consider_processing()
if(stamina_dam > DAMAGE_PRECISION)
. = TRUE
//else if.. else if.. so on.
else
. = FALSE
needs_processing = .
//Return TRUE to get whatever mob this is in to update health.
/obj/item/bodypart/proc/on_life(stam_regen)
@@ -279,21 +292,24 @@
if(can_inflict <= 0)
return FALSE
brute_dam += brute
burn_dam += burn
if(brute)
set_brute_dam(brute_dam + brute)
if(burn)
set_burn_dam(burn_dam + burn)
//We've dealt the physical damages, if there's room lets apply the stamina damage.
stamina_dam += round(clamp(stamina, 0, max_stamina_damage - stamina_dam), DAMAGE_PRECISION)
if(stamina)
set_stamina_dam(stamina_dam + round(clamp(stamina, 0, max_stamina_damage - stamina_dam), DAMAGE_PRECISION))
if(owner && updating_health)
owner.updatehealth()
if(stamina > DAMAGE_PRECISION)
owner.update_stamina()
owner.stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME
. = TRUE
consider_processing()
update_disabled()
if(owner)
if(can_be_disabled)
update_disabled()
if(updating_health)
owner.updatehealth()
if(stamina > DAMAGE_PRECISION)
owner.update_stamina()
owner.stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME
. = TRUE
return update_bodypart_damage_state() || .
/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds
@@ -468,19 +484,53 @@
//Cannot remove negative damage (i.e. apply damage)
/obj/item/bodypart/proc/heal_damage(brute, burn, stamina, required_status, updating_health = TRUE)
if(required_status && (status != required_status)) //So we can only heal certain kinds of limbs, ie robotic vs organic.
if(required_status && status != required_status) //So we can only heal certain kinds of limbs, ie robotic vs organic.
return
brute_dam = round(max(brute_dam - brute, 0), DAMAGE_PRECISION)
burn_dam = round(max(burn_dam - burn, 0), DAMAGE_PRECISION)
stamina_dam = round(max(stamina_dam - stamina, 0), DAMAGE_PRECISION)
if(owner && updating_health)
owner.updatehealth()
consider_processing()
update_disabled()
if(brute)
set_brute_dam(round(max(brute_dam - brute, 0), DAMAGE_PRECISION))
if(burn)
set_burn_dam(round(max(burn_dam - burn, 0), DAMAGE_PRECISION))
if(stamina)
set_stamina_dam(round(max(stamina_dam - stamina, 0), DAMAGE_PRECISION))
if(owner)
if(can_be_disabled)
update_disabled()
if(updating_health)
owner.updatehealth()
cremation_progress = min(0, cremation_progress - ((brute_dam + burn_dam)*(100/max_damage)))
return update_bodypart_damage_state()
///Proc to hook behavior associated to the change of the brute_dam variable's value.
/obj/item/bodypart/proc/set_brute_dam(new_value)
if(brute_dam == new_value)
return
. = brute_dam
brute_dam = new_value
///Proc to hook behavior associated to the change of the burn_dam variable's value.
/obj/item/bodypart/proc/set_burn_dam(new_value)
if(burn_dam == new_value)
return
. = burn_dam
burn_dam = new_value
///Proc to hook behavior associated to the change of the stamina_dam variable's value.
/obj/item/bodypart/proc/set_stamina_dam(new_value)
if(stamina_dam == new_value)
return
. = stamina_dam
stamina_dam = new_value
if(stamina_dam > DAMAGE_PRECISION)
needs_processing = TRUE
else
needs_processing = FALSE
//Returns total damage.
/obj/item/bodypart/proc/get_damage(include_stamina = FALSE)
var/total = brute_dam + burn_dam
@@ -488,51 +538,166 @@
total = max(total, stamina_dam)
return total
//Checks disabled status thresholds
/obj/item/bodypart/proc/update_disabled()
if(!owner)
return
if(!isnull(set_disabled(is_disabled()))) //set_disabled will return null when there's no change
owner.update_mobility()
if(!can_be_disabled)
set_disabled(FALSE)
CRASH("update_disabled called with can_be_disabled false")
/obj/item/bodypart/proc/is_disabled()
if(!owner)
return
if(HAS_TRAIT(src, TRAIT_PARALYSIS))
return BODYPART_DISABLED_PARALYSIS
for(var/i in wounds)
var/datum/wound/W = i
if(W.disabling)
return BODYPART_DISABLED_WOUND
if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE))
. = bodypart_disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
set_disabled(TRUE)
return
if(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBWOUND) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0%
if(!last_maxed)
var/total_damage = max(brute_dam + burn_dam, stamina_dam)
if(total_damage >= max_damage * disable_threshold) //Easy limb disable disables the limb at 40% health instead of 0%
if(!last_maxed)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
last_maxed = TRUE
if(!is_organic_limb() || stamina_dam >= max_damage)
return BODYPART_DISABLED_DAMAGE
else if(bodypart_disabled && (get_damage(TRUE) <= (max_damage * 0.8))) // reenabled at 80% now instead of 50% as of wounds update
last_maxed = FALSE
return BODYPART_NOT_DISABLED
else
return BODYPART_NOT_DISABLED
return BODYPART_NOT_DISABLED
last_maxed = TRUE
set_disabled(TRUE)
return
if(bodypart_disabled && total_damage <= max_damage * 0.8) // reenabled at 80% now instead of 50% as of wounds update
last_maxed = FALSE
set_disabled(FALSE)
///Proc to change the value of the `disabled` variable and react to the event of its change.
/obj/item/bodypart/proc/set_disabled(new_disabled)
if(isnull(new_disabled) || bodypart_disabled == new_disabled || !owner)
if(bodypart_disabled == new_disabled)
return
. = bodypart_disabled
bodypart_disabled = new_disabled
if(bodypart_disabled && owner.get_item_for_held_index(held_index))
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(!owner)
return
if(bodypart_disabled)
if(!.)
owner.update_mobility()
else if (.)
owner.update_mobility()
owner.update_health_hud() //update the healthdoll
owner.update_body()
///Proc to change the value of the `owner` variable and react to the event of its change.
/obj/item/bodypart/proc/set_owner(new_owner)
if(owner == new_owner)
return FALSE //`null` is a valid option, so we need to use a num var to make it clear no change was made.
. = owner
owner = new_owner
var/needs_update_disabled = FALSE //Only really relevant if there's an owner
if(.)
var/mob/living/carbon/old_owner = .
if(can_be_disabled)
if(HAS_TRAIT(old_owner, TRAIT_EASYLIMBWOUND))
disable_threshold = initial(disable_threshold)
needs_update_disabled = TRUE
UnregisterSignal(old_owner, list(
SIGNAL_REMOVETRAIT(TRAIT_EASYLIMBWOUND),
SIGNAL_ADDTRAIT(TRAIT_EASYLIMBWOUND),
))
if(initial(can_be_disabled))
if(HAS_TRAIT(old_owner, TRAIT_NOLIMBDISABLE))
if(!owner || !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE))
set_can_be_disabled(initial(can_be_disabled))
needs_update_disabled = TRUE
UnregisterSignal(old_owner, list(
SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE),
SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE),
))
if(owner)
if(can_be_disabled)
if(HAS_TRAIT(owner, TRAIT_EASYLIMBWOUND))
disable_threshold = 0.6
needs_update_disabled = TRUE
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_EASYLIMBWOUND), .proc/on_owner_easylimbwound_trait_loss)
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_EASYLIMBWOUND), .proc/on_owner_easylimbwound_trait_gain)
if(initial(can_be_disabled))
if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE))
set_can_be_disabled(FALSE)
needs_update_disabled = FALSE
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), .proc/on_owner_nolimbdisable_trait_loss)
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), .proc/on_owner_nolimbdisable_trait_gain)
if(needs_update_disabled)
update_disabled()
///Proc to change the value of the `can_be_disabled` variable and react to the event of its change.
/obj/item/bodypart/proc/set_can_be_disabled(new_can_be_disabled)
if(can_be_disabled == new_can_be_disabled)
return
. = can_be_disabled
can_be_disabled = new_can_be_disabled
if(can_be_disabled)
if(owner)
if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE))
CRASH("set_can_be_disabled to TRUE with for limb whose owner has TRAIT_NOLIMBDISABLE")
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS), .proc/on_paralysis_trait_gain)
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS), .proc/on_paralysis_trait_loss)
if(HAS_TRAIT(owner, TRAIT_EASYLIMBWOUND))
disable_threshold = 0.6
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_EASYLIMBWOUND), .proc/on_owner_easylimbwound_trait_loss)
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_EASYLIMBWOUND), .proc/on_owner_easylimbwound_trait_gain)
update_disabled()
else if(.)
if(owner)
UnregisterSignal(owner, list(
SIGNAL_ADDTRAIT(TRAIT_PARALYSIS),
SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS),
SIGNAL_REMOVETRAIT(TRAIT_EASYLIMBWOUND),
SIGNAL_ADDTRAIT(TRAIT_EASYLIMBWOUND),
))
set_disabled(FALSE)
///Called when TRAIT_PARALYSIS is added to the limb.
/obj/item/bodypart/proc/on_paralysis_trait_gain(obj/item/bodypart/source)
SIGNAL_HANDLER
if(can_be_disabled)
set_disabled(TRUE)
///Called when TRAIT_PARALYSIS is removed from the limb.
/obj/item/bodypart/proc/on_paralysis_trait_loss(obj/item/bodypart/source)
SIGNAL_HANDLER
if(can_be_disabled)
update_disabled()
///Called when TRAIT_NOLIMBDISABLE is added to the owner.
/obj/item/bodypart/proc/on_owner_nolimbdisable_trait_gain(mob/living/carbon/source)
SIGNAL_HANDLER
set_can_be_disabled(FALSE)
///Called when TRAIT_NOLIMBDISABLE is removed from the owner.
/obj/item/bodypart/proc/on_owner_nolimbdisable_trait_loss(mob/living/carbon/source)
SIGNAL_HANDLER
set_can_be_disabled(initial(can_be_disabled))
///Called when TRAIT_EASYLIMBWOUND is added to the owner.
/obj/item/bodypart/proc/on_owner_easylimbwound_trait_gain(mob/living/carbon/source)
SIGNAL_HANDLER
disable_threshold = 0.6
if(can_be_disabled)
update_disabled()
///Called when TRAIT_EASYLIMBWOUND is removed from the owner.
/obj/item/bodypart/proc/on_owner_easylimbwound_trait_loss(mob/living/carbon/source)
SIGNAL_HANDLER
disable_threshold = initial(disable_threshold)
if(can_be_disabled)
update_disabled()
//Updates an organ's brute/burn states for use by update_damage_overlays()
//Returns 1 if we need to update overlays. 0 otherwise.
/obj/item/bodypart/proc/update_bodypart_damage_state()
@@ -754,7 +919,7 @@
QDEL_NULL(current_gauze)
wound_damage_multiplier = dam_mul
update_disabled()
/obj/item/bodypart/proc/get_bleed_rate()
if(status != BODYPART_ORGANIC) // maybe in the future we can bleed oil from aug parts, but not now
@@ -455,8 +455,8 @@
L = newBodyPart(limb_zone, 0, 0)
if(L)
if(!noheal)
L.brute_dam = 0
L.burn_dam = 0
L.set_brute_dam(0)
L.set_burn_dam(0)
L.brutestate = 0
L.burnstate = 0
+200 -84
View File
@@ -72,35 +72,62 @@
held_index = 1
px_x = -6
px_y = 0
can_be_disabled = TRUE
/obj/item/bodypart/l_arm/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/l_arm/set_owner(new_owner)
. = ..()
if(. == FALSE)
return
var/mob/living/carbon/owner = null
if(owner)
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM))
ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM)
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), .proc/on_owner_paralysis_loss)
else
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM)
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), .proc/on_owner_paralysis_gain)
if(.)
var/mob/living/carbon/old_owner = .
if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_ARM))
UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM))
if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM))
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM)
else
UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM))
///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_ARM trait.
/obj/item/bodypart/l_arm/proc/on_owner_paralysis_gain(mob/living/carbon/source)
SIGNAL_HANDLER
ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM)
UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM))
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), .proc/on_owner_paralysis_loss)
///Proc to react to the owner losing the TRAIT_PARALYSIS_L_ARM trait.
/obj/item/bodypart/l_arm/proc/on_owner_paralysis_loss(mob/living/carbon/source)
SIGNAL_HANDLER
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM)
UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM))
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), .proc/on_owner_paralysis_gain)
/obj/item/bodypart/l_arm/set_disabled(new_disabled)
. = ..()
if(isnull(.))
if(isnull(.) || !owner)
return
if(. == BODYPART_NOT_DISABLED)
if(bodypart_disabled != BODYPART_NOT_DISABLED)
owner.set_usable_hands(owner.usable_hands + 1)
else if(bodypart_disabled == BODYPART_NOT_DISABLED)
owner.set_usable_hands(owner.usable_hands - 1)
switch(bodypart_disabled)
if(BODYPART_DISABLED_DAMAGE)
if(!.)
if(bodypart_disabled)
owner.set_usable_hands(owner.usable_hands - 1)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
to_chat(owner, "<span class='userdanger'>Your lose control of your [name]!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(BODYPART_DISABLED_PARALYSIS)
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
else if(!bodypart_disabled)
owner.set_usable_hands(owner.usable_hands + 1)
if(owner.hud_used)
var/obj/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"]
hand_screen_object?.update_icon()
@@ -119,12 +146,14 @@
icon_state = "alien_l_arm"
px_x = 0
px_y = 0
dismemberable = 0
dismemberable = FALSE
can_be_disabled = FALSE
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/l_arm/devil
dismemberable = 0
dismemberable = FALSE
can_be_disabled = FALSE
max_damage = 5000
animal_origin = DEVIL_BODYPART
@@ -145,35 +174,62 @@
px_x = 6
px_y = 0
max_stamina_damage = 50
can_be_disabled = TRUE
/obj/item/bodypart/r_arm/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/r_arm/set_owner(new_owner)
. = ..()
if(. == FALSE)
return
var/mob/living/carbon/owner = null
if(owner)
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM))
ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM)
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), .proc/on_owner_paralysis_loss)
else
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM)
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), .proc/on_owner_paralysis_gain)
if(.)
var/mob/living/carbon/old_owner = .
if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_ARM))
UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM))
if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM))
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM)
else
UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM))
///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_ARM trait.
/obj/item/bodypart/r_arm/proc/on_owner_paralysis_gain(mob/living/carbon/source)
SIGNAL_HANDLER
ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM)
UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM))
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), .proc/on_owner_paralysis_loss)
///Proc to react to the owner losing the TRAIT_PARALYSIS_R_ARM trait.
/obj/item/bodypart/r_arm/proc/on_owner_paralysis_loss(mob/living/carbon/source)
SIGNAL_HANDLER
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM)
UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM))
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), .proc/on_owner_paralysis_gain)
/obj/item/bodypart/r_arm/set_disabled(new_disabled)
. = ..()
if(isnull(.))
if(isnull(.) || !owner)
return
if(. == BODYPART_NOT_DISABLED)
if(bodypart_disabled != BODYPART_NOT_DISABLED)
owner.set_usable_hands(owner.usable_hands + 1)
else if(bodypart_disabled == BODYPART_NOT_DISABLED)
owner.set_usable_hands(owner.usable_hands - 1)
switch(bodypart_disabled)
if(BODYPART_DISABLED_DAMAGE)
if(!.)
if(bodypart_disabled)
owner.set_usable_hands(owner.usable_hands - 1)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
to_chat(owner, "<span class='userdanger'>Your lose control of your [name]!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(BODYPART_DISABLED_PARALYSIS)
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
else if(!bodypart_disabled)
owner.set_usable_hands(owner.usable_hands + 1)
if(owner.hud_used)
var/obj/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"]
hand_screen_object?.update_icon()
@@ -192,12 +248,14 @@
icon_state = "alien_r_arm"
px_x = 0
px_y = 0
dismemberable = 0
dismemberable = FALSE
can_be_disabled = FALSE
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/r_arm/devil
dismemberable = 0
dismemberable = FALSE
can_be_disabled = FALSE
max_damage = 5000
animal_origin = DEVIL_BODYPART
@@ -215,31 +273,58 @@
px_x = -2
px_y = 12
max_stamina_damage = 50
can_be_disabled = TRUE
/obj/item/bodypart/l_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/l_leg/set_owner(new_owner)
. = ..()
if(. == FALSE)
return
if(owner)
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG)
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), .proc/on_owner_paralysis_loss)
else
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG)
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), .proc/on_owner_paralysis_gain)
if(.)
var/mob/living/carbon/old_owner = .
if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_LEG))
UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG))
if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG)
else
UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG))
///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_LEG trait.
/obj/item/bodypart/l_leg/proc/on_owner_paralysis_gain(mob/living/carbon/source)
SIGNAL_HANDLER
ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG)
UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG))
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), .proc/on_owner_paralysis_loss)
///Proc to react to the owner losing the TRAIT_PARALYSIS_L_LEG trait.
/obj/item/bodypart/l_leg/proc/on_owner_paralysis_loss(mob/living/carbon/source)
SIGNAL_HANDLER
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG)
UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG))
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), .proc/on_owner_paralysis_gain)
/obj/item/bodypart/l_leg/set_disabled(new_disabled)
. = ..()
if(isnull(.))
if(isnull(.) || !owner)
return
if(. == BODYPART_NOT_DISABLED)
if(bodypart_disabled != BODYPART_NOT_DISABLED)
owner.set_usable_legs(owner.usable_legs + 1)
else if(bodypart_disabled == BODYPART_NOT_DISABLED)
owner.set_usable_legs(owner.usable_legs - 1)
switch(bodypart_disabled)
if(BODYPART_DISABLED_DAMAGE)
if(!.)
if(bodypart_disabled)
owner.set_usable_legs(owner.usable_legs - 1)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
if(BODYPART_DISABLED_PARALYSIS)
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
to_chat(owner, "<span class='userdanger'>Your lose control of your [name]!</span>")
else if(!bodypart_disabled)
owner.set_usable_legs(owner.usable_legs + 1)
/obj/item/bodypart/l_leg/digitigrade
@@ -258,12 +343,14 @@
icon_state = "alien_l_leg"
px_x = 0
px_y = 0
dismemberable = 0
dismemberable = FALSE
can_be_disabled = FALSE
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/l_leg/devil
dismemberable = 0
dismemberable = FALSE
can_be_disabled = FALSE
max_damage = 5000
animal_origin = DEVIL_BODYPART
@@ -283,31 +370,58 @@
px_x = 2
px_y = 12
max_stamina_damage = 50
can_be_disabled = TRUE
/obj/item/bodypart/r_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/r_leg/set_owner(new_owner)
. = ..()
if(. == FALSE)
return
if(owner)
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG)
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), .proc/on_owner_paralysis_loss)
else
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG)
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG), .proc/on_owner_paralysis_gain)
if(.)
var/mob/living/carbon/old_owner = .
if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_LEG))
UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG))
if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG)
else
UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG))
///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_LEG trait.
/obj/item/bodypart/r_leg/proc/on_owner_paralysis_gain(mob/living/carbon/source)
SIGNAL_HANDLER
ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG)
UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG))
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), .proc/on_owner_paralysis_loss)
///Proc to react to the owner losing the TRAIT_PARALYSIS_R_LEG trait.
/obj/item/bodypart/r_leg/proc/on_owner_paralysis_loss(mob/living/carbon/source)
SIGNAL_HANDLER
REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG)
UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG))
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG), .proc/on_owner_paralysis_gain)
/obj/item/bodypart/r_leg/set_disabled(new_disabled)
. = ..()
if(isnull(.))
if(isnull(.) || !owner)
return
if(. == BODYPART_NOT_DISABLED)
if(bodypart_disabled != BODYPART_NOT_DISABLED)
owner.set_usable_legs(owner.usable_legs + 1)
else if(bodypart_disabled == BODYPART_NOT_DISABLED)
owner.set_usable_legs(owner.usable_legs - 1)
switch(bodypart_disabled)
if(BODYPART_DISABLED_DAMAGE)
if(!.)
if(bodypart_disabled)
owner.set_usable_legs(owner.usable_legs - 1)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
if(BODYPART_DISABLED_PARALYSIS)
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
to_chat(owner, "<span class='userdanger'>Your lose control of your [name]!</span>")
else if(!bodypart_disabled)
owner.set_usable_legs(owner.usable_legs + 1)
/obj/item/bodypart/r_leg/digitigrade
@@ -326,11 +440,13 @@
icon_state = "alien_r_leg"
px_x = 0
px_y = 0
dismemberable = 0
dismemberable = FALSE
can_be_disabled = FALSE
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/r_leg/devil
dismemberable = 0
dismemberable = FALSE
can_be_disabled = FALSE
max_damage = 5000
animal_origin = DEVIL_BODYPART