[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
-5
View File
@@ -63,11 +63,6 @@
#define BODYPART_ORGANIC 1
#define BODYPART_ROBOTIC 2
#define BODYPART_NOT_DISABLED 0
#define BODYPART_DISABLED_DAMAGE 1
#define BODYPART_DISABLED_PARALYSIS 2
#define BODYPART_DISABLED_WOUND 3
#define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi'
#define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi'
+4 -1
View File
@@ -203,7 +203,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_KNOW_ENGI_WIRES "know_engi_wires"
//non-mob traits
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
/// Used for limb-based paralysis, where replacing the limb will fix it.
#define TRAIT_PARALYSIS "paralysis"
/// Used for limbs.
#define TRAIT_DISABLED_BY_WOUND "disabled-by-wound"
///Used for managing KEEP_TOGETHER in [appearance_flags]
#define TRAIT_KEEP_TOGETHER "keep-together"
+2 -2
View File
@@ -7,8 +7,8 @@
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity)
if(!has_active_hand()) //can't attack without a hand.
var/obj/item/bodypart/check_arm = get_active_hand()
if(check_arm && check_arm.is_disabled() == BODYPART_DISABLED_WOUND)
to_chat(src, "<span class='warning'>The damage in your [check_arm.name] is preventing you from using it! Get it fixed, or at least splinted!</span>")
if(check_arm?.bodypart_disabled)
to_chat(src, "<span class='warning'>Your [check_arm.name] is in no condition to be used.</span>")
return
to_chat(src, "<span class='notice'>You look at your arm and sigh.</span>")
+2 -2
View File
@@ -104,13 +104,13 @@
..()
for(var/X in paralysis_traits)
ADD_TRAIT(owner, X, "trauma_paralysis")
owner.update_disabled_bodyparts()
/datum/brain_trauma/severe/paralysis/on_lose()
..()
for(var/X in paralysis_traits)
REMOVE_TRAIT(owner, X, "trauma_paralysis")
owner.update_disabled_bodyparts()
/datum/brain_trauma/severe/paralysis/paraplegic
random_gain = FALSE
+35 -3
View File
@@ -95,7 +95,7 @@
QDEL_NULL(attached_surgery)
if(limb?.wounds && (src in limb.wounds)) // destroy can call remove_wound() and remove_wound() calls qdel, so we check to make sure there's anything to remove first
remove_wound()
limb = null
set_limb(null)
victim = null
return ..()
@@ -129,7 +129,7 @@
return
victim = L.owner
limb = L
set_limb(L)
LAZYADD(victim.all_wounds, src)
LAZYADD(limb.wounds, src)
limb.update_wounds()
@@ -192,13 +192,45 @@
already_scarred = TRUE
remove_wound(replaced=TRUE)
new_wound.apply_wound(limb, old_wound = src, smited = smited)
. = new_wound
qdel(src)
return new_wound
/// The immediate negative effects faced as a result of the wound
/datum/wound/proc/wound_injury(datum/wound/old_wound = null)
return
/// Proc called to change the variable `limb` and react to the event.
/datum/wound/proc/set_limb(new_value)
if(limb == new_value)
return FALSE //Limb can either be a reference to something or `null`. Returning the number variable makes it clear no change was made.
. = limb
limb = new_value
if(. && disabling)
var/obj/item/bodypart/old_limb = .
REMOVE_TRAIT(old_limb, TRAIT_PARALYSIS, src)
REMOVE_TRAIT(old_limb, TRAIT_DISABLED_BY_WOUND, src)
if(limb)
if(disabling)
ADD_TRAIT(limb, TRAIT_PARALYSIS, src)
ADD_TRAIT(limb, TRAIT_DISABLED_BY_WOUND, src)
/// Proc called to change the variable `disabling` and react to the event.
/datum/wound/proc/set_disabling(new_value)
if(disabling == new_value)
return
. = disabling
disabling = new_value
if(disabling)
if(!. && limb) //Gained disabling.
ADD_TRAIT(limb, TRAIT_PARALYSIS, src)
ADD_TRAIT(limb, TRAIT_DISABLED_BY_WOUND, src)
else if(. && limb) //Lost disabling.
REMOVE_TRAIT(limb, TRAIT_PARALYSIS, src)
REMOVE_TRAIT(limb, TRAIT_DISABLED_BY_WOUND, src)
/// Additional beneficial effects when the wound is gained, in case you want to give a temporary boost to allow the victim to try an escape or last stand
/datum/wound/proc/second_wind()
switch(severity)
+1 -1
View File
@@ -177,7 +177,7 @@
interaction_efficiency_penalty = interaction_efficiency_penalty
if(initial(disabling))
disabling = !limb.current_gauze
set_disabling(!limb.current_gauze)
limb.update_wounds()
+4 -4
View File
@@ -82,19 +82,19 @@
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
if(!disabling && prob(2))
to_chat(victim, "<span class='warning'><b>Your [limb.name] completely locks up, as you struggle for control against the infection!</b></span>")
disabling = TRUE
set_disabling(TRUE)
else if(disabling && prob(8))
to_chat(victim, "<span class='notice'>You regain sensation in your [limb.name], but it's still in terrible shape!</span>")
disabling = FALSE
set_disabling(FALSE)
else if(prob(20))
victim.adjustToxLoss(0.5)
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
if(!disabling && prob(3))
to_chat(victim, "<span class='warning'><b>You suddenly lose all sensation of the festering infection in your [limb.name]!</b></span>")
disabling = TRUE
set_disabling(TRUE)
else if(disabling && prob(3))
to_chat(victim, "<span class='notice'>You can barely feel your [limb.name] again, and you have to strain to retain motor control!</span>")
disabling = FALSE
set_disabling(FALSE)
else if(prob(1))
to_chat(victim, "<span class='warning'>You contemplate life without your [limb.name]...</span>")
victim.adjustToxLoss(0.75)
+1 -1
View File
@@ -46,7 +46,7 @@
victim.visible_message(msg, "<span class='userdanger'>Your [dismembered_part.name] [occur_text]!</span>")
limb = dismembered_part
set_limb(dismembered_part)
severity = WOUND_SEVERITY_LOSS
second_wind()
log_wound(victim, src)
+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