mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-24 20:47:10 +01:00
854 lines
23 KiB
Plaintext
854 lines
23 KiB
Plaintext
|
|
/mob/living/Destroy()
|
|
if(ranged_ability)
|
|
ranged_ability.remove_ranged_ability(src)
|
|
return ..()
|
|
|
|
/mob/living/ghostize(can_reenter_corpse = 1)
|
|
var/prev_client = client
|
|
. = ..()
|
|
if(.)
|
|
if(ranged_ability && prev_client)
|
|
ranged_ability.remove_mousepointer(prev_client)
|
|
|
|
/mob/living/proc/OpenCraftingMenu()
|
|
return
|
|
|
|
/mob/living/Stat()
|
|
. = ..()
|
|
if(. && get_rig_stats)
|
|
var/obj/item/weapon/rig/rig = get_rig()
|
|
if(rig)
|
|
SetupStat(rig)
|
|
|
|
/mob/living/proc/can_track(mob/living/user)
|
|
//basic fast checks go first. When overriding this proc, I recommend calling ..() at the end.
|
|
var/turf/T = get_turf(src)
|
|
if(!T)
|
|
return 0
|
|
if(!is_level_reachable(T.z))
|
|
return 0
|
|
if(user != null && src == user)
|
|
return 0
|
|
if(invisibility || alpha == 0)//cloaked
|
|
return 0
|
|
if(digitalcamo)
|
|
return 0
|
|
|
|
// Now, are they viewable by a camera? (This is last because it's the most intensive check)
|
|
if(!near_camera(src))
|
|
return 0
|
|
|
|
return 1
|
|
|
|
//mob verbs are a lot faster than object verbs
|
|
//for more info on why this is not atom/pull, see examinate() in mob.dm
|
|
/mob/living/verb/pulled(atom/movable/AM as mob|obj in oview(1))
|
|
set name = "Pull"
|
|
set category = "Object"
|
|
|
|
if(AM.Adjacent(src))
|
|
start_pulling(AM)
|
|
return
|
|
|
|
//same as above
|
|
/mob/living/pointed(atom/A as mob|obj|turf in view())
|
|
if(incapacitated())
|
|
return 0
|
|
if(status_flags & FAKEDEATH)
|
|
return 0
|
|
if(!..())
|
|
return 0
|
|
visible_message("<b>[src]</b> points to [A]")
|
|
return 1
|
|
|
|
/mob/living/verb/succumb()
|
|
set hidden = 1
|
|
if(InCritical())
|
|
attack_log += "[src] has ["succumbed to death"] with [round(health, 0.1)] points of health!"
|
|
adjustOxyLoss(health - config.health_threshold_dead)
|
|
updatehealth()
|
|
// super check for weird mobs, including ones that adjust hp
|
|
// we don't want to go overboard and gib them, though
|
|
for(var/i = 1 to 5)
|
|
if(health < config.health_threshold_dead)
|
|
break
|
|
take_overall_damage(max(5, health - config.health_threshold_dead), 0)
|
|
updatehealth()
|
|
to_chat(src, "<span class='notice'>You have given up life and succumbed to death.</span>")
|
|
|
|
/mob/living/proc/InCritical()
|
|
return (health < 0 && health > -95.0 && stat == UNCONSCIOUS)
|
|
|
|
/mob/living/ex_act(severity)
|
|
..()
|
|
flash_eyes()
|
|
|
|
/mob/living/proc/updatehealth()
|
|
if(status_flags & GODMODE)
|
|
health = maxHealth
|
|
stat = CONSCIOUS
|
|
return
|
|
health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss()
|
|
|
|
|
|
//This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually
|
|
//affects them once clothing is factored in. ~Errorage
|
|
/mob/living/proc/calculate_affecting_pressure(var/pressure)
|
|
return 0
|
|
|
|
/mob/living/proc/adjustBodyTemp(actual, desired, incrementboost)
|
|
var/temperature = actual
|
|
var/difference = abs(actual-desired) //get difference
|
|
var/increments = difference/10 //find how many increments apart they are
|
|
var/change = increments*incrementboost // Get the amount to change by (x per increment)
|
|
|
|
// Too cold
|
|
if(actual < desired)
|
|
temperature += change
|
|
if(actual > desired)
|
|
temperature = desired
|
|
// Too hot
|
|
if(actual > desired)
|
|
temperature -= change
|
|
if(actual < desired)
|
|
temperature = desired
|
|
// if(istype(src, /mob/living/carbon/human))
|
|
// to_chat(world, "[src] ~ [bodytemperature] ~ [temperature]")
|
|
return temperature
|
|
|
|
|
|
// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching.
|
|
// Stop! ... Hammertime! ~Carn
|
|
// I touched them without asking... I'm soooo edgy ~Erro (added nodamage checks)
|
|
// no ~Tigerkitty
|
|
|
|
/mob/living/proc/getBruteLoss()
|
|
return bruteloss
|
|
|
|
/mob/living/proc/adjustBruteLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
bruteloss = min(max(bruteloss + amount, 0),(maxHealth*2))
|
|
|
|
/mob/living/proc/getOxyLoss()
|
|
return oxyloss
|
|
|
|
/mob/living/proc/adjustOxyLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
oxyloss = min(max(oxyloss + amount, 0),(maxHealth*2))
|
|
|
|
/mob/living/proc/setOxyLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
oxyloss = amount
|
|
|
|
/mob/living/proc/getToxLoss()
|
|
return toxloss
|
|
|
|
/mob/living/proc/adjustToxLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
toxloss = min(max(toxloss + amount, 0),(maxHealth*2))
|
|
|
|
/mob/living/proc/setToxLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
toxloss = amount
|
|
|
|
/mob/living/proc/getFireLoss()
|
|
return fireloss
|
|
|
|
/mob/living/proc/adjustFireLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
fireloss = min(max(fireloss + amount, 0),(maxHealth*2))
|
|
|
|
/mob/living/proc/getCloneLoss()
|
|
return cloneloss
|
|
|
|
/mob/living/proc/adjustCloneLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
cloneloss = min(max(cloneloss + amount, 0),(maxHealth*2))
|
|
|
|
/mob/living/proc/setCloneLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
cloneloss = amount
|
|
|
|
/mob/living/proc/getBrainLoss()
|
|
return brainloss
|
|
|
|
/mob/living/proc/adjustBrainLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
brainloss = min(max(brainloss + amount, 0),(maxHealth*2))
|
|
|
|
/mob/living/proc/setBrainLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
brainloss = amount
|
|
|
|
/mob/living/proc/getStaminaLoss()
|
|
return staminaloss
|
|
|
|
/mob/living/proc/adjustStaminaLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0
|
|
staminaloss = min(max(staminaloss + amount, 0),(maxHealth*2))
|
|
|
|
/mob/living/proc/setStaminaLoss(var/amount)
|
|
if(status_flags & GODMODE) return 0
|
|
staminaloss = amount
|
|
|
|
/mob/living/proc/getMaxHealth()
|
|
return maxHealth
|
|
|
|
/mob/living/proc/setMaxHealth(var/newMaxHealth)
|
|
maxHealth = newMaxHealth
|
|
|
|
// ++++ROCKDTBEN++++ MOB PROCS //END
|
|
|
|
|
|
/mob/proc/get_contents()
|
|
|
|
|
|
//Recursive function to find everything a mob is holding.
|
|
/mob/living/get_contents(var/obj/item/weapon/storage/Storage = null)
|
|
var/list/L = list()
|
|
|
|
if(Storage) //If it called itself
|
|
L += Storage.return_inv()
|
|
|
|
//Leave this commented out, it will cause storage items to exponentially add duplicate to the list
|
|
//for(var/obj/item/weapon/storage/S in Storage.return_inv()) //Check for storage items
|
|
// L += get_contents(S)
|
|
|
|
for(var/obj/item/weapon/gift/G in Storage.return_inv()) //Check for gift-wrapped items
|
|
L += G.gift
|
|
if(istype(G.gift, /obj/item/weapon/storage))
|
|
L += get_contents(G.gift)
|
|
|
|
for(var/obj/item/smallDelivery/D in Storage.return_inv()) //Check for package wrapped items
|
|
L += D.wrapped
|
|
if(istype(D.wrapped, /obj/item/weapon/storage)) //this should never happen
|
|
L += get_contents(D.wrapped)
|
|
return L
|
|
|
|
else
|
|
|
|
L += contents
|
|
for(var/obj/item/weapon/storage/S in contents) //Check for storage items
|
|
L += get_contents(S)
|
|
for(var/obj/item/clothing/suit/storage/S in contents)//Check for labcoats and jackets
|
|
L += get_contents(S)
|
|
for(var/obj/item/clothing/accessory/storage/S in contents)//Check for holsters
|
|
L += get_contents(S)
|
|
for(var/obj/item/weapon/implant/storage/I in contents) //Check for storage implants.
|
|
L += I.get_contents()
|
|
for(var/obj/item/weapon/gift/G in contents) //Check for gift-wrapped items
|
|
L += G.gift
|
|
if(istype(G.gift, /obj/item/weapon/storage))
|
|
L += get_contents(G.gift)
|
|
|
|
for(var/obj/item/smallDelivery/D in contents) //Check for package wrapped items
|
|
L += D.wrapped
|
|
if(istype(D.wrapped, /obj/item/weapon/storage)) //this should never happen
|
|
L += get_contents(D.wrapped)
|
|
for(var/obj/item/weapon/folder/F in contents)
|
|
L += F.contents //Folders can't store any storage items.
|
|
|
|
return L
|
|
|
|
/mob/living/proc/check_contents_for(A)
|
|
var/list/L = get_contents()
|
|
|
|
for(var/obj/B in L)
|
|
if(B.type == A)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
/mob/living/proc/can_inject()
|
|
return 1
|
|
|
|
/mob/living/proc/get_organ_target()
|
|
var/mob/shooter = src
|
|
var/t = shooter:zone_sel.selecting
|
|
if((t in list( "eyes", "mouth" )))
|
|
t = "head"
|
|
var/obj/item/organ/external/def_zone = ran_zone(t)
|
|
return def_zone
|
|
|
|
// heal ONE external organ, organ gets randomly selected from damaged ones.
|
|
/mob/living/proc/heal_organ_damage(var/brute, var/burn)
|
|
adjustBruteLoss(-brute)
|
|
adjustFireLoss(-burn)
|
|
updatehealth()
|
|
|
|
// damage ONE external organ, organ gets randomly selected from damaged ones.
|
|
/mob/living/proc/take_organ_damage(var/brute, var/burn)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
adjustBruteLoss(brute)
|
|
adjustFireLoss(burn)
|
|
updatehealth()
|
|
|
|
// heal MANY external organs, in random order
|
|
/mob/living/proc/heal_overall_damage(var/brute, var/burn)
|
|
adjustBruteLoss(-brute)
|
|
adjustFireLoss(-burn)
|
|
updatehealth()
|
|
|
|
// damage MANY external organs, in random order
|
|
/mob/living/proc/take_overall_damage(var/brute, var/burn, var/used_weapon = null)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
adjustBruteLoss(brute)
|
|
adjustFireLoss(burn)
|
|
updatehealth()
|
|
|
|
/mob/living/proc/has_organic_damage()
|
|
return (maxHealth - health)
|
|
|
|
|
|
/mob/living/proc/restore_all_organs()
|
|
return
|
|
|
|
/mob/living/proc/revive()
|
|
rejuvenate()
|
|
if(iscarbon(src))
|
|
var/mob/living/carbon/C = src
|
|
|
|
if(C.handcuffed && !initial(C.handcuffed))
|
|
C.unEquip(C.handcuffed)
|
|
C.handcuffed = initial(C.handcuffed)
|
|
C.update_handcuffed()
|
|
|
|
if(C.legcuffed && !initial(C.legcuffed))
|
|
C.unEquip(C.legcuffed)
|
|
C.legcuffed = initial(C.legcuffed)
|
|
C.update_inv_legcuffed()
|
|
|
|
if(C.reagents)
|
|
for(var/datum/reagent/R in C.reagents.reagent_list)
|
|
C.reagents.clear_reagents()
|
|
C.reagents.addiction_list.Cut()
|
|
|
|
/mob/living/proc/rejuvenate()
|
|
var/mob/living/carbon/human/human_mob = null //Get this declared for use later.
|
|
|
|
// shut down various types of badness
|
|
setToxLoss(0)
|
|
setOxyLoss(0)
|
|
setCloneLoss(0)
|
|
setBrainLoss(0)
|
|
setStaminaLoss(0)
|
|
SetSleeping(0)
|
|
SetParalysis(0, 1, 1)
|
|
SetStunned(0, 1, 1)
|
|
SetWeakened(0, 1, 1)
|
|
SetSlowed(0)
|
|
SetLoseBreath(0)
|
|
SetDizzy(0)
|
|
SetJitter(0)
|
|
SetConfused(0)
|
|
SetDrowsy(0)
|
|
radiation = 0
|
|
SetDruggy(0)
|
|
SetHallucinate(0)
|
|
blinded = 0
|
|
nutrition = NUTRITION_LEVEL_FED + 50
|
|
bodytemperature = 310
|
|
CureBlind()
|
|
CureNearsighted()
|
|
CureMute()
|
|
CureDeaf()
|
|
CureTourettes()
|
|
CureEpilepsy()
|
|
CureCoughing()
|
|
CureNervous()
|
|
SetEyeBlind(0)
|
|
SetEyeBlurry(0)
|
|
SetEarDamage(0)
|
|
SetEarDeaf(0)
|
|
heal_overall_damage(1000, 1000)
|
|
ExtinguishMob()
|
|
fire_stacks = 0
|
|
on_fire = 0
|
|
suiciding = 0
|
|
if(buckled) //Unbuckle the mob and clear the alerts.
|
|
buckled.buckled_mob = null
|
|
buckled = null
|
|
anchored = initial(anchored)
|
|
update_canmove()
|
|
clear_alert("buckled")
|
|
post_buckle_mob(src)
|
|
|
|
if(iscarbon(src))
|
|
var/mob/living/carbon/C = src
|
|
C.handcuffed = initial(C.handcuffed)
|
|
C.heart_attack = 0
|
|
|
|
for(var/datum/disease/D in C.viruses)
|
|
D.cure(0)
|
|
|
|
// restore all of the human's blood and reset their shock stage
|
|
if(ishuman(src))
|
|
human_mob = src
|
|
human_mob.restore_blood()
|
|
human_mob.shock_stage = 0
|
|
human_mob.decaylevel = 0
|
|
|
|
restore_all_organs()
|
|
surgeries.Cut() //End all surgeries.
|
|
if(stat == DEAD)
|
|
dead_mob_list -= src
|
|
living_mob_list += src
|
|
timeofdeath = 0
|
|
|
|
stat = CONSCIOUS
|
|
update_fire()
|
|
regenerate_icons()
|
|
if(human_mob)
|
|
human_mob.update_eyes()
|
|
human_mob.update_dna()
|
|
return
|
|
|
|
/mob/living/proc/UpdateDamageIcon()
|
|
return
|
|
|
|
|
|
/mob/living/proc/Examine_OOC()
|
|
set name = "Examine Meta-Info (OOC)"
|
|
set category = "OOC"
|
|
set src in view()
|
|
|
|
if(config.allow_Metadata)
|
|
if(client)
|
|
to_chat(usr, "[src]'s Metainfo:<br>[client.prefs.metadata]")
|
|
else
|
|
to_chat(usr, "[src] does not have any stored infomation!")
|
|
else
|
|
to_chat(usr, "OOC Metadata is not supported by this server!")
|
|
|
|
return
|
|
|
|
/mob/living/Move(atom/newloc, direct)
|
|
if(buckled && buckled.loc != newloc) //not updating position
|
|
if(!buckled.anchored)
|
|
return buckled.Move(newloc, direct)
|
|
else
|
|
return 0
|
|
|
|
if(restrained())
|
|
stop_pulling()
|
|
|
|
|
|
var/t7 = 1
|
|
if(restrained())
|
|
for(var/mob/living/M in range(src, 1))
|
|
if((M.pulling == src && M.stat == 0 && !( M.restrained() )))
|
|
t7 = null
|
|
if(t7 && pulling && (get_dist(src, pulling) <= 1 || pulling.loc == loc))
|
|
var/turf/T = loc
|
|
. = ..()
|
|
|
|
if(pulling && pulling.loc)
|
|
if(!( isturf(pulling.loc) ))
|
|
stop_pulling()
|
|
return
|
|
else
|
|
if(Debug)
|
|
diary <<"pulling disappeared? at [__LINE__] in mob.dm - pulling = [pulling]"
|
|
diary <<"REPORT THIS"
|
|
|
|
/////
|
|
if(pulling && pulling.anchored)
|
|
stop_pulling()
|
|
return
|
|
|
|
if(!restrained())
|
|
var/diag = get_dir(src, pulling)
|
|
if((diag - 1) & diag)
|
|
else
|
|
diag = null
|
|
if((get_dist(src, pulling) > 1 || diag))
|
|
if(isliving(pulling))
|
|
var/mob/living/M = pulling
|
|
var/ok = 1
|
|
if(locate(/obj/item/weapon/grab, M.grabbed_by))
|
|
if(prob(75))
|
|
var/obj/item/weapon/grab/G = pick(M.grabbed_by)
|
|
if(istype(G, /obj/item/weapon/grab))
|
|
for(var/mob/O in viewers(M, null))
|
|
O.show_message(text("\red [] has been pulled from []'s grip by []", G.affecting, G.assailant, src), 1)
|
|
//G = null
|
|
qdel(G)
|
|
else
|
|
ok = 0
|
|
if(locate(/obj/item/weapon/grab, M.grabbed_by.len))
|
|
ok = 0
|
|
if(ok)
|
|
var/atom/movable/t = M.pulling
|
|
M.stop_pulling()
|
|
|
|
if(M.lying && (prob(M.getBruteLoss() / 6)))
|
|
var/turf/location = M.loc
|
|
if(istype(location, /turf/simulated))
|
|
location.add_blood(M)
|
|
pulling.Move(T, get_dir(pulling, T))
|
|
if(M)
|
|
M.start_pulling(t)
|
|
else
|
|
if(pulling)
|
|
pulling.Move(T, get_dir(pulling, T))
|
|
else
|
|
stop_pulling()
|
|
. = ..()
|
|
|
|
if(s_active && !( s_active in contents ) && get_turf(s_active) != get_turf(src)) //check !( s_active in contents ) first so we hopefully don't have to call get_turf() so much.
|
|
s_active.close(src)
|
|
|
|
if(.) // did we actually move?
|
|
handle_footstep(loc)
|
|
step_count++
|
|
|
|
if(update_slimes)
|
|
for(var/mob/living/carbon/slime/M in view(1,src))
|
|
M.UpdateFeed(src)
|
|
|
|
/mob/living/proc/handle_footstep(turf/T)
|
|
if(istype(T))
|
|
return 1
|
|
return 0
|
|
|
|
/*//////////////////////
|
|
START RESIST PROCS
|
|
*///////////////////////
|
|
|
|
/mob/living/verb/resist()
|
|
set name = "Resist"
|
|
set category = "IC"
|
|
|
|
if(!isliving(src) || next_move > world.time || stat || weakened || stunned || paralysis)
|
|
return
|
|
changeNext_move(CLICK_CD_RESIST)
|
|
|
|
if(!restrained())
|
|
if(resist_grab())
|
|
return
|
|
|
|
//unbuckling yourself
|
|
if(buckled && last_special <= world.time)
|
|
resist_buckle()
|
|
|
|
//Breaking out of a container (Locker, sleeper, cryo...)
|
|
else if(isobj(loc))
|
|
var/obj/C = loc
|
|
C.container_resist(src)
|
|
|
|
else if(canmove)
|
|
if(on_fire)
|
|
resist_fire() //stop, drop, and roll
|
|
else if(last_special <= world.time)
|
|
resist_restraints() //trying to remove cuffs.
|
|
|
|
/*////////////////////
|
|
RESIST SUBPROCS
|
|
*/////////////////////
|
|
/mob/living/proc/resist_grab()
|
|
var/resisting = 0
|
|
for(var/obj/O in requests)
|
|
qdel(O)
|
|
resisting++
|
|
for(var/X in grabbed_by)
|
|
var/obj/item/weapon/grab/G = X
|
|
resisting++
|
|
switch(G.state)
|
|
if(GRAB_PASSIVE)
|
|
qdel(G)
|
|
|
|
if(GRAB_AGGRESSIVE)
|
|
if(prob(60))
|
|
visible_message("<span class='danger'>[src] has broken free of [G.assailant]'s grip!</span>")
|
|
qdel(G)
|
|
|
|
if(GRAB_NECK)
|
|
if(prob(5))
|
|
visible_message("<span class='danger'>[src] has broken free of [G.assailant]'s headlock!</span>")
|
|
qdel(G)
|
|
|
|
if(resisting)
|
|
visible_message("<span class='danger'>[src] resists!</span>")
|
|
return 1
|
|
|
|
/mob/living/proc/resist_buckle()
|
|
spawn(0)
|
|
resist_muzzle()
|
|
buckled.user_unbuckle_mob(src,src)
|
|
|
|
/mob/living/proc/resist_muzzle()
|
|
return
|
|
|
|
/mob/living/proc/resist_fire()
|
|
return
|
|
|
|
/mob/living/proc/resist_restraints()
|
|
spawn(0)
|
|
resist_muzzle()
|
|
return
|
|
|
|
/*//////////////////////
|
|
END RESIST PROCS
|
|
*///////////////////////
|
|
|
|
/mob/living/proc/Exhaust()
|
|
to_chat(src, "<span class='notice'>You're too exhausted to keep going...</span>")
|
|
Weaken(5)
|
|
|
|
/mob/living/proc/get_visible_name()
|
|
return name
|
|
|
|
/mob/living/update_gravity(has_gravity)
|
|
if(!ticker)
|
|
return
|
|
if(has_gravity)
|
|
clear_alert("weightless")
|
|
else
|
|
throw_alert("weightless", /obj/screen/alert/weightless)
|
|
float(!has_gravity)
|
|
|
|
/mob/living/proc/float(on)
|
|
if(throwing)
|
|
return
|
|
var/fixed = 0
|
|
if(anchored || (buckled && buckled.anchored))
|
|
fixed = 1
|
|
if(on && !floating && !fixed)
|
|
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
|
|
floating = 1
|
|
else if(((!on || fixed) && floating))
|
|
var/final_pixel_y = get_standard_pixel_y_offset(lying)
|
|
animate(src, pixel_y = final_pixel_y, time = 10)
|
|
floating = 0
|
|
|
|
/mob/living/proc/can_use_vents()
|
|
return "You can't fit into that vent."
|
|
|
|
//called when the mob receives a bright flash
|
|
/mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
|
|
if(check_eye_prot() < intensity && (override_blindness_check || !(disabilities & BLIND)))
|
|
overlay_fullscreen("flash", type)
|
|
addtimer(src, "clear_fullscreen", 25, FALSE, "flash", 25)
|
|
return 1
|
|
|
|
/mob/living/proc/check_eye_prot()
|
|
return 0
|
|
|
|
/mob/living/proc/check_ear_prot()
|
|
|
|
// The src mob is trying to strip an item from someone
|
|
// Override if a certain type of mob should be behave differently when stripping items (can't, for example)
|
|
/mob/living/stripPanelUnequip(obj/item/what, mob/who, where, var/silent = 0)
|
|
if(what.flags & NODROP)
|
|
to_chat(src, "<span class='warning'>You can't remove \the [what.name], it appears to be stuck!</span>")
|
|
return
|
|
if(!silent)
|
|
who.visible_message("<span class='danger'>[src] tries to remove [who]'s [what.name].</span>", \
|
|
"<span class='userdanger'>[src] tries to remove [who]'s [what.name].</span>")
|
|
what.add_fingerprint(src)
|
|
if(do_mob(src, who, what.strip_delay))
|
|
if(what && what == who.get_item_by_slot(where) && Adjacent(who))
|
|
who.unEquip(what)
|
|
if(silent)
|
|
put_in_hands(what)
|
|
add_logs(src, who, "stripped", addition="of [what]", print_attack_log = isLivingSSD(who))
|
|
|
|
// The src mob is trying to place an item on someone
|
|
// Override if a certain mob should be behave differently when placing items (can't, for example)
|
|
/mob/living/stripPanelEquip(obj/item/what, mob/who, where, var/silent = 0)
|
|
what = get_active_hand()
|
|
if(what && (what.flags & NODROP))
|
|
to_chat(src, "<span class='warning'>You can't put \the [what.name] on [who], it's stuck to your hand!</span>")
|
|
return
|
|
if(what)
|
|
if(!what.mob_can_equip(who, where, 1))
|
|
to_chat(src, "<span class='warning'>\The [what.name] doesn't fit in that place!</span>")
|
|
return
|
|
if(!silent)
|
|
visible_message("<span class='notice'>[src] tries to put [what] on [who].</span>")
|
|
if(do_mob(src, who, what.put_on_delay))
|
|
if(what && Adjacent(who))
|
|
unEquip(what)
|
|
who.equip_to_slot_if_possible(what, where, 0, 1)
|
|
add_logs(src, who, "equipped", what, print_attack_log = isLivingSSD(who))
|
|
|
|
|
|
/mob/living/singularity_act()
|
|
var/gain = 20
|
|
investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up!
|
|
gib()
|
|
return(gain)
|
|
|
|
/mob/living/singularity_pull(S)
|
|
step_towards(src,S)
|
|
|
|
/mob/living/narsie_act()
|
|
if(client)
|
|
makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, src, null, 1)
|
|
spawn_dust()
|
|
gib()
|
|
return
|
|
|
|
/atom/movable/proc/do_attack_animation(atom/A, end_pixel_y)
|
|
var/pixel_x_diff = 0
|
|
var/pixel_y_diff = 0
|
|
var/final_pixel_y = initial(pixel_y)
|
|
if(end_pixel_y)
|
|
final_pixel_y = end_pixel_y
|
|
|
|
var/direction = get_dir(src, A)
|
|
if(direction & NORTH)
|
|
pixel_y_diff = 8
|
|
else if(direction & SOUTH)
|
|
pixel_y_diff = -8
|
|
|
|
if(direction & EAST)
|
|
pixel_x_diff = 8
|
|
else if(direction & WEST)
|
|
pixel_x_diff = -8
|
|
|
|
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2)
|
|
animate(pixel_x = initial(pixel_x), pixel_y = final_pixel_y, time = 2)
|
|
|
|
|
|
/mob/living/do_attack_animation(atom/A)
|
|
var/final_pixel_y = get_standard_pixel_y_offset(lying)
|
|
..(A, final_pixel_y)
|
|
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
|
|
|
|
// What icon do we use for the attack?
|
|
var/image/I
|
|
if(hand && l_hand) // Attacked with item in left hand.
|
|
I = image(l_hand.icon, A, l_hand.icon_state, A.layer + 1)
|
|
else if(!hand && r_hand) // Attacked with item in right hand.
|
|
I = image(r_hand.icon, A, r_hand.icon_state, A.layer + 1)
|
|
else // Attacked with a fist?
|
|
return
|
|
|
|
// Who can see the attack?
|
|
var/list/viewing = list()
|
|
for(var/mob/M in viewers(A))
|
|
if(M.client && M.client.prefs.show_ghostitem_attack)
|
|
viewing |= M.client
|
|
flick_overlay(I, viewing, 5) // 5 ticks/half a second
|
|
|
|
// Scale the icon.
|
|
I.transform *= 0.75
|
|
// The icon should not rotate.
|
|
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
|
|
|
|
// Set the direction of the icon animation.
|
|
var/direction = get_dir(src, A)
|
|
if(direction & NORTH)
|
|
I.pixel_y = -16
|
|
else if(direction & SOUTH)
|
|
I.pixel_y = 16
|
|
|
|
if(direction & EAST)
|
|
I.pixel_x = -16
|
|
else if(direction & WEST)
|
|
I.pixel_x = 16
|
|
|
|
if(!direction) // Attacked self?!
|
|
I.pixel_z = 16
|
|
|
|
// And animate the attack!
|
|
animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
|
|
|
|
/atom/movable/proc/receive_damage(atom/A)
|
|
var/pixel_x_diff = rand(-3,3)
|
|
var/pixel_y_diff = rand(-3,3)
|
|
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2)
|
|
animate(pixel_x = initial(pixel_x), pixel_y = initial(pixel_y), time = 2)
|
|
|
|
/mob/living/receive_damage(atom/A)
|
|
..()
|
|
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
|
|
|
|
/mob/living/proc/do_jitter_animation(jitteriness)
|
|
var/amplitude = min(4, (jitteriness/100) + 1)
|
|
var/pixel_x_diff = rand(-amplitude, amplitude)
|
|
var/pixel_y_diff = rand(-amplitude/3, amplitude/3)
|
|
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6)
|
|
animate(pixel_x = initial(pixel_x) , pixel_y = initial(pixel_y) , time = 2)
|
|
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
|
|
|
|
|
|
/mob/living/proc/get_temperature(datum/gas_mixture/environment)
|
|
var/loc_temp = T0C
|
|
if(istype(loc, /obj/mecha))
|
|
var/obj/mecha/M = loc
|
|
loc_temp = M.return_temperature()
|
|
|
|
else if(istype(loc, /obj/spacepod))
|
|
var/obj/spacepod/S = loc
|
|
loc_temp = S.return_temperature()
|
|
|
|
else if(istype(loc, /obj/structure/transit_tube_pod))
|
|
loc_temp = environment.temperature
|
|
|
|
else if(istype(get_turf(src), /turf/space))
|
|
var/turf/heat_turf = get_turf(src)
|
|
loc_temp = heat_turf.temperature
|
|
|
|
else if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
|
|
var/obj/machinery/atmospherics/unary/cryo_cell/C = loc
|
|
|
|
if(C.air_contents.total_moles() < 10)
|
|
loc_temp = environment.temperature
|
|
else
|
|
loc_temp = C.air_contents.temperature
|
|
|
|
else
|
|
loc_temp = environment.temperature
|
|
|
|
return loc_temp
|
|
|
|
/mob/living/proc/get_standard_pixel_x_offset(lying = 0)
|
|
return initial(pixel_x)
|
|
|
|
/mob/living/proc/get_standard_pixel_y_offset(lying = 0)
|
|
return initial(pixel_y)
|
|
|
|
/mob/living/proc/spawn_dust()
|
|
new /obj/effect/decal/cleanable/ash(loc)
|
|
|
|
//used in datum/reagents/reaction() proc
|
|
/mob/living/proc/get_permeability_protection()
|
|
return 0
|
|
|
|
/mob/living/proc/attempt_harvest(obj/item/I, mob/user)
|
|
if(stat == DEAD && !isnull(butcher_results)) //can we butcher it?
|
|
if(istype(I, /obj/item/weapon/kitchen/knife))
|
|
to_chat(user, "<span class='notice'>You begin to butcher [src]...</span>")
|
|
playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
|
|
if(do_mob(user, src, 80))
|
|
harvest(user)
|
|
return 1
|
|
|
|
/mob/living/proc/harvest(mob/living/user)
|
|
if(qdeleted(src))
|
|
return
|
|
if(butcher_results)
|
|
for(var/path in butcher_results)
|
|
for(var/i = 1, i <= butcher_results[path], i++)
|
|
new path(loc)
|
|
butcher_results.Remove(path) //In case you want to have things like simple_animals drop their butcher results on gib, so it won't double up below.
|
|
visible_message("<span class='notice'>[user] butchers [src].</span>")
|
|
gib()
|
|
|
|
/mob/living/movement_delay()
|
|
var/tally = 0
|
|
|
|
if(slowed)
|
|
tally += 10
|
|
|
|
return tally
|
|
|
|
/mob/living/proc/can_use_guns(var/obj/item/weapon/gun/G)
|
|
if(G.trigger_guard != TRIGGER_GUARD_ALLOW_ALL && !IsAdvancedToolUser())
|
|
to_chat(src, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
|
return 0
|
|
return 1
|