mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 16:07:40 +00:00
* first series of updates * datums * games folder * admin and atmosia stuffs * moar * mob updates borg riding * sprites and stuff * fixes for various things * oops. some missed fixes
796 lines
24 KiB
Plaintext
796 lines
24 KiB
Plaintext
/mob/living/carbon
|
|
blood_volume = BLOOD_VOLUME_NORMAL
|
|
|
|
/mob/living/carbon/New()
|
|
create_reagents(1000)
|
|
update_body_parts() //to update the carbon's new bodyparts appearance
|
|
..()
|
|
|
|
/mob/living/carbon/Destroy()
|
|
for(var/guts in internal_organs)
|
|
qdel(guts)
|
|
for(var/atom/movable/food in stomach_contents)
|
|
qdel(food)
|
|
for(var/BP in bodyparts)
|
|
qdel(BP)
|
|
for(var/imp in implants)
|
|
qdel(imp)
|
|
bodyparts = list()
|
|
remove_from_all_data_huds()
|
|
if(dna)
|
|
qdel(dna)
|
|
return ..()
|
|
|
|
/mob/living/carbon/relaymove(mob/user, direction)
|
|
if(user in src.stomach_contents)
|
|
if(prob(40))
|
|
if(prob(25))
|
|
audible_message("<span class='warning'>You hear something rumbling inside [src]'s stomach...</span>", \
|
|
"<span class='warning'>You hear something rumbling.</span>", 4,\
|
|
"<span class='userdanger'>Something is rumbling inside your stomach!</span>")
|
|
var/obj/item/I = user.get_active_held_item()
|
|
if(I && I.force)
|
|
var/d = rand(round(I.force / 4), I.force)
|
|
var/obj/item/bodypart/BP = get_bodypart("chest")
|
|
if(BP.receive_damage(d, 0))
|
|
update_damage_overlays()
|
|
visible_message("<span class='danger'>[user] attacks [src]'s stomach wall with the [I.name]!</span>", \
|
|
"<span class='userdanger'>[user] attacks your stomach wall with the [I.name]!</span>")
|
|
playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
|
|
|
|
if(prob(src.getBruteLoss() - 50))
|
|
for(var/atom/movable/A in stomach_contents)
|
|
A.loc = loc
|
|
stomach_contents.Remove(A)
|
|
src.gib()
|
|
|
|
|
|
/mob/living/carbon/swap_hand(held_index)
|
|
if(!held_index)
|
|
held_index = (active_hand_index % held_items.len)+1
|
|
|
|
var/obj/item/item_in_hand = src.get_active_held_item()
|
|
if(item_in_hand) //this segment checks if the item in your hand is twohanded.
|
|
if(istype(item_in_hand,/obj/item/weapon/twohanded))
|
|
if(item_in_hand:wielded == 1)
|
|
usr << "<span class='warning'>Your other hand is too busy holding the [item_in_hand.name]</span>"
|
|
return
|
|
var/oindex = active_hand_index
|
|
active_hand_index = held_index
|
|
if(hud_used)
|
|
var/obj/screen/inventory/hand/H
|
|
H = hud_used.hand_slots["[oindex]"]
|
|
if(H)
|
|
H.update_icon()
|
|
H = hud_used.hand_slots["[held_index]"]
|
|
if(H)
|
|
H.update_icon()
|
|
|
|
|
|
/mob/living/carbon/activate_hand(selhand) //l/r OR 1-held_items.len
|
|
if(!selhand)
|
|
selhand = (active_hand_index % held_items.len)+1
|
|
|
|
if(istext(selhand))
|
|
selhand = lowertext(selhand)
|
|
if(selhand == "right" || selhand == "r")
|
|
selhand = 2
|
|
if(selhand == "left" || selhand == "l")
|
|
selhand = 1
|
|
|
|
if(selhand != active_hand_index)
|
|
swap_hand(selhand)
|
|
else
|
|
mode() // Activate held item
|
|
|
|
/mob/living/carbon/attackby(obj/item/I, mob/user, params)
|
|
if(lying && surgeries.len)
|
|
if(user != src && user.a_intent == INTENT_HELP)
|
|
for(var/datum/surgery/S in surgeries)
|
|
if(S.next_step(user))
|
|
return 1
|
|
return ..()
|
|
|
|
/mob/living/carbon/throw_impact(atom/hit_atom, throwingdatum)
|
|
. = ..()
|
|
var/hurt = TRUE
|
|
if(istype(throwingdatum, /datum/thrownthing))
|
|
var/datum/thrownthing/D = throwingdatum
|
|
if(iscyborg(D.thrower))
|
|
var/mob/living/silicon/robot/R = D.thrower
|
|
if(!R.emagged)
|
|
hurt = FALSE
|
|
if(hit_atom.density && isturf(hit_atom))
|
|
if(hurt)
|
|
Weaken(1)
|
|
take_bodypart_damage(10)
|
|
if(iscarbon(hit_atom) && hit_atom != src)
|
|
var/mob/living/carbon/victim = hit_atom
|
|
if(victim.movement_type & FLYING)
|
|
return
|
|
if(hurt)
|
|
victim.take_bodypart_damage(10)
|
|
take_bodypart_damage(10)
|
|
victim.Weaken(1)
|
|
Weaken(1)
|
|
visible_message("<span class='danger'>[src] crashes into [victim], knocking them both over!</span>", "<span class='userdanger'>You violently crash into [victim]!</span>")
|
|
playsound(src,'sound/weapons/punch1.ogg',50,1)
|
|
|
|
|
|
//Throwing stuff
|
|
/mob/living/carbon/proc/toggle_throw_mode()
|
|
if(stat)
|
|
return
|
|
if(in_throw_mode)
|
|
throw_mode_off()
|
|
else
|
|
throw_mode_on()
|
|
|
|
|
|
/mob/living/carbon/proc/throw_mode_off()
|
|
in_throw_mode = 0
|
|
if(client && hud_used)
|
|
hud_used.throw_icon.icon_state = "act_throw_off"
|
|
|
|
|
|
/mob/living/carbon/proc/throw_mode_on()
|
|
in_throw_mode = 1
|
|
if(client && hud_used)
|
|
hud_used.throw_icon.icon_state = "act_throw_on"
|
|
|
|
/mob/proc/throw_item(atom/target)
|
|
return
|
|
|
|
/mob/living/carbon/throw_item(atom/target)
|
|
throw_mode_off()
|
|
if(!target || !isturf(loc))
|
|
return
|
|
if(istype(target, /obj/screen))
|
|
return
|
|
|
|
var/atom/movable/thrown_thing
|
|
var/obj/item/I = src.get_active_held_item()
|
|
|
|
if(!I)
|
|
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
|
|
var/mob/living/throwable_mob = pulling
|
|
if(!throwable_mob.buckled)
|
|
thrown_thing = throwable_mob
|
|
stop_pulling()
|
|
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
|
|
var/turf/end_T = get_turf(target)
|
|
if(start_T && end_T)
|
|
var/start_T_descriptor = "<font color='#6b5d00'>tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]</font>"
|
|
var/end_T_descriptor = "<font color='#6b4400'>tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]</font>"
|
|
add_logs(src, throwable_mob, "thrown", addition="from [start_T_descriptor] with the target [end_T_descriptor]")
|
|
|
|
else if(!(I.flags & (NODROP|ABSTRACT)))
|
|
thrown_thing = I
|
|
dropItemToGround(I)
|
|
|
|
if(thrown_thing)
|
|
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
|
|
newtonian_move(get_dir(target, src))
|
|
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
|
|
|
|
/mob/living/carbon/restrained(ignore_grab)
|
|
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
|
|
|
|
/mob/living/carbon/proc/canBeHandcuffed()
|
|
return 0
|
|
|
|
|
|
/mob/living/carbon/show_inv(mob/user)
|
|
user.set_machine(src)
|
|
var/dat = {"
|
|
<HR>
|
|
<B><FONT size=3>[name]</FONT></B>
|
|
<HR>
|
|
<BR><B>Head:</B> <A href='?src=\ref[src];item=[slot_head]'> [(head && !(head.flags&ABSTRACT)) ? head : "Nothing"]</A>
|
|
<BR><B>Mask:</B> <A href='?src=\ref[src];item=[slot_wear_mask]'> [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"]</A>
|
|
<BR><B>Neck:</B> <A href='?src=\ref[src];item=[slot_neck]'> [(wear_neck && !(wear_neck.flags&ABSTRACT)) ? wear_neck : "Nothing"]</A>"}
|
|
|
|
for(var/i in 1 to held_items.len)
|
|
var/obj/item/I = get_item_for_held_index(i)
|
|
dat += "<BR><B>[get_held_index_name(i)]:</B></td><td><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags & ABSTRACT)) ? I : "Nothing"]</a>"
|
|
|
|
dat += "<BR><B>Back:</B> <A href='?src=\ref[src];item=[slot_back]'>[back ? back : "Nothing"]</A>"
|
|
|
|
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank))
|
|
dat += "<BR><A href='?src=\ref[src];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
|
|
|
|
if(handcuffed)
|
|
dat += "<BR><A href='?src=\ref[src];item=[slot_handcuffed]'>Handcuffed</A>"
|
|
if(legcuffed)
|
|
dat += "<BR><A href='?src=\ref[src];item=[slot_legcuffed]'>Legcuffed</A>"
|
|
|
|
dat += {"
|
|
<BR>
|
|
<BR><A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
|
|
"}
|
|
user << browse(dat, "window=mob\ref[src];size=325x500")
|
|
onclose(user, "mob\ref[src]")
|
|
|
|
/mob/living/carbon/Topic(href, href_list)
|
|
..()
|
|
//strip panel
|
|
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
|
if(href_list["internal"])
|
|
var/slot = text2num(href_list["internal"])
|
|
var/obj/item/ITEM = get_item_by_slot(slot)
|
|
if(ITEM && istype(ITEM, /obj/item/weapon/tank) && wear_mask && (wear_mask.flags & MASKINTERNALS))
|
|
visible_message("<span class='danger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM].</span>", \
|
|
"<span class='userdanger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM].</span>")
|
|
if(do_mob(usr, src, POCKET_STRIP_DELAY))
|
|
if(internal)
|
|
internal = null
|
|
update_internals_hud_icon(0)
|
|
else if(ITEM && istype(ITEM, /obj/item/weapon/tank))
|
|
if((wear_mask && (wear_mask.flags & MASKINTERNALS)) || getorganslot("breathing_tube"))
|
|
internal = ITEM
|
|
update_internals_hud_icon(1)
|
|
|
|
visible_message("<span class='danger'>[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM].</span>", \
|
|
"<span class='userdanger'>[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM].</span>")
|
|
|
|
|
|
/mob/living/carbon/fall(forced)
|
|
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing
|
|
|
|
/mob/living/carbon/is_muzzled()
|
|
return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
|
|
|
|
/mob/living/carbon/resist_buckle()
|
|
if(restrained())
|
|
changeNext_move(CLICK_CD_BREAKOUT)
|
|
last_special = world.time + CLICK_CD_BREAKOUT
|
|
visible_message("<span class='warning'>[src] attempts to unbuckle themself!</span>", \
|
|
"<span class='notice'>You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)</span>")
|
|
if(do_after(src, 600, 0, target = src))
|
|
if(!buckled)
|
|
return
|
|
buckled.user_unbuckle_mob(src,src)
|
|
else
|
|
if(src && buckled)
|
|
src << "<span class='warning'>You fail to unbuckle yourself!</span>"
|
|
else
|
|
buckled.user_unbuckle_mob(src,src)
|
|
|
|
/mob/living/carbon/resist_fire()
|
|
fire_stacks -= 5
|
|
Weaken(3, 1, 1)
|
|
spin(32,2)
|
|
visible_message("<span class='danger'>[src] rolls on the floor, trying to put themselves out!</span>", \
|
|
"<span class='notice'>You stop, drop, and roll!</span>")
|
|
sleep(30)
|
|
if(fire_stacks <= 0)
|
|
visible_message("<span class='danger'>[src] has successfully extinguished themselves!</span>", \
|
|
"<span class='notice'>You extinguish yourself.</span>")
|
|
ExtinguishMob()
|
|
return
|
|
|
|
/mob/living/carbon/resist_restraints()
|
|
var/obj/item/I = null
|
|
var/type = 0
|
|
if(handcuffed)
|
|
I = handcuffed
|
|
type = 1
|
|
else if(legcuffed)
|
|
I = legcuffed
|
|
type = 2
|
|
if(I)
|
|
if(type == 1)
|
|
changeNext_move(CLICK_CD_BREAKOUT)
|
|
last_special = world.time + CLICK_CD_BREAKOUT
|
|
if(type == 2)
|
|
changeNext_move(CLICK_CD_RANGE)
|
|
last_special = world.time + CLICK_CD_RANGE
|
|
cuff_resist(I)
|
|
|
|
|
|
/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0)
|
|
breakouttime = I.breakouttime
|
|
var/displaytime = breakouttime / 600
|
|
if(!cuff_break)
|
|
visible_message("<span class='warning'>[src] attempts to remove [I]!</span>")
|
|
src << "<span class='notice'>You attempt to remove [I]... (This will take around [displaytime] minutes and you need to stand still.)</span>"
|
|
if(do_after(src, breakouttime, 0, target = src))
|
|
clear_cuffs(I, cuff_break)
|
|
else
|
|
src << "<span class='warning'>You fail to remove [I]!</span>"
|
|
|
|
else if(cuff_break == FAST_CUFFBREAK)
|
|
breakouttime = 50
|
|
visible_message("<span class='warning'>[src] is trying to break [I]!</span>")
|
|
src << "<span class='notice'>You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)</span>"
|
|
if(do_after(src, breakouttime, 0, target = src))
|
|
clear_cuffs(I, cuff_break)
|
|
else
|
|
src << "<span class='warning'>You fail to break [I]!</span>"
|
|
|
|
else if(cuff_break == INSTANT_CUFFBREAK)
|
|
clear_cuffs(I, cuff_break)
|
|
|
|
/mob/living/carbon/proc/uncuff()
|
|
if (handcuffed)
|
|
var/obj/item/weapon/W = handcuffed
|
|
handcuffed = null
|
|
if (buckled && buckled.buckle_requires_restraints)
|
|
buckled.unbuckle_mob(src)
|
|
update_handcuffed()
|
|
if (client)
|
|
client.screen -= W
|
|
if (W)
|
|
W.loc = loc
|
|
W.dropped(src)
|
|
if (W)
|
|
W.layer = initial(W.layer)
|
|
W.plane = initial(W.plane)
|
|
if (legcuffed)
|
|
var/obj/item/weapon/W = legcuffed
|
|
legcuffed = null
|
|
update_inv_legcuffed()
|
|
if (client)
|
|
client.screen -= W
|
|
if (W)
|
|
W.loc = loc
|
|
W.dropped(src)
|
|
if (W)
|
|
W.layer = initial(W.layer)
|
|
W.plane = initial(W.plane)
|
|
|
|
/mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break)
|
|
if(!I.loc || buckled)
|
|
return
|
|
visible_message("<span class='danger'>[src] manages to [cuff_break ? "break" : "remove"] [I]!</span>")
|
|
src << "<span class='notice'>You successfully [cuff_break ? "break" : "remove"] [I].</span>"
|
|
|
|
if(cuff_break)
|
|
qdel(I)
|
|
if(I == handcuffed)
|
|
handcuffed = null
|
|
update_handcuffed()
|
|
return
|
|
else if(I == legcuffed)
|
|
legcuffed = null
|
|
update_inv_legcuffed()
|
|
return
|
|
return TRUE
|
|
|
|
else
|
|
if(I == handcuffed)
|
|
handcuffed.loc = loc
|
|
handcuffed.dropped(src)
|
|
handcuffed = null
|
|
if(buckled && buckled.buckle_requires_restraints)
|
|
buckled.unbuckle_mob(src)
|
|
update_handcuffed()
|
|
return
|
|
if(I == legcuffed)
|
|
legcuffed.loc = loc
|
|
legcuffed.dropped()
|
|
legcuffed = null
|
|
update_inv_legcuffed()
|
|
return
|
|
else
|
|
dropItemToGround(I)
|
|
return
|
|
return TRUE
|
|
|
|
/mob/living/carbon/proc/is_mouth_covered(head_only = 0, mask_only = 0)
|
|
if( (!mask_only && head && (head.flags_cover & HEADCOVERSMOUTH)) || (!head_only && wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH)) )
|
|
return 1
|
|
|
|
/mob/living/carbon/get_standard_pixel_y_offset(lying = 0)
|
|
if(lying)
|
|
return -6
|
|
else
|
|
return initial(pixel_y)
|
|
|
|
/mob/living/carbon/proc/accident(obj/item/I)
|
|
if(!I || (I.flags & (NODROP|ABSTRACT)))
|
|
return
|
|
|
|
dropItemToGround(I)
|
|
|
|
var/modifier = 0
|
|
if(disabilities & CLUMSY)
|
|
modifier -= 40 //Clumsy people are more likely to hit themselves -Honk!
|
|
|
|
switch(rand(1,100)+modifier) //91-100=Nothing special happens
|
|
if(-INFINITY to 0) //attack yourself
|
|
I.attack(src,src)
|
|
if(1 to 30) //throw it at yourself
|
|
I.throw_impact(src)
|
|
if(31 to 60) //Throw object in facing direction
|
|
var/turf/target = get_turf(loc)
|
|
var/range = rand(2,I.throw_range)
|
|
for(var/i = 1; i < range; i++)
|
|
var/turf/new_turf = get_step(target, dir)
|
|
target = new_turf
|
|
if(new_turf.density)
|
|
break
|
|
I.throw_at(target,I.throw_range,I.throw_speed,src)
|
|
if(61 to 90) //throw it down to the floor
|
|
var/turf/target = get_turf(loc)
|
|
I.throw_at(target,I.throw_range,I.throw_speed,src)
|
|
|
|
/mob/living/carbon/proc/AddAbility(obj/effect/proc_holder/alien/A)
|
|
abilities.Add(A)
|
|
A.on_gain(src)
|
|
if(A.has_action)
|
|
A.action.Grant(src)
|
|
sortInsert(abilities, /proc/cmp_abilities_cost, 0)
|
|
|
|
/mob/living/carbon/proc/RemoveAbility(obj/effect/proc_holder/alien/A)
|
|
abilities.Remove(A)
|
|
A.on_lose(src)
|
|
if(A.action)
|
|
A.action.Remove(src)
|
|
|
|
/mob/living/carbon/proc/add_abilities_to_panel()
|
|
for(var/obj/effect/proc_holder/alien/A in abilities)
|
|
statpanel("[A.panel]",A.plasma_cost > 0?"([A.plasma_cost])":"",A)
|
|
|
|
/mob/living/carbon/Stat()
|
|
..()
|
|
if(statpanel("Status"))
|
|
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
|
|
if(vessel)
|
|
stat(null, "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]")
|
|
if(locate(/obj/item/device/assembly/health) in src)
|
|
stat(null, "Health: [health]")
|
|
|
|
add_abilities_to_panel()
|
|
|
|
/mob/living/carbon/attack_ui(slot)
|
|
if(!has_hand_for_held_index(active_hand_index))
|
|
return 0
|
|
return ..()
|
|
|
|
/mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1, var/toxic = 0)
|
|
if(dna && dna.species && NOHUNGER in dna.species.species_traits)
|
|
return 1
|
|
|
|
if(nutrition < 100 && !blood)
|
|
if(message)
|
|
visible_message("<span class='warning'>[src] dry heaves!</span>", \
|
|
"<span class='userdanger'>You try to throw up, but there's nothing in your stomach!</span>")
|
|
if(stun)
|
|
Weaken(10)
|
|
return 1
|
|
|
|
if(is_mouth_covered()) //make this add a blood/vomit overlay later it'll be hilarious
|
|
if(message)
|
|
visible_message("<span class='danger'>[src] throws up all over themself!</span>", \
|
|
"<span class='userdanger'>You throw up all over yourself!</span>")
|
|
distance = 0
|
|
else
|
|
if(message)
|
|
visible_message("<span class='danger'>[src] throws up!</span>", "<span class='userdanger'>You throw up!</span>")
|
|
|
|
if(stun)
|
|
Stun(4)
|
|
|
|
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
|
|
var/turf/T = get_turf(src)
|
|
for(var/i=0 to distance)
|
|
if(blood)
|
|
if(T)
|
|
add_splatter_floor(T)
|
|
if(stun)
|
|
adjustBruteLoss(3)
|
|
else
|
|
if(T)
|
|
T.add_vomit_floor(src, 0)//toxic barf looks different
|
|
nutrition -= lost_nutrition
|
|
adjustToxLoss(-3)
|
|
T = get_step(T, dir)
|
|
if (is_blocked_turf(T))
|
|
break
|
|
return 1
|
|
|
|
|
|
/mob/living/carbon/fully_replace_character_name(oldname,newname)
|
|
..()
|
|
if(dna)
|
|
dna.real_name = real_name
|
|
|
|
//Updates the mob's health from bodyparts and mob damage variables
|
|
/mob/living/carbon/updatehealth()
|
|
if(status_flags & GODMODE)
|
|
return
|
|
var/total_burn = 0
|
|
var/total_brute = 0
|
|
for(var/X in bodyparts) //hardcoded to streamline things a bit
|
|
var/obj/item/bodypart/BP = X
|
|
total_brute += BP.brute_dam
|
|
total_burn += BP.burn_dam
|
|
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
|
|
update_stat()
|
|
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD )
|
|
become_husk()
|
|
med_hud_set_health()
|
|
|
|
/mob/living/carbon/update_sight()
|
|
if(!client)
|
|
return
|
|
if(stat == DEAD)
|
|
sight = (SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
|
see_in_dark = 8
|
|
see_invisible = SEE_INVISIBLE_OBSERVER
|
|
return
|
|
|
|
sight = initial(sight)
|
|
var/obj/item/organ/eyes/E = getorganslot("eye_sight")
|
|
if(!E)
|
|
update_tint()
|
|
else
|
|
see_invisible = E.see_invisible
|
|
see_in_dark = E.see_in_dark
|
|
sight |= E.sight_flags
|
|
|
|
if(client.eye != src)
|
|
var/atom/A = client.eye
|
|
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
|
|
return
|
|
|
|
if(glasses)
|
|
var/obj/item/clothing/glasses/G = glasses
|
|
sight |= G.vision_flags
|
|
see_in_dark = max(G.darkness_view, see_in_dark)
|
|
if(G.invis_override)
|
|
see_invisible = G.invis_override
|
|
else
|
|
see_invisible = min(G.invis_view, see_invisible)
|
|
if(dna)
|
|
for(var/X in dna.mutations)
|
|
var/datum/mutation/M = X
|
|
if(M.name == XRAY)
|
|
sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
|
see_in_dark = max(see_in_dark, 8)
|
|
|
|
if(see_override)
|
|
see_invisible = see_override
|
|
|
|
|
|
//to recalculate and update the mob's total tint from tinted equipment it's wearing.
|
|
/mob/living/carbon/proc/update_tint()
|
|
if(!tinted_weldhelh)
|
|
return
|
|
tinttotal = get_total_tint()
|
|
if(tinttotal >= TINT_BLIND)
|
|
overlay_fullscreen("tint", /obj/screen/fullscreen/blind)
|
|
else if(tinttotal >= TINT_DARKENED)
|
|
overlay_fullscreen("tint", /obj/screen/fullscreen/impaired, 2)
|
|
else
|
|
clear_fullscreen("tint", 0)
|
|
|
|
/mob/living/carbon/proc/get_total_tint()
|
|
. = 0
|
|
if(istype(head, /obj/item/clothing/head))
|
|
var/obj/item/clothing/head/HT = head
|
|
. += HT.tint
|
|
if(wear_mask)
|
|
. += wear_mask.tint
|
|
|
|
var/obj/item/organ/eyes/E = getorganslot("eye_sight")
|
|
if(E)
|
|
. += E.tint
|
|
|
|
else
|
|
. += INFINITY
|
|
|
|
//this handles hud updates
|
|
/mob/living/carbon/update_damage_hud()
|
|
|
|
if(!client)
|
|
return
|
|
|
|
if(stat == UNCONSCIOUS && health <= HEALTH_THRESHOLD_CRIT)
|
|
var/severity = 0
|
|
switch(health)
|
|
if(-20 to -10) severity = 1
|
|
if(-30 to -20) severity = 2
|
|
if(-40 to -30) severity = 3
|
|
if(-50 to -40) severity = 4
|
|
if(-60 to -50) severity = 5
|
|
if(-70 to -60) severity = 6
|
|
if(-80 to -70) severity = 7
|
|
if(-90 to -80) severity = 8
|
|
if(-95 to -90) severity = 9
|
|
if(-INFINITY to -95) severity = 10
|
|
overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity)
|
|
else
|
|
clear_fullscreen("crit")
|
|
if(oxyloss)
|
|
var/severity = 0
|
|
switch(oxyloss)
|
|
if(10 to 20) severity = 1
|
|
if(20 to 25) severity = 2
|
|
if(25 to 30) severity = 3
|
|
if(30 to 35) severity = 4
|
|
if(35 to 40) severity = 5
|
|
if(40 to 45) severity = 6
|
|
if(45 to INFINITY) severity = 7
|
|
overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity)
|
|
else
|
|
clear_fullscreen("oxy")
|
|
|
|
//Fire and Brute damage overlay (BSSR)
|
|
var/hurtdamage = getBruteLoss() + getFireLoss() + damageoverlaytemp
|
|
if(hurtdamage)
|
|
var/severity = 0
|
|
switch(hurtdamage)
|
|
if(5 to 15) severity = 1
|
|
if(15 to 30) severity = 2
|
|
if(30 to 45) severity = 3
|
|
if(45 to 70) severity = 4
|
|
if(70 to 85) severity = 5
|
|
if(85 to INFINITY) severity = 6
|
|
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
|
|
else
|
|
clear_fullscreen("brute")
|
|
|
|
/mob/living/carbon/update_health_hud(shown_health_amount)
|
|
if(!client || !hud_used)
|
|
return
|
|
if(hud_used.healths)
|
|
if(stat != DEAD)
|
|
. = 1
|
|
if(!shown_health_amount)
|
|
shown_health_amount = health
|
|
if(shown_health_amount >= maxHealth)
|
|
hud_used.healths.icon_state = "health0"
|
|
else if(shown_health_amount > maxHealth*0.8)
|
|
hud_used.healths.icon_state = "health1"
|
|
else if(shown_health_amount > maxHealth*0.6)
|
|
hud_used.healths.icon_state = "health2"
|
|
else if(shown_health_amount > maxHealth*0.4)
|
|
hud_used.healths.icon_state = "health3"
|
|
else if(shown_health_amount > maxHealth*0.2)
|
|
hud_used.healths.icon_state = "health4"
|
|
else if(shown_health_amount > 0)
|
|
hud_used.healths.icon_state = "health5"
|
|
else
|
|
hud_used.healths.icon_state = "health6"
|
|
else
|
|
hud_used.healths.icon_state = "health7"
|
|
|
|
/mob/living/carbon/proc/update_internals_hud_icon(internal_state = 0)
|
|
if(hud_used && hud_used.internals)
|
|
hud_used.internals.icon_state = "internal[internal_state]"
|
|
|
|
/mob/living/carbon/update_stat()
|
|
if(status_flags & GODMODE)
|
|
return
|
|
if(stat != DEAD)
|
|
if(health<= HEALTH_THRESHOLD_DEAD || !getorgan(/obj/item/organ/brain))
|
|
death()
|
|
return
|
|
if(paralysis || sleeping || getOxyLoss() > 50 || (status_flags & FAKEDEATH) || health <= HEALTH_THRESHOLD_CRIT)
|
|
if(stat == CONSCIOUS)
|
|
stat = UNCONSCIOUS
|
|
blind_eyes(1)
|
|
update_canmove()
|
|
else
|
|
if(stat == UNCONSCIOUS)
|
|
stat = CONSCIOUS
|
|
resting = 0
|
|
adjust_blindness(-1)
|
|
update_canmove()
|
|
update_damage_hud()
|
|
update_health_hud()
|
|
med_hud_set_status()
|
|
|
|
//called when we get cuffed/uncuffed
|
|
/mob/living/carbon/proc/update_handcuffed()
|
|
if(handcuffed)
|
|
drop_all_held_items()
|
|
stop_pulling()
|
|
throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed)
|
|
else
|
|
clear_alert("handcuffed")
|
|
update_action_buttons_icon() //some of our action buttons might be unusable when we're handcuffed.
|
|
update_inv_handcuffed()
|
|
update_hud_handcuffed()
|
|
|
|
/mob/living/carbon/fully_heal(admin_revive = 0)
|
|
if(reagents)
|
|
reagents.clear_reagents()
|
|
var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain)
|
|
if(B)
|
|
B.damaged_brain = 0
|
|
for(var/datum/disease/D in viruses)
|
|
if (D.severity != NONTHREAT)
|
|
D.cure(0)
|
|
if(admin_revive)
|
|
regenerate_limbs()
|
|
regenerate_organs()
|
|
handcuffed = initial(handcuffed)
|
|
for(var/obj/item/weapon/restraints/R in contents) //actually remove cuffs from inventory
|
|
qdel(R)
|
|
update_handcuffed()
|
|
if(reagents)
|
|
reagents.addiction_list = list()
|
|
..()
|
|
|
|
/mob/living/carbon/can_be_revived()
|
|
. = ..()
|
|
if(!getorgan(/obj/item/organ/brain))
|
|
return 0
|
|
|
|
/mob/living/carbon/harvest(mob/living/user)
|
|
if(QDELETED(src))
|
|
return
|
|
var/organs_amt = 0
|
|
for(var/X in internal_organs)
|
|
var/obj/item/organ/O = X
|
|
if(prob(50))
|
|
organs_amt++
|
|
O.Remove(src)
|
|
O.loc = get_turf(src)
|
|
if(organs_amt)
|
|
user << "<span class='notice'>You retrieve some of [src]\'s internal organs!</span>"
|
|
|
|
..()
|
|
|
|
/mob/living/carbon/ExtinguishMob()
|
|
for(var/X in get_equipped_items())
|
|
var/obj/item/I = X
|
|
I.acid_level = 0 //washes off the acid on our clothes
|
|
I.extinguish() //extinguishes our clothes
|
|
..()
|
|
|
|
/mob/living/carbon/fakefire(var/fire_icon = "Generic_mob_burning")
|
|
var/image/new_fire_overlay = image("icon"='icons/mob/OnFire.dmi', "icon_state"= fire_icon, "layer"=-FIRE_LAYER)
|
|
new_fire_overlay.appearance_flags = RESET_COLOR
|
|
overlays_standing[FIRE_LAYER] = new_fire_overlay
|
|
apply_overlay(FIRE_LAYER)
|
|
|
|
/mob/living/carbon/fakefireextinguish()
|
|
remove_overlay(FIRE_LAYER)
|
|
|
|
|
|
/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130)
|
|
C.visible_message("<span class='danger'>[src] is attempting to devour [C]!</span>", \
|
|
"<span class='userdanger'>[src] is attempting to devour you!</span>")
|
|
if(!do_mob(src, C, devour_time))
|
|
return
|
|
if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == INTENT_GRAB)
|
|
C.visible_message("<span class='danger'>[src] devours [C]!</span>", \
|
|
"<span class='userdanger'>[src] devours you!</span>")
|
|
C.forceMove(src)
|
|
stomach_contents.Add(C)
|
|
add_logs(src, C, "devoured")
|
|
|
|
/mob/living/carbon/proc/create_bodyparts()
|
|
var/l_arm_index_next = -1
|
|
var/r_arm_index_next = 0
|
|
for(var/X in bodyparts)
|
|
var/obj/item/bodypart/O = new X()
|
|
O.owner = src
|
|
bodyparts.Remove(X)
|
|
bodyparts.Add(O)
|
|
if(O.body_part == ARM_LEFT)
|
|
l_arm_index_next += 2
|
|
O.held_index = l_arm_index_next //1, 3, 5, 7...
|
|
hand_bodyparts += O
|
|
else if(O.body_part == ARM_RIGHT)
|
|
r_arm_index_next += 2
|
|
O.held_index = r_arm_index_next //2, 4, 6, 8...
|
|
hand_bodyparts += O
|
|
|
|
|
|
/mob/living/carbon/proc/create_internal_organs()
|
|
for(var/X in internal_organs)
|
|
var/obj/item/organ/I = X
|
|
I.Insert(src)
|
|
|
|
/mob/living/carbon/vv_get_dropdown()
|
|
. = ..()
|
|
. += "---"
|
|
.["Make AI"] = "?_src_=vars;makeai=\ref[src]"
|
|
.["Modify bodypart"] = "?_src_=vars;editbodypart=\ref[src]"
|
|
.["Modify organs"] = "?_src_=vars;editorgans=\ref[src]"
|