Ported parts of the BS12 organ system.

This includes:
- Individual wounds
- Dismemberment
- Bone breaking

It also adds configuration values to config/game_options.txt to control the point at which bones break and limbs are cut off.

Does not include surgery or bleeding yet.

git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4720 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
CIB123
2012-09-18 21:32:39 +00:00
parent 0fbfa48217
commit d6dfd49a75
27 changed files with 1243 additions and 164 deletions
+7
View File
@@ -71,6 +71,9 @@
var/health_threshold_crit = 0
var/health_threshold_dead = -100
var/organ_health_multiplier = 1
var/organ_regeneration_multiplier = 1
var/revival_pod_plants = 1
var/revival_cloning = 1
var/revival_brain_life = -1
@@ -365,6 +368,10 @@
config.metroid_delay = value
if("animal_delay")
config.animal_delay = value
if("organ_health_multiplier")
config.organ_health_multiplier = value / 100
if("organ_regeneration_multiplier")
config.organ_regeneration_multiplier = value / 100
else
diary << "Unknown setting in configuration: '[name]'"
+5 -4
View File
@@ -1,8 +1,6 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
/datum/organ
var/name = "organ"
var/mob/owner = null
var/mob/living/carbon/human/owner = null
///datum/organ/proc/process()
// return 0
@@ -10,5 +8,8 @@
///datum/organ/proc/receive_chem(chemical as obj)
// return 0
proc/process()
return 0
proc/receive_chem(chemical as obj)
return 0
+574 -76
View File
@@ -1,142 +1,640 @@
/****************************************************
EXTERNAL ORGANS
****************************************************/
/datum/organ/external
name = "external"
var/icon_name = null
var/body_part = null
var/brutestate = 0
var/burnstate = 0
var/damage_state = "00"
var/brute_dam = 0
var/burn_dam = 0
var/max_damage = 0
// var/bandaged = 0
// var/wound_size = 0
// var/max_size = 0
var/max_size = 0
var/tmp/list/obj/item/weapon/implant/implant
var/display_name
var/list/wounds = list()
var/number_wounds = 0 // cache the number of wounds, which is NOT wounds.len!
var/tmp/perma_injury = 0
var/tmp/perma_dmg = 0
var/tmp/destspawn = 0 //Has it spawned the broken limb?
var/tmp/amputated = 0 // Whether this has been cleanly amputated, thus causing no pain
var/min_broken_damage = 30
var/datum/organ/external/parent
var/list/datum/organ/external/children
var/damage_msg = "\red You feel an intense pain"
var/status = 0
var/broken_description
var/open = 0
var/stage = 0
proc/take_damage(brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list())
// TODO: this proc needs to be rewritten to not update damages directly
if((brute <= 0) && (burn <= 0))
return 0
if(status & ORGAN_DESTROYED)
return 0
if(status & ORGAN_ROBOT)
brute *= 0.66 //~2/3 damage for ROBOLIMBS
burn *= 0.66 //~2/3 damage for ROBOLIMBS
//if(owner && !(status & ORGAN_ROBOT))
// owner.pain(display_name, (brute+burn)*3, 1, burn > brute)
if(sharp)
var/nux = brute * rand(10,15)
if(brute_dam >= max_damage * config.organ_health_multiplier)
if(prob(5 * brute))
status |= ORGAN_DESTROYED
droplimb()
return
else if(prob(nux))
createwound( CUT, brute )
if(!(status & ORGAN_ROBOT))
owner << "You feel something wet on your [display_name]"
if((brute_dam + burn_dam + brute + burn) < max_damage)
if(brute)
brute_dam += brute
if( (prob(brute*2) && !sharp) || sharp )
createwound( CUT, brute )
else if(!sharp)
createwound( BRUISE, brute )
if(burn)
burn_dam += burn
createwound( BURN, burn )
else
var/can_inflict = max_damage - (brute_dam + burn_dam) //How much damage can we actually cause?
if(can_inflict)
if (brute > 0 && burn > 0)
brute = can_inflict/2
burn = can_inflict/2
var/ratio = brute / (brute + burn)
brute_dam += ratio * can_inflict
burn_dam += (1 - ratio) * can_inflict
else
if (brute > 0)
brute = can_inflict
brute_dam += brute
createwound(BRUISE, brute)
else
burn = can_inflict
burn_dam += burn
createwound(BRUISE, brute)
else if(!(status & ORGAN_ROBOT))
var/passed_dam = (brute + burn) - can_inflict //Getting how much overdamage we have.
var/list/datum/organ/external/possible_points = list()
if(parent)
possible_points += parent
if(children)
possible_points += children
if(forbidden_limbs.len)
possible_points -= forbidden_limbs
if(!possible_points.len)
message_admins("Oh god WHAT! [owner]'s [src] was unable to find an organ to pass overdamage too!")
else
var/datum/organ/external/target = pick(possible_points)
if(brute)
target.take_damage(passed_dam, 0, sharp, used_weapon, forbidden_limbs + src)
else
target.take_damage(0, passed_dam, sharp, used_weapon, forbidden_limbs + src)
else
droplimb(1) //Robot limbs just kinda fail at full damage.
if(status & ORGAN_BROKEN)
owner.emote("scream")
owner.updatehealth()
// sync the organ's damage with its wounds
src.update_damages()
var/result = update_icon()
return result
proc/heal_damage(brute, burn, internal = 0, robo_repair = 0)
if(status & ORGAN_ROBOT && !robo_repair)
return
// heal damage on the individual wounds
for(var/datum/wound/W in wounds)
if(brute == 0 && burn == 0)
break
// heal brute damage
if(W.damage_type == CUT || W.damage_type == BRUISE)
brute = W.heal_damage(brute)
else if(W.damage_type == BURN)
burn = W.heal_damage(burn)
// sync organ damage with wound damages
update_damages()
if(internal)
status &= ~ORGAN_BROKEN
perma_injury = 0
// sync the organ's damage with its wounds
src.update_damages()
owner.updatehealth()
var/result = update_icon()
return result
proc/update_damages()
number_wounds = 0
brute_dam = 0
burn_dam = 0
status &= ~ORGAN_BLEEDING
for(var/datum/wound/W in wounds)
if(W.damage_type == CUT || W.damage_type == BRUISE)
brute_dam += W.damage
else if(W.damage_type == BURN)
burn_dam += W.damage
if(!W.bandaged && W.damage > 4)
status |= ORGAN_BLEEDING
number_wounds += W.amount
proc/update_wounds()
for(var/datum/wound/W in wounds)
// wounds can disappear after 10 minutes at the earliest
if(W.damage == 0 && W.created + 10 * 10 * 60 <= world.time)
wounds -= W
// let the GC handle the deletion of the wound
if(W.is_treated())
// slow healing
var/amount = 0.2
if(W.bandaged) amount++
if(W.salved) amount++
if(W.disinfected) amount++
// amount of healing is spread over all the wounds
W.heal_damage((amount * W.amount * config.organ_regeneration_multiplier) / (5*owner.number_wounds+1))
// sync the organ's damage with its wounds
src.update_damages()
proc/get_damage() //returns total damage
return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use health?
proc/get_damage_brute()
return max(brute_dam+perma_injury, perma_injury)
proc/get_damage_fire()
return burn_dam
process()
// process wounds, doing healing etc., only do this every 4 ticks to save processing power
if(owner.life_tick % 4 == 0)
update_wounds()
if(status & ORGAN_DESTROYED)
if(!destspawn)
droplimb()
return
if(!(status & ORGAN_BROKEN))
perma_dmg = 0
if(parent)
if(parent.status & ORGAN_DESTROYED)
status |= ORGAN_DESTROYED
owner:update_body()
return
if(brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT))
if(!(status & ORGAN_BROKEN))
owner.visible_message("\red You hear a loud cracking sound coming from \the [owner].","\red <b>Something feels like it shattered in your [display_name]!</b>","You hear a sickening crack.")
owner.emote("scream")
status |= ORGAN_BROKEN
broken_description = pick("broken","fracture","hairline fracture")
perma_injury = brute_dam
return
// new damage icon system
// returns just the brute/burn damage code
proc/damage_state_text()
var/tburn = 0
var/tbrute = 0
if(burn_dam ==0)
tburn =0
else if (burn_dam < (max_damage * 0.25 / 2))
tburn = 1
else if (burn_dam < (max_damage * 0.75 / 2))
tburn = 2
else
tburn = 3
if (brute_dam == 0)
tbrute = 0
else if (brute_dam < (max_damage * 0.25 / 2))
tbrute = 1
else if (brute_dam < (max_damage * 0.75 / 2))
tbrute = 2
else
tbrute = 3
return "[tbrute][tburn]"
// new damage icon system
// adjusted to set damage_state to brute/burn code only (without r_name0 as before)
proc/update_icon()
var/n_is = damage_state_text()
if (n_is != damage_state)
damage_state = n_is
owner.update_body()
return 1
return 0
proc/droplimb(var/override = 0,var/no_explode = 0)
if(override)
status |= ORGAN_DESTROYED
if(status & ORGAN_DESTROYED)
if(status & ORGAN_SPLINTED)
status &= ~ORGAN_SPLINTED
if(implant)
for(var/implants in implant)
del(implants)
//owner.unlock_medal("Lost something?", 0, "Lose a limb.", "easy")
for(var/datum/organ/external/I in children)
if(I && !(I.status & ORGAN_DESTROYED))
I.droplimb(1,1)
var/obj/item/weapon/organ/H
switch(body_part)
if(UPPER_TORSO)
owner.gib()
if(LOWER_TORSO)
owner << "\red You are now sterile."
if(HEAD)
H = new /obj/item/weapon/organ/head(owner.loc, owner)
if(ishuman(owner))
if(owner.gender == FEMALE)
H.icon_state = "head_f_l"
H.overlays += owner.generate_head_icon()
H:transfer_identity(owner)
H.pixel_x = -10
H.pixel_y = 6
H.name = "[owner.real_name]'s head"
// TODO: re-add this when dismemberment has been ported properly
//if(ishuman(owner))
// owner.update_face()
owner.update_body()
owner.death()
if(ARM_RIGHT)
H = new /obj/item/weapon/organ/r_arm(owner.loc, owner)
if(ismonkey(owner))
H.icon_state = "r_arm_l"
if(ARM_LEFT)
H = new /obj/item/weapon/organ/l_arm(owner.loc, owner)
if(ismonkey(owner))
H.icon_state = "l_arm_l"
if(LEG_RIGHT)
H = new /obj/item/weapon/organ/r_leg(owner.loc, owner)
if(ismonkey(owner))
H.icon_state = "r_leg_l"
if(LEG_LEFT)
H = new /obj/item/weapon/organ/l_leg(owner.loc, owner)
if(ismonkey(owner))
H.icon_state = "l_leg_l"
if(HAND_RIGHT)
H = new /obj/item/weapon/organ/r_hand(owner.loc, owner)
if(ismonkey(owner))
H.icon_state = "r_hand_l"
if(HAND_LEFT)
H = new /obj/item/weapon/organ/l_hand(owner.loc, owner)
if(ismonkey(owner))
H.icon_state = "l_hand_l"
if(FOOT_RIGHT)
H = new /obj/item/weapon/organ/r_foot/(owner.loc, owner)
if(ismonkey(owner))
H.icon_state = "r_foot_l"
if(FOOT_LEFT)
H = new /obj/item/weapon/organ/l_foot(owner.loc, owner)
if(ismonkey(owner))
H.icon_state = "l_foot_l"
if(ismonkey(owner))
H.icon = 'monkey.dmi'
var/lol = pick(cardinal)
step(H,lol)
destspawn = 1
if(status & ORGAN_ROBOT)
owner.visible_message("\red \The [owner]'s [display_name] explodes violently!",\
"\red <b>Your [display_name] explodes!</b>",\
"You hear an explosion followed by a scream!")
if(!no_explode)
explosion(get_turf(owner),-1,-1,2,3)
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else
owner.visible_message("\red [owner.name]'s [display_name] flies off in an arc.",\
"<span class='moderate'><b>Your [display_name] goes flying off!</b></span>",\
"You hear a terrible sound of ripping tendons and flesh.")
owner.update_body()
// TODO: also add stuff to update the appropriate clothing
proc/createwound(var/type = CUT, var/damage)
if(hasorgans(owner))
var/wound_type
var/size = min( max( 1, damage/10 ) , 6)
// first check whether we can widen an existing wound
if(wounds.len > 0 && prob(25))
if((type == CUT || type == BRUISE) && damage >= 5)
var/datum/wound/W = pick(wounds)
if(W.amount == 1 && W.started_healing())
W.open_wound()
owner.visible_message("\red The wound on [owner.name]'s [display_name] widens with a nasty ripping voice.",\
"\red The wound on your [display_name] widens with a nasty ripping voice.",\
"You hear a nasty ripping noise, as if flesh is being torn apart.")
return
if(damage == 0) return
// the wound we will create
var/datum/wound/W
switch(type)
if(CUT)
src.status |= ORGAN_BLEEDING
var/list/size_names = list(/datum/wound/cut, /datum/wound/deep_cut, /datum/wound/flesh_wound, /datum/wound/gaping_wound, /datum/wound/big_gaping_wound, /datum/wound/massive_wound)
wound_type = size_names[size]
W = new wound_type(damage)
if(BRUISE)
var/list/size_names = list(/datum/wound/bruise/tiny_bruise, /datum/wound/bruise/small_bruise, /datum/wound/bruise/moderate_bruise, /datum/wound/bruise/large_bruise, /datum/wound/bruise/huge_bruise, /datum/wound/bruise/monumental_bruise)
wound_type = size_names[size]
W = new wound_type(damage)
if(BURN)
var/list/size_names = list(/datum/wound/moderate_burn, /datum/wound/large_burn, /datum/wound/severe_burn, /datum/wound/deep_burn, /datum/wound/carbonised_area)
wound_type = size_names[size]
W = new wound_type(damage)
// check whether we can add the wound to an existing wound
for(var/datum/wound/other in wounds)
if(other.desc == W.desc)
// okay, add it!
other.damage += W.damage
other.amount += 1
W = null // to signify that the wound was added
break
// if we couldn't add the wound to another wound, ignore
if(W)
wounds += W
proc/emp_act(severity)
if(!(status & ORGAN_ROBOT))
return
if(prob(30*severity))
take_damage(4(4-severity), 0, 1, used_weapon = "EMP")
else
droplimb(1)
proc/getDisplayName()
switch(name)
if("l_leg")
return "left leg"
if("r_leg")
return "right leg"
if("l_arm")
return "left arm"
if("r_arm")
return "right arm"
if("l_foot")
return "left foot"
if("r_foot")
return "right foot"
if("l_hand")
return "left hand"
if("r_hand")
return "right hand"
else
return name
/datum/organ/external/chest
name = "chest"
icon_name = "chest"
display_name = "chest"
max_damage = 150
min_broken_damage = 75
body_part = UPPER_TORSO
/datum/organ/external/groin
name = "groin"
icon_name = "diaper"
display_name = "groin"
max_damage = 115
min_broken_damage = 70
body_part = LOWER_TORSO
/datum/organ/external/head
name = "head"
icon_name = "head"
max_damage = 125
display_name = "head"
max_damage = 75
min_broken_damage = 40
body_part = HEAD
var/disfigured = 0
/datum/organ/external/l_arm
name = "l_arm"
display_name = "left arm"
icon_name = "l_arm"
max_damage = 75
min_broken_damage = 30
body_part = ARM_LEFT
/datum/organ/external/l_leg
name = "l_leg"
display_name = "left leg"
icon_name = "l_leg"
max_damage = 75
min_broken_damage = 30
body_part = LEG_LEFT
/datum/organ/external/r_arm
name = "r_arm"
display_name = "right arm"
icon_name = "r_arm"
max_damage = 75
min_broken_damage = 30
body_part = ARM_RIGHT
/datum/organ/external/r_leg
name = "r_leg"
display_name = "right leg"
icon_name = "r_leg"
max_damage = 75
min_broken_damage = 30
body_part = LEG_RIGHT
/*Leaving these here in case we want to use them later
/datum/organ/external/l_foot
name = "l foot"
name = "l_foot"
display_name = "left foot"
icon_name = "l_foot"
max_damage = 40
min_broken_damage = 15
body_part = FOOT_LEFT
/datum/organ/external/r_foot
name = "r foot"
name = "r_foot"
display_name = "right foot"
icon_name = "r_foot"
max_damage = 40
min_broken_damage = 15
body_part = FOOT_RIGHT
/datum/organ/external/r_hand
name = "r hand"
name = "r_hand"
display_name = "right hand"
icon_name = "r_hand"
max_damage = 40
min_broken_damage = 15
body_part = HAND_RIGHT
/datum/organ/external/l_hand
name = "l hand"
name = "l_hand"
display_name = "left hand"
icon_name = "l_hand"
max_damage = 40
min_broken_damage = 15
body_part = HAND_LEFT
/datum/organ/external/groin
name = "groin"
icon_name = "groin"
body_part = LOWER_TORSO
*/
/****************************************************
EXTERNAL ORGAN ITEMS
****************************************************/
//Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all.
//Damage will not exceed max_damage using this proc
//Cannot apply negative damage
/datum/organ/external/proc/take_damage(brute, burn)
if(owner && owner.nodamage) return 0 //godmode
brute = max(brute,0)
burn = max(burn,0)
obj/item/weapon/organ
icon = 'human.dmi'
var/can_inflict = max_damage - (brute_dam + burn_dam)
if(!can_inflict) return 0
obj/item/weapon/organ/New(loc, mob/living/carbon/human/H)
..(loc)
if(!istype(H))
return
if(H.dna)
if(!blood_DNA)
blood_DNA = list()
blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
if((brute + burn) < can_inflict)
brute_dam += brute
burn_dam += burn
var/icon/I = new /icon(icon, icon_state)
if (H.s_tone >= 0)
I.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD)
else
if(brute > 0)
if(burn > 0)
brute = round( (brute/(brute+burn)) * can_inflict, 1 )
burn = can_inflict - brute //gets whatever damage is left over
brute_dam += brute
burn_dam += burn
I.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT)
icon = I
obj/item/weapon/organ/head
name = "head"
icon_state = "head_m_l"
var/mob/living/carbon/brain/brainmob
var/brain_op_stage = 0
obj/item/weapon/organ/head/New()
..()
spawn(5)
if(brainmob && brainmob.client)
brainmob.client.screen.len = null //clear the hud
obj/item/weapon/organ/head/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->head
brainmob = new(src)
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna
if(H.mind)
H.mind.transfer_to(brainmob)
brainmob.container = src
obj/item/weapon/organ/head/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/scalpel))
switch(brain_op_stage)
if(0)
for(var/mob/O in (oviewers(brainmob) - user))
O.show_message("\red [brainmob] is beginning to have \his head cut open with [src] by [user].", 1)
brainmob << "\red [user] begins to cut open your head with [src]!"
user << "\red You cut [brainmob]'s head open with [src]!"
brain_op_stage = 1
if(2)
for(var/mob/O in (oviewers(brainmob) - user))
O.show_message("\red [brainmob] is having \his connections to the brain delicately severed with [src] by [user].", 1)
brainmob << "\red [user] begins to cut open your head with [src]!"
user << "\red You cut [brainmob]'s head open with [src]!"
brain_op_stage = 3.0
else
brute_dam += can_inflict
else
if(burn > 0)
burn_dam += can_inflict
..()
else if(istype(W,/obj/item/weapon/circular_saw))
switch(brain_op_stage)
if(1)
for(var/mob/O in (oviewers(brainmob) - user))
O.show_message("\red [brainmob] has \his skull sawed open with [src] by [user].", 1)
brainmob << "\red [user] begins to saw open your head with [src]!"
user << "\red You saw [brainmob]'s head open with [src]!"
brain_op_stage = 2
if(3)
for(var/mob/O in (oviewers(brainmob) - user))
O.show_message("\red [brainmob] has \his spine's connection to the brain severed with [src] by [user].", 1)
brainmob << "\red [user] severs your brain's connection to the spine with [src]!"
user << "\red You sever [brainmob]'s brain's connection to the spine with [src]!"
user.attack_log += "\[[time_stamp()]\]<font color='red'> Debrained [brainmob.name] ([brainmob.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])</font>"
brainmob.attack_log += "\[[time_stamp()]\]<font color='orange'> Debrained by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])</font>"
log_admin("ATTACK: [brainmob] ([brainmob.ckey]) debrained [user] ([user.ckey]).")
message_admins("ATTACK: [brainmob] ([brainmob.ckey]) debrained [user] ([user.ckey]).")
var/obj/item/brain/B = new(loc)
B.transfer_identity(brainmob)
brain_op_stage = 4.0
else
return 0
return update_icon()
..()
else
..()
//Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all.
//Damage cannot go below zero.
//Cannot remove negative damage (i.e. apply damage)
/datum/organ/external/proc/heal_damage(brute, burn)
brute = max(brute, 0)
burn = max(burn, 0)
brute_dam = max(brute_dam - brute, 0)
burn_dam = max(burn_dam - burn, 0)
return update_icon()
//Returns total damage...kinda pointless really
/datum/organ/external/proc/get_damage() //returns total damage
return brute_dam + burn_dam
//Updates an organ's brute/burn states for use by updateDamageIcon()
//Returns 1 if we need to update overlays. 0 otherwise.
/datum/organ/external/proc/update_icon()
var/tbrute = round( (brute_dam/max_damage)*3, 1 )
var/tburn = round( (burn_dam/max_damage)*3, 1 )
if((tbrute != brutestate) || (tburn != burnstate))
brutestate = tbrute
burnstate = tburn
return 1
return 0
//Returns a display name for the organ
/datum/organ/external/proc/getDisplayName()
switch(name)
if("l_leg") return "left leg"
if("r_leg") return "right leg"
if("l_arm") return "left arm"
if("r_arm") return "right arm"
else return name
obj/item/weapon/organ/l_arm
name = "left arm"
icon_state = "l_arm_l"
obj/item/weapon/organ/l_foot
name = "left foot"
icon_state = "l_foot_l"
obj/item/weapon/organ/l_hand
name = "left hand"
icon_state = "l_hand_l"
obj/item/weapon/organ/l_leg
name = "left leg"
icon_state = "l_leg_l"
obj/item/weapon/organ/r_arm
name = "right arm"
icon_state = "r_arm_l"
obj/item/weapon/organ/r_foot
name = "right foot"
icon_state = "r_foot_l"
obj/item/weapon/organ/r_hand
name = "right hand"
icon_state = "r_hand_l"
obj/item/weapon/organ/r_leg
name = "right leg"
icon_state = "r_leg_l"
+3
View File
@@ -1,3 +1,6 @@
/****************************************************
INTERNAL ORGANS
****************************************************/
/datum/organ/internal
name = "internal"
+196
View File
@@ -0,0 +1,196 @@
/****************************************************
WOUNDS
****************************************************/
/datum/wound
// stages such as "cut", "deep cut", etc.
var/list/stages
// number representing the current stage
var/current_stage = 0
// description of the wound
var/desc = ""
// amount of damage this wound causes
var/damage = 0
// amount of damage the current wound type requires(less means we need to apply the next healing stage)
var/min_damage = 0
// one of CUT, BRUISE, BURN
var/damage_type = CUT
// whether this wound needs a bandage/salve to heal at all
var/needs_treatment = 0
// is the wound bandaged?
var/tmp/bandaged = 0
// is the wound salved?
var/tmp/salved = 0
// is the wound disinfected?
var/tmp/disinfected = 0
var/tmp/created = 0
// number of wounds of this type
var/tmp/amount = 1
// helper lists
var/tmp/list/desc_list = list()
var/tmp/list/damage_list = list()
New(var/damage)
created = world.time
// reading from a list("stage" = damage) is pretty difficult, so build two separate
// lists from them instead
for(var/V in stages)
desc_list += V
damage_list += stages[V]
src.damage = damage
// initialize with the first stage
next_stage()
// this will ensure the size of the wound matches the damage
src.heal_damage(0)
// returns 1 if there's a next stage, 0 otherwise
proc/next_stage()
if(current_stage + 1 > src.desc_list.len)
return 0
current_stage++
src.min_damage = damage_list[current_stage]
src.desc = desc_list[current_stage]
return 1
// returns 1 if the wound has started healing
proc/started_healing()
return (current_stage > 1)
// checks whether the wound has been appropriately treated
// always returns 1 for wounds that don't need to be treated
proc/is_treated()
if(!needs_treatment) return 1
if(damage_type == BRUISE || damage_type == CUT)
return bandaged
else if(damage_type == BURN)
return salved
// heal the given amount of damage, and if the given amount of damage was more
// than what needed to be healed, return how much heal was left
proc/heal_damage(amount)
var/healed_damage = min(src.damage, amount)
amount -= healed_damage
src.damage -= healed_damage
while(src.damage / src.amount < damage_list[current_stage] && current_stage < src.desc_list.len)
current_stage++
desc = desc_list[current_stage]
// return amount of healing still leftover, can be used for other wounds
return amount
// opens the wound again
proc/open_wound()
if(current_stage > 1)
// e.g. current_stage is 2, then reset it to 0 and do next_stage(), bringing it to 1
src.current_stage -= 2
next_stage()
src.damage = src.min_damage + 5
/** CUTS **/
/datum/wound/cut
// link wound descriptions to amounts of damage
stages = list("cut" = 5, "healing cut" = 2, "small scab" = 0)
/datum/wound/deep_cut
stages = list("deep cut" = 15, "clotted cut" = 8, "scab" = 2, "fresh skin" = 0)
/datum/wound/flesh_wound
stages = list("flesh wound" = 25, "blood soaked clot" = 15, "large scab" = 5, "fresh skin" = 0)
/datum/wound/gaping_wound
stages = list("gaping wound" = 50, "large blood soaked clot" = 25, "large clot" = 15, "small angry scar" = 5, \
"small straight scar" = 0)
/datum/wound/big_gaping_wound
stages = list("big gaping wound" = 60, "gauze wrapped wound" = 50, "blood soaked bandage" = 25,\
"large angry scar" = 10, "large straight scar" = 0)
needs_treatment = 1 // this only heals when bandaged
/datum/wound/massive_wound
stages = list("massive wound" = 70, "massive blood soaked bandage" = 40, "huge bloody mess" = 20,\
"massive angry scar" = 10, "massive jagged scar" = 0)
needs_treatment = 1 // this only heals when bandaged
/** BRUISES **/
/datum/wound/bruise
stages = list("monumental bruise" = 80, "huge bruise" = 50, "large bruise" = 30,\
"moderate bruise" = 20, "small bruise" = 10, "tiny bruise" = 5)
needs_treatment = 1 // this only heals when bandaged
damage_type = BRUISE
/datum/wound/bruise/monumental_bruise
// implement sub-paths by starting at a later stage
/datum/wound/bruise/huge_bruise
current_stage = 1
/datum/wound/bruise/large_bruise
current_stage = 2
/datum/wound/bruise/moderate_bruise
current_stage = 3
needs_treatment = 0
/datum/wound/bruise/small_bruise
current_stage = 4
needs_treatment = 0
/datum/wound/bruise/tiny_bruise
current_stage = 5
needs_treatment = 0
/** BURNS **/
/datum/wound/moderate_burn
stages = list("moderate burn" = 5, "moderate salved burn" = 2, "fresh skin" = 0)
needs_treatment = 1 // this only heals when bandaged
damage_type = BURN
/datum/wound/large_burn
stages = list("large burn" = 15, "large salved burn" = 5, "fresh skin" = 0)
needs_treatment = 1 // this only heals when bandaged
damage_type = BURN
/datum/wound/severe_burn
stages = list("severe burn" = 30, "severe salved burn" = 10, "burn scar" = 0)
needs_treatment = 1 // this only heals when bandaged
damage_type = BURN
/datum/wound/deep_burn
stages = list("deep burn" = 40, "deep salved burn" = 15, "large burn scar" = 0)
needs_treatment = 1 // this only heals when bandaged
damage_type = BURN
/datum/wound/carbonised_area
stages = list("carbonised area" = 50, "treated carbonised area" = 20, "massive burn scar" = 0)
needs_treatment = 1 // this only heals when bandaged
damage_type = BURN
+4
View File
@@ -1355,6 +1355,7 @@
m_amt = 12000
origin_tech = "materials=1"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharp = 1
/obj/item/weapon/kitchenknife/ritual
name = "ritual knife"
@@ -1436,6 +1437,7 @@
icon_state = "knife"
force = 10.0
throwforce = 10.0
sharp = 1
/obj/item/weapon/kitchen/utensil/spoon
name = "spoon"
@@ -1458,6 +1460,7 @@
g_amt = 5000
origin_tech = "materials=1;biotech=1"
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharp = 1
/obj/item/weapon/retractor
name = "retractor"
@@ -1524,6 +1527,7 @@
g_amt = 10000
origin_tech = "materials=1;biotech=1"
attack_verb = list("attacked", "slashed", "sawed", "cut")
sharp = 1
/obj/item/weapon/syntiflesh
name = "syntiflesh"
-2
View File
@@ -505,8 +505,6 @@
for(var/obj/T in (M.contents-implants))
del(T)
//for(var/R in M.organs)
// del(M.organs[text("[]", R)])
O.loc = M.loc
@@ -844,15 +844,16 @@ ________________________________________________________________________________
U << "\red Procedure interrupted. Protocol terminated."
return
else if(istype(I, /obj/item/weapon/disk/tech_disk))//If it's a data disk, we want to copy the research on to the suit.
if(I:stored)//If it has something on it.
var/obj/item/weapon/disk/tech_disk/tdisk = I
if(tdisk.stored)//If it has something on it.
U << "Research information detected, processing..."
if(do_after(U,s_delay))
for(var/datum/tech/current_data in stored_research)
if(current_data.id==I:stored.id)
if(current_data.level<I:stored.level)
current_data.level=I:stored.level
if(current_data.id==tdisk.stored.id)
if(current_data.level<tdisk.stored.level)
current_data.level=tdisk.stored.level
break
I:stored = null
tdisk.stored = null
U << "\blue Data analyzed and updated. Disk erased."
else
U << "\red <b>ERROR</b>: \black Procedure interrupted. Process terminated."
+2 -2
View File
@@ -837,8 +837,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
C.loc = src
user << "<span class='notice'>You insert [C] into [src].</span>"
cartridge = C
if(C:radio)
C:radio.hostpda = src
if(cartridge.radio)
cartridge.radio.hostpda = src
else if(istype(C, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/idcard = C
+1
View File
@@ -11,6 +11,7 @@
animate_movement = 2
var/throwforce = 1
var/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
var/sharp = 0 // whether this object cuts
/obj/proc/process()
processing_objects.Remove(src)
+13
View File
@@ -203,3 +203,16 @@
//if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand
return items
/** BS12's proc to get the item in the active hand. Couldn't find the /tg/ equivalent. **/
/mob/proc/equipped()
if(issilicon(src))
if(isrobot(src))
if(src:module_active)
return src:module_active
else
if (hand)
return l_hand
else
return r_hand
return
@@ -10,3 +10,8 @@
var/silent = null //Can't talk. Value goes down every life proc.
var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
// total amount of wounds on mob, used to spread out healing and the like over all wounds
var/number_wounds = 0
+142 -34
View File
@@ -201,40 +201,6 @@
msg += "...</span>\n"
else
msg += "<span class='warning'>"
var/temp = getBruteLoss() //no need to calculate each of these twice
if(temp)
if(temp < 30)
msg += "[t_He] [t_has] minor bruising.\n"
else
msg += "<B>[t_He] [t_has] severe bruising!</B>\n"
temp = getFireLoss()
if(temp)
if(temp < 30)
msg += "[t_He] [t_has] minor burns.\n"
else
msg += "<B>[t_He] [t_has] severe burns!</B>\n"
temp = getCloneLoss()
if(temp)
if(temp < 30)
msg += "[t_He] [t_has] minor genetic deformities.\n"
else
msg += "<B>[t_He] [t_has] severe genetic deformities.</B>\n"
if(nutrition < 100)
msg += "[t_He] [t_is] severely malnourished.\n"
else if(nutrition >= 500)
if(usr.nutrition < 100)
msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else
msg += "[t_He] [t_is] quite chubby.\n"
msg += "</span>"
if(stat == UNCONSCIOUS)
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n"
else if(getBrainLoss() >= 60)
@@ -245,6 +211,148 @@
else if(!client)
msg += "[t_He] [t_has] a vacant, braindead stare...\n"
msg += "<span class='warning'>"
if(nutrition < 100)
msg += "[t_He] [t_is] severely malnourished.\n"
else if(nutrition >= 500)
if(usr.nutrition < 100)
msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else
msg += "[t_He] [t_is] quite chubby.\n"
msg += "</span>"
var/list/wound_flavor_text = list()
var/list/is_destroyed = list()
var/list/is_bleeding = list()
for(var/datum/organ/external/temp in organs)
if(temp)
if(temp.status & ORGAN_DESTROYED)
is_destroyed["[temp.display_name]"] = 1
wound_flavor_text["[temp.display_name]"] = "<span class='warning'><b>[t_He] is missing [t_his] [temp.display_name].</b></span>\n"
continue
if(temp.status & ORGAN_ROBOT)
if(!(temp.brute_dam + temp.burn_dam))
wound_flavor_text["[temp.display_name]"] = "<span class='warning'>[t_He] has a robot [temp.display_name]!</span>\n"
continue
else
wound_flavor_text["[temp.display_name]"] = "<span class='warning'>[t_He] has a robot [temp.display_name], it has"
if(temp.brute_dam) switch(temp.brute_dam)
if(0 to 20)
wound_flavor_text["[temp.display_name]"] += " some dents"
if(21 to INFINITY)
wound_flavor_text["[temp.display_name]"] += pick(" a lot of dents"," severe denting")
if(temp.brute_dam && temp.burn_dam)
wound_flavor_text["[temp.display_name]"] += " and"
if(temp.burn_dam) switch(temp.burn_dam)
if(0 to 20)
wound_flavor_text["[temp.display_name]"] += " some burns"
if(21 to INFINITY)
wound_flavor_text["[temp.display_name]"] += pick(" a lot of burns"," severe melting")
wound_flavor_text["[temp.display_name]"] += "!</span>\n"
else if(temp.wounds.len > 0)
var/list/wound_descriptors = list()
for(var/datum/wound/W in temp.wounds)
if(W.desc in wound_descriptors)
wound_descriptors[W.desc] += W.amount
continue
wound_descriptors[W.desc] = W.amount
var/list/flavor_text = list()
var/list/no_exclude = list("gaping wound", "big gaping wound", "massive wound", "large bruise",\
"huge bruise", "massive bruise", "severe burn", "large burn", "deep burn", "carbonised area")
for(var/wound in wound_descriptors)
switch(wound_descriptors[wound])
if(1)
if(!flavor_text.len)
flavor_text += "<span class='warning'>[t_He] has[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a [wound]"
else
flavor_text += "[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a [wound]"
if(2)
if(!flavor_text.len)
flavor_text += "<span class='warning'>[t_He] has[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a pair of [wound]s"
else
flavor_text += "[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a pair of [wound]s"
if(3 to 5)
if(!flavor_text.len)
flavor_text += "<span class='warning'>[t_He] has several [wound]s"
else
flavor_text += " several [wound]s"
if(6 to INFINITY)
if(!flavor_text.len)
flavor_text += "<span class='warning'>[t_He] has a bunch of [wound]s"
else
flavor_text += " a ton of [wound]\s"
var/flavor_text_string = ""
for(var/text = 1, text <= flavor_text.len, text++)
if(text == flavor_text.len && flavor_text.len > 1)
flavor_text_string += ", and"
else if(flavor_text.len > 1 && text > 1)
flavor_text_string += ","
flavor_text_string += flavor_text[text]
flavor_text_string += " on [t_his] [temp.display_name].</span><br>"
wound_flavor_text["[temp.name]"] = flavor_text_string
if(temp.status & ORGAN_BLEEDING)
is_bleeding["[temp.name]"] = 1
else
wound_flavor_text["[temp.display_name]"] = ""
//Handles the text strings being added to the actual description.
//If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext.
var/display_chest = 0
var/display_shoes = 0
var/display_gloves = 0
if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas)))))
msg += wound_flavor_text["head"]
else if(is_bleeding["head"])
msg += "<span class='warning'>[src] has blood running down [t_his] face!</span>\n"
if(wound_flavor_text["chest"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you.
msg += wound_flavor_text["chest"]
else if(is_bleeding["chest"])
display_chest = 1
if(wound_flavor_text["left arm"] && (is_destroyed["left arm"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["left arm"]
else if(is_bleeding["left arm"])
display_chest = 1
if(wound_flavor_text["left hand"] && (is_destroyed["left hand"] || (!gloves && !skipgloves)))
msg += wound_flavor_text["left hand"]
else if(is_bleeding["left hand"])
display_gloves = 1
if(wound_flavor_text["right arm"] && (is_destroyed["right arm"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["right arm"]
else if(is_bleeding["right arm"])
display_chest = 1
if(wound_flavor_text["right hand"] && (is_destroyed["right hand"] || (!gloves && !skipgloves)))
msg += wound_flavor_text["right hand"]
else if(is_bleeding["right hand"])
display_gloves = 1
if(wound_flavor_text["groin"] && (is_destroyed["groin"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["groin"]
else if(is_bleeding["groin"])
display_chest = 1
if(wound_flavor_text["left leg"] && (is_destroyed["left leg"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["left leg"]
else if(is_bleeding["left leg"])
display_chest = 1
if(wound_flavor_text["left foot"]&& (is_destroyed["left foot"] || (!shoes && !skipshoes)))
msg += wound_flavor_text["left foot"]
else if(is_bleeding["left foot"])
display_shoes = 1
if(wound_flavor_text["right leg"] && (is_destroyed["right leg"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["right leg"]
else if(is_bleeding["right leg"])
display_chest = 1
if(wound_flavor_text["right foot"]&& (is_destroyed["right foot"] || (!shoes && !skipshoes)))
msg += wound_flavor_text["right foot"]
else if(is_bleeding["right foot"])
display_shoes = 1
if(display_chest)
msg += "<span class='warning'><b>[src] has blood soaking through from under [t_his] clothing!</b></span>\n"
if(display_shoes)
msg += "<span class='warning'><b>[src] has blood running from [t_his] shoes!</b></span>\n"
if(display_gloves)
msg += "<span class='warning'><b>[src] has blood running from under [t_his] gloves!</b></span>\n"
if(digitalcamo)
msg += "[t_He] [t_is] repulsively uncanny!\n"
@@ -587,6 +587,8 @@
mymob.flash.screen_loc = "1,1 to 15,15"
mymob.flash.layer = 17
mymob.pain = new /obj/screen( null )
/*
mymob.hands = new /obj/screen( null )
mymob.hands.icon = ui_style
+27 -4
View File
@@ -21,8 +21,31 @@
dna = new /datum/dna(null)
//initialise organs
organs = newlist(/datum/organ/external/chest, /datum/organ/external/head, /datum/organ/external/l_arm, \
/datum/organ/external/r_arm, /datum/organ/external/r_leg, /datum/organ/external/l_leg)
organs = list()
organs_by_name["chest"] = new/datum/organ/external/chest()
organs_by_name["head"] = new/datum/organ/external/head()
organs_by_name["l_arm"] = new/datum/organ/external/l_arm()
organs_by_name["r_arm"] = new/datum/organ/external/r_arm()
organs_by_name["r_leg"] = new/datum/organ/external/r_leg()
organs_by_name["l_leg"] = new/datum/organ/external/l_leg()
organs_by_name["l_hand"] = new/datum/organ/external/l_hand()
organs_by_name["r_hand"] = new/datum/organ/external/r_hand()
organs_by_name["l_foot"] = new/datum/organ/external/l_foot()
organs_by_name["r_foot"] = new/datum/organ/external/r_foot()
// connect feet to legs and hands to arms
var/datum/organ/external/organ = organs_by_name["l_hand"]
organ.parent = organs_by_name["l_arm"]
organ = organs_by_name["r_hand"]
organ.parent = organs_by_name["r_arm"]
organ = organs_by_name["l_foot"]
organ.parent = organs_by_name["l_leg"]
organ = organs_by_name["r_foot"]
organ.parent = organs_by_name["r_leg"]
for(var/name in organs_by_name)
organs += organs_by_name[name]
for(var/datum/organ/external/O in organs)
O.owner = src
@@ -518,8 +541,8 @@
//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable
/mob/living/carbon/human/proc/get_face_name()
var/datum/organ/external/O = get_organ("head")
if( (status_flags&DISFIGURED) || (O.brutestate+O.burnstate)>2 || !real_name ) //disfigured. use id-name if possible
var/datum/organ/external/head/head = get_organ("head")
if( !head || head.disfigured || !real_name ) //disfigured. use id-name if possible
return "Unknown"
return real_name
@@ -86,11 +86,11 @@
//Damages ONE external organ, organ gets randomly selected from damagable ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/take_organ_damage(var/brute, var/burn)
/mob/living/carbon/human/take_organ_damage(var/brute, var/burn, var/sharp = 0)
var/list/datum/organ/external/parts = get_damageable_organs()
if(!parts.len) return
var/datum/organ/external/picked = pick(parts)
if(picked.take_damage(brute,burn))
if(picked.take_damage(brute,burn,sharp))
UpdateDamageIcon()
updatehealth()
@@ -116,7 +116,7 @@
if(update) UpdateDamageIcon()
// damage MANY external organs, in random order
/mob/living/carbon/human/take_overall_damage(var/brute, var/burn)
/mob/living/carbon/human/take_overall_damage(var/brute, var/burn, var/sharp = 0)
if(nodamage) return //godmode
var/list/datum/organ/external/parts = get_damageable_organs()
var/update = 0
@@ -126,7 +126,7 @@
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.take_damage(brute,burn)
update |= picked.take_damage(brute,burn,sharp)
brute -= (picked.brute_dam - brute_was)
burn -= (picked.burn_dam - burn_was)
@@ -150,19 +150,17 @@
/mob/living/carbon/human/proc/get_organ(var/zone)
if(!zone) zone = "chest"
for(var/datum/organ/external/O in organs)
if(O.name == zone)
return O
return null
return organs_by_name[zone]
/mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0)
/mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/obj/item/weapon)
if((damagetype != BRUTE) && (damagetype != BURN))
..(damage, damagetype, def_zone, blocked)
return 1
if(blocked >= 2) return 0
var/sharp = weapon.sharp
var/datum/organ/external/organ = null
if(isorgan(def_zone))
organ = def_zone
@@ -178,10 +176,10 @@
switch(damagetype)
if(BRUTE)
if(organ.take_damage(damage, 0))
if(organ.take_damage(damage, 0, sharp))
UpdateDamageIcon()
if(BURN)
if(organ.take_damage(0, damage))
if(organ.take_damage(0, damage, sharp))
UpdateDamageIcon()
updatehealth()
return 1
@@ -44,6 +44,7 @@
var/icon/lying_icon = null
var/list/organs = list()
var/list/organs_by_name = list() // map organ names to organs
var/miming = null //Toggle for the mime's abilities.
@@ -53,6 +53,8 @@
fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it.
//TODO: seperate this out
// update the current life tick, can be used to e.g. only do something every 4 ticks
life_tick++
var/datum/gas_mixture/environment = loc.return_air()
//No need to update all of these procs if the guy is dead.
@@ -167,6 +169,71 @@
if(3)
emote("drool")
proc/handle_organs()
// take care of organ related updates, such as broken and missing limbs
// recalculate number of wounds
number_wounds = 0
for(var/datum/organ/external/E in organs)
if(!E)
world << name
continue
number_wounds += E.number_wounds
var/leg_tally = 2
for(var/datum/organ/external/E in organs)
E.process()
if(E.status & ORGAN_ROBOT && prob(E.brute_dam + E.burn_dam))
if(E.name == "l_hand" || E.name == "l_arm")
if(hand && equipped())
drop_item()
emote("custom v drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else if(E.name == "r_hand" || E.name == "r_arm")
if(!hand && equipped())
drop_item()
emote("custom v drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else if(E.name == "l_leg" || E.name == "l_foot" \
|| E.name == "r_leg" || E.name == "r_foot" && !lying)
leg_tally-- // let it fail even if just foot&leg
if(E.status & ORGAN_BROKEN || E.status & ORGAN_DESTROYED)
if(E.name == "l_hand" || E.name == "l_arm")
if(hand && equipped())
if(E.status & ORGAN_SPLINTED && prob(10))
drop_item()
emote("scream")
else
drop_item()
emote("scream")
else if(E.name == "r_hand" || E.name == "r_arm")
if(!hand && equipped())
if(E.status & ORGAN_SPLINTED && prob(10))
drop_item()
emote("scream")
else
drop_item()
emote("scream")
else if(E.name == "l_leg" || E.name == "l_foot" \
|| E.name == "r_leg" || E.name == "r_foot" && !lying)
if(!(E.status & ORGAN_SPLINTED))
leg_tally-- // let it fail even if just foot&leg
// can't stand
if(leg_tally == 0 && !paralysis && !(lying || resting))
emote("scream")
emote("collapse")
paralysis = 10
proc/handle_mutations_and_radiation()
if(getFireLoss())
@@ -817,6 +884,7 @@
silent = 0
else //ALIVE. LIGHTS ARE ON
updatehealth() //TODO
handle_organs()
if(health <= config.health_threshold_dead || brain_op_stage == 4.0)
death()
blinded = 1
@@ -122,6 +122,7 @@ Please contact me on #coderbus IRC. ~Carn x
/mob/living/carbon/human
var/list/overlays_lying[TOTAL_LAYERS]
var/list/overlays_standing[TOTAL_LAYERS]
var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed
//UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING
@@ -164,39 +165,108 @@ Please contact me on #coderbus IRC. ~Carn x
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists
/mob/living/carbon/human/UpdateDamageIcon(var/update_icons=1)
var/image/standing = image("icon" = 'icons/mob/dam_human.dmi', "icon_state" = "blank")
var/image/lying = image("icon" = 'icons/mob/dam_human.dmi', "icon_state" = "blank2")
for(var/datum/organ/external/O in organs)
if(O.brutestate)
standing.overlays += "[O.icon_name]_[O.brutestate]0" //we're adding icon_states of the base image as overlays
lying.overlays += "[O.icon_name]2_[O.brutestate]0"
if(O.burnstate)
standing.overlays += "[O.icon_name]_0[O.burnstate]"
lying.overlays += "[O.icon_name]2_0[O.burnstate]"
// first check whether something actually changed about damage appearance
var/damage_appearance = ""
for(var/datum/organ/external/O in organs)
if(O.status & ORGAN_DESTROYED) damage_appearance += "d"
else
damage_appearance += O.damage_state
if(damage_appearance == previous_damage_appearance)
// nothing to do here
return
previous_damage_appearance = damage_appearance
var/icon/standing = new /icon('dam_human.dmi', "00")
var/icon/lying = new /icon('dam_human.dmi', "00-2")
// blend the individual damage states with our icons
for(var/datum/organ/external/O in organs)
if(!(O.status & ORGAN_DESTROYED))
O.update_icon()
var/icon/DI = new /icon('icons/mob/dam_human.dmi', O.damage_state) // the damage icon for whole human
DI.Blend(new /icon('dam_mask.dmi', O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels
standing.Blend(DI,ICON_OVERLAY)
DI = new /icon('icons/mob/dam_human.dmi', "[O.damage_state]-2") // repeat for lying icons
DI.Blend(new /icon('dam_mask.dmi', "[O.icon_name]2"), ICON_MULTIPLY)
lying.Blend(DI,ICON_OVERLAY)
var/image/standing_image = new /image("icon" = standing)
var/image/lying_image = new /image("icon" = lying)
overlays_standing[DAMAGE_LAYER] = standing_image
overlays_lying[DAMAGE_LAYER] = lying_image
overlays_standing[DAMAGE_LAYER] = standing
overlays_lying[DAMAGE_LAYER] = lying
if(update_icons) update_icons()
//BASE MOB SPRITE
/mob/living/carbon/human/proc/update_body(var/update_icons=1)
if(stand_icon) del(stand_icon)
if(lying_icon) del(lying_icon)
if(dna && dna.mutantrace) return
var/husk = (HUSK in src.mutations)
var/fat = (FAT in src.mutations)
var/g = "m"
if(gender == FEMALE) g = "f"
var/husk = (HUSK in src.mutations)
var/obese = (FAT in src.mutations)
// whether to draw the individual limbs
var/individual_limbs = 1
//Base mob icon
if(husk)
stand_icon = new /icon('icons/mob/human.dmi', "husk_s")
lying_icon = new /icon('icons/mob/human.dmi', "husk_l")
else if(fat)
if(obese)
// Sorry, no dismemberment for fat people.
stand_icon = new /icon('icons/mob/human.dmi', "fatbody_s")
lying_icon = new /icon('icons/mob/human.dmi', "fatbody_l")
individual_limbs = 0
else
stand_icon = new /icon('icons/mob/human.dmi', "body_[g]_s")
lying_icon = new /icon('icons/mob/human.dmi', "body_[g]_l")
stand_icon = new /icon('icons/mob/human.dmi', "torso_[g]_s")
lying_icon = new /icon('icons/mob/human.dmi', "torso_[g]_l")
// Draw each individual limb
if(individual_limbs)
stand_icon.Blend(new /icon('icons/mob/human.dmi', "chest_[g]_s"), ICON_OVERLAY)
lying_icon.Blend(new /icon('icons/mob/human.dmi', "chest_[g]_l"), ICON_OVERLAY)
var/datum/organ/external/head = get_organ("head")
if(head && !(head.status & ORGAN_DESTROYED))
stand_icon.Blend(new /icon('icons/mob/human.dmi', "head_[g]_s"), ICON_OVERLAY)
lying_icon.Blend(new /icon('icons/mob/human.dmi', "head_[g]_l"), ICON_OVERLAY)
for(var/datum/organ/external/part in organs)
if(!istype(part, /datum/organ/external/groin) \
&& !istype(part, /datum/organ/external/chest) \
&& !istype(part, /datum/organ/external/head) \
&& !(part.status & ORGAN_DESTROYED))
var/icon/temp = new /icon('human.dmi', "[part.icon_name]_s")
if(part.status & ORGAN_ROBOT) temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
stand_icon.Blend(temp, ICON_OVERLAY)
temp = new /icon('human.dmi', "[part.icon_name]_l")
if(part.status & ORGAN_ROBOT) temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
lying_icon.Blend(temp , ICON_OVERLAY)
stand_icon.Blend(new /icon('human.dmi', "groin_[g]_s"), ICON_OVERLAY)
lying_icon.Blend(new /icon('human.dmi', "groin_[g]_l"), ICON_OVERLAY)
if (husk)
var/icon/husk_s = new /icon('human.dmi', "husk_s")
var/icon/husk_l = new /icon('human.dmi', "husk_l")
for(var/datum/organ/external/part in organs)
if(!istype(part, /datum/organ/external/groin) \
&& !istype(part, /datum/organ/external/chest) \
&& !istype(part, /datum/organ/external/head) \
&& (part.status & ORGAN_DESTROYED))
husk_s.Blend(new /icon('dam_mask.dmi', "[part.icon_name]"), ICON_SUBTRACT)
husk_l.Blend(new /icon('dam_mask.dmi', "[part.icon_name]2"), ICON_SUBTRACT)
stand_icon.Blend(husk_s, ICON_OVERLAY)
lying_icon.Blend(husk_l, ICON_OVERLAY)
//Skin tone
if(s_tone >= 0)
@@ -207,6 +277,7 @@ Please contact me on #coderbus IRC. ~Carn x
lying_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT)
//Eyes
// Note: These used to be in update_face(), and the fact they're here will make it difficult to create a disembodied head
var/icon/eyes_s = new/icon('icons/mob/human_face.dmi', "eyes_s")
var/icon/eyes_l = new/icon('icons/mob/human_face.dmi', "eyes_l")
eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD)
@@ -219,11 +290,11 @@ Please contact me on #coderbus IRC. ~Carn x
lying_icon.Blend(new/icon('icons/mob/human_face.dmi', "mouth_[g]_l"), ICON_OVERLAY)
//Underwear
if(underwear < 12 && underwear > 0)
if(!fat)
stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY)
lying_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_l"), ICON_OVERLAY)
if(update_icons) update_icons()
if(underwear < 6 && underwear > 0)
if(!obese)
stand_icon.Blend(new /icon('human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY)
lying_icon.Blend(new /icon('human.dmi', "underwear[underwear]_[g]_l"), ICON_OVERLAY)
//HAIR OVERLAY
@@ -649,6 +720,42 @@ Please contact me on #coderbus IRC. ~Carn x
overlays_standing[L_HAND_LAYER] = null
if(update_icons) update_icons()
// Used mostly for creating head items
/mob/living/carbon/human/proc/generate_head_icon()
var/g = "m"
if (gender == FEMALE) g = "f"
//base icons
var/icon/face_lying = new /icon('icons/mob/human_face.dmi',"bald_l")
if(f_style)
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style]
if(facial_hair_style)
var/icon/facial_l = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_l")
facial_l.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD)
face_lying.Blend(facial_l, ICON_OVERLAY)
if(h_style)
var/datum/sprite_accessory/hair_style = hair_styles_list[h_style]
if(hair_style)
var/icon/hair_l = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_l")
hair_l.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD)
face_lying.Blend(hair_l, ICON_OVERLAY)
//Eyes
// Note: These used to be in update_face(), and the fact they're here will make it difficult to create a disembodied head
var/icon/eyes_s = new/icon('icons/mob/human_face.dmi', "eyes_s")
var/icon/eyes_l = new/icon('icons/mob/human_face.dmi', "eyes_l")
eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD)
eyes_l.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD)
face_lying.Blend(eyes_l, ICON_OVERLAY)
//Mouth
face_lying.Blend(new/icon('icons/mob/human_face.dmi', "mouth_[g]_l"), ICON_OVERLAY)
var/image/face_lying_image = new /image(icon = face_lying)
return face_lying_image
//Human Overlays Indexes/////////
#undef MUTANTRACE_LAYER
#undef MUTATIONS_LAYER
+1
View File
@@ -30,6 +30,7 @@
var/obj/screen/nutrition_icon = null
var/obj/screen/pressure = null
var/obj/screen/damageoverlay = null
var/obj/screen/pain = null
/*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob.
A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such.
+3
View File
@@ -115,6 +115,9 @@ proc/isorgan(A)
return 1
return 0
proc/hasorgans(A)
return (ishuman(A) || ismonkey(A))
/proc/hsl2rgb(h, s, l)
return
+33
View File
@@ -500,3 +500,36 @@ var/list/liftable_structures = list(\
//some arbitrary defines to be used by self-pruning global lists. (see master_controller)
#define PROCESS_KILL 26 //Used to trigger removal from a processing list
//Damage things
#define CUT "cut"
#define BRUISE "bruise"
#define BRUTE "brute"
#define BURN "fire"
#define TOX "tox"
#define OXY "oxy"
#define CLONE "clone"
#define HALLOSS "halloss"
#define STUN "stun"
#define WEAKEN "weaken"
#define PARALYZE "paralize"
#define IRRADIATE "irradiate"
#define STUTTER "stutter"
#define SLUR "slur"
#define EYE_BLUR "eye_blur"
#define DROWSY "drowsy"
/////////////////
//ORGAN DEFINES//
/////////////////
#define ORGAN_CUT_AWAY 1
#define ORGAN_GAUZED 2
#define ORGAN_ATTACHABLE 4
#define ORGAN_BLEEDING 8
#define ORGAN_BANDAGED 16
#define ORGAN_BROKEN 32
#define ORGAN_DESTROYED 64
#define ORGAN_ROBOT 128
#define ORGAN_SPLINTED 256
#define SALVED 512
+8
View File
@@ -6,6 +6,14 @@ HEALTH_THRESHOLD_CRIT 0
## level of health at which a mob becomes dead
HEALTH_THRESHOLD_DEAD -100
## multiplier which enables organs to take more damage before bones breaking or limbs being destroyed
## 100 means normal, 50 means half
ORGAN_HEALTH_MULTIPLIER 100
## multiplier which influences how fast organs regenerate naturally
## 100 means normal, 50 means half
ORGAN_REGENERATION_MULTIPLIER 100
### REVIVAL ###
## whether pod plants work or not
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

+1 -1
View File
@@ -223,7 +223,6 @@
// END_FILE_DIR
// BEGIN_PREFERENCES
#define DEBUG
// END_PREFERENCES
// BEGIN_INCLUDE
@@ -307,6 +306,7 @@
#include "code\datums\helper_datums\topic_input.dm"
#include "code\datums\organs\organ.dm"
#include "code\datums\organs\organ_external.dm"
#include "code\datums\organs\wound.dm"
#include "code\datums\spells\area_teleport.dm"
#include "code\datums\spells\conjure.dm"
#include "code\datums\spells\emplosion.dm"