mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-20 10:37:45 +01:00
* Laser pointers Adds laser pointers, ported from tg/oldaurora (but heavily modified). They can be found in the loadout, as well as made by science. Science can also upgrade them, which makes them occasionally useful for blinding people, too. The bugfixes which make several of the features work properly will come in a separate commit. * Three fixes Cats now have resting sprites for all 4 directions, instead of just east. This was needed to make cats look like they're pouncing on the laser dot. Cameras can now be EMPed more than once, and EMPs actually are able to disable them now. This was needed for the shining lasers into cameras feature. Flash_eyes() now actually displays a flashing animation on your screen when you get flashed (except for silicons, who for some reason are excluded from this unless EMPed). This was needed for laser pointers to have a temporary "blinding" effect when shone into someone's eyes. (removes errant debug message too, whoops) * Nerf Reduced chances of laser pointers doing anything useful on silicons. Also, fixes a duplicated proc, oops. * Requested changes Minor changes as requested - 'cell' to 'diode', view() to viewers(), range() to viewers(). Stops buckled or dead cats from reacting to laser pointers. Zombie cats are fun, but no. Also, does another small nerf to the effects on silicons.
390 lines
13 KiB
Plaintext
390 lines
13 KiB
Plaintext
/mob/living/carbon/New()
|
|
//setup reagent holders
|
|
bloodstr = new/datum/reagents/metabolism/bloodstream(500, src)
|
|
ingested = new/datum/reagents/metabolism/ingested(500, src)
|
|
touching = new/datum/reagents/metabolism/touch(500, src)
|
|
reagents = bloodstr
|
|
if (!default_language && species_language)
|
|
default_language = all_languages[species_language]
|
|
..()
|
|
|
|
/mob/living/carbon/Life()
|
|
..()
|
|
|
|
handle_viruses()
|
|
|
|
// Increase germ_level regularly
|
|
if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level
|
|
germ_level++
|
|
|
|
/mob/living/carbon/Destroy()
|
|
qdel(ingested)
|
|
qdel(touching)
|
|
// We don't qdel(bloodstr) because it's the same as qdel(reagents)
|
|
for(var/guts in internal_organs)
|
|
qdel(guts)
|
|
for(var/food in stomach_contents)
|
|
qdel(food)
|
|
return ..()
|
|
|
|
/mob/living/carbon/rejuvenate()
|
|
bloodstr.clear_reagents()
|
|
ingested.clear_reagents()
|
|
touching.clear_reagents()
|
|
..()
|
|
|
|
/mob/living/carbon/Move(NewLoc, direct)
|
|
. = ..()
|
|
if(.)
|
|
if(src.nutrition && src.stat != 2)
|
|
src.nutrition -= DEFAULT_HUNGER_FACTOR/10
|
|
if(src.m_intent == "run")
|
|
src.nutrition -= DEFAULT_HUNGER_FACTOR/10
|
|
if((FAT in src.mutations) && src.m_intent == "run" && src.bodytemperature <= 360)
|
|
src.bodytemperature += 2
|
|
|
|
// Moving around increases germ_level faster
|
|
if(germ_level < GERM_LEVEL_MOVE_CAP && prob(8))
|
|
germ_level++
|
|
|
|
/mob/living/carbon/relaymove(var/mob/living/user, direction)
|
|
if((user in src.stomach_contents) && istype(user))
|
|
if(user.last_special <= world.time)
|
|
user.last_special = world.time + 50
|
|
src.visible_message("<span class='danger'>You hear something rumbling inside [src]'s stomach...</span>")
|
|
var/obj/item/I = user.get_active_hand()
|
|
if(I && I.force)
|
|
var/d = rand(round(I.force / 4), I.force)
|
|
if(istype(src, /mob/living/carbon/human))
|
|
var/mob/living/carbon/human/H = src
|
|
var/obj/item/organ/external/organ = H.get_organ(BP_TORSO)
|
|
if (istype(organ))
|
|
if(organ.take_damage(d, 0))
|
|
H.UpdateDamageIcon()
|
|
H.updatehealth()
|
|
else
|
|
src.take_organ_damage(d)
|
|
user.visible_message("<span class='danger'>[user] attacks [src]'s 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/gib()
|
|
for(var/mob/M in src)
|
|
if(M in src.stomach_contents)
|
|
src.stomach_contents.Remove(M)
|
|
M.loc = src.loc
|
|
for(var/mob/N in viewers(src, null))
|
|
if(N.client)
|
|
N.show_message(text("<font color='red'><B>[M] bursts out of [src]!</B></font>"), 2)
|
|
..()
|
|
|
|
/mob/living/carbon/attack_hand(mob/M as mob)
|
|
if(!istype(M, /mob/living/carbon)) return
|
|
if (ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
var/obj/item/organ/external/temp = H.organs_by_name["r_hand"]
|
|
if (H.hand)
|
|
temp = H.organs_by_name["l_hand"]
|
|
if(temp && !temp.is_usable())
|
|
H << "<font color='red'>You can't use your [temp.name]</font>"
|
|
return
|
|
|
|
return
|
|
|
|
/mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null, var/stun = 1)
|
|
if(status_flags & GODMODE) return 0 //godmode
|
|
if(def_zone == "l_hand" || def_zone == "r_hand") //Diona (And any other potential plant people) hands don't get shocked.
|
|
if(species.flags & IS_PLANT)
|
|
return 0
|
|
shock_damage *= siemens_coeff
|
|
if (shock_damage<1)
|
|
return 0
|
|
|
|
src.apply_damage(shock_damage, BURN, def_zone, used_weapon="Electrocution")
|
|
playsound(loc, "sparks", 50, 1, -1)
|
|
if (shock_damage > 15)
|
|
src.visible_message(
|
|
"<span class='warning'>[src] was electrocuted[source ? " by the [source]" : ""]!</span>", \
|
|
"<span class='danger'>You feel a powerful shock course through your body!</span>", \
|
|
"<span class='warning'>You hear a heavy electrical crack.</span>" \
|
|
)
|
|
else
|
|
src.visible_message(
|
|
"<span class='warning'>[src] was shocked[source ? " by the [source]" : ""].</span>", \
|
|
"<span class='warning'>You feel a shock course through your body.</span>", \
|
|
"<span class='warning'>You hear a zapping sound.</span>" \
|
|
)
|
|
|
|
if(stun)
|
|
switch(shock_damage)
|
|
if(16 to 20)
|
|
Stun(2)
|
|
if(21 to 25)
|
|
Weaken(2)
|
|
if(26 to 30)
|
|
Weaken(5)
|
|
if(31 to INFINITY)
|
|
Weaken(10) //This should work for now, more is really silly and makes you lay there forever
|
|
|
|
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
|
s.set_up(5, 1, loc)
|
|
s.start()
|
|
|
|
return shock_damage
|
|
|
|
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
|
|
if (src.health >= config.health_threshold_crit)
|
|
if(src == M && istype(src, /mob/living/carbon/human))
|
|
var/mob/living/carbon/human/H = src
|
|
var/datum/gender/T = gender_datums[H.get_visible_gender()]
|
|
src.visible_message( \
|
|
"<font color='blue'>[src] examines [T.himself].</font>", \
|
|
"<font color='blue'>You check yourself for injuries.</font>" \
|
|
)
|
|
|
|
for(var/obj/item/organ/external/org in H.organs)
|
|
var/list/status = list()
|
|
var/brutedamage = org.brute_dam
|
|
var/burndamage = org.burn_dam
|
|
/*
|
|
if(halloss > 0) //Makes halloss show up as actual wounds on self examine.
|
|
if(prob(30))
|
|
brutedamage += halloss
|
|
if(prob(30))
|
|
burndamage += halloss
|
|
*/
|
|
switch(brutedamage)
|
|
if(1 to 20)
|
|
status += "bruised"
|
|
if(20 to 40)
|
|
status += "wounded"
|
|
if(40 to INFINITY)
|
|
status += "mangled"
|
|
|
|
switch(burndamage)
|
|
if(1 to 10)
|
|
status += "numb"
|
|
if(10 to 40)
|
|
status += "blistered"
|
|
if(40 to INFINITY)
|
|
status += "peeling away"
|
|
|
|
if(org.is_stump())
|
|
status += "MISSING"
|
|
if(org.status & ORGAN_MUTATED)
|
|
status += "weirdly shapen"
|
|
if(org.dislocated == 2)
|
|
status += "dislocated"
|
|
if(org.status & ORGAN_BROKEN)
|
|
status += "hurts when touched"
|
|
if(org.status & ORGAN_DEAD)
|
|
status += "is bruised and necrotic"
|
|
if(!org.is_usable() || org.is_dislocated())
|
|
status += "dangling uselessly"
|
|
if(status.len)
|
|
src.show_message("My [org.name] is <span class='warning'> [english_list(status)].</span>",1)
|
|
else
|
|
src.show_message("My [org.name] is <span class='notice'> OK.</span>",1)
|
|
|
|
if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit))
|
|
H.play_xylophone()
|
|
else if (on_fire)
|
|
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
|
if (M.on_fire)
|
|
M.visible_message("<span class='warning'>[M] tries to pat out [src]'s flames, but to no avail!</span>",
|
|
"<span class='warning'>You try to pat out [src]'s flames, but to no avail! Put yourself out first!</span>")
|
|
else
|
|
M.visible_message("<span class='warning'>[M] tries to pat out [src]'s flames!</span>",
|
|
"<span class='warning'>You try to pat out [src]'s flames! Hot!</span>")
|
|
if(do_mob(M, src, 15))
|
|
src.adjust_fire_stacks(-0.5)
|
|
if (prob(10) && (M.fire_stacks <= 0))
|
|
M.adjust_fire_stacks(1)
|
|
M.IgniteMob()
|
|
if (M.on_fire)
|
|
M.visible_message("<span class='danger'>The fire spreads from [src] to [M]!</span>",
|
|
"<span class='danger'>The fire spreads to you as well!</span>")
|
|
else
|
|
src.adjust_fire_stacks(-0.5) //Less effective than stop, drop, and roll - also accounting for the fact that it takes half as long.
|
|
if (src.fire_stacks <= 0)
|
|
M.visible_message("<span class='warning'>[M] successfully pats out [src]'s flames.</span>",
|
|
"<span class='warning'>You successfully pat out [src]'s flames.</span>")
|
|
src.ExtinguishMob()
|
|
src.fire_stacks = 0
|
|
else
|
|
if (istype(src,/mob/living/carbon/human) && src:w_uniform)
|
|
var/mob/living/carbon/human/H = src
|
|
H.w_uniform.add_fingerprint(M)
|
|
|
|
var/show_ssd
|
|
var/mob/living/carbon/human/H = src
|
|
var/datum/gender/T = gender_datums[H.get_visible_gender()] // make sure to cast to human before using get_gender() or get_visible_gender()!
|
|
if(istype(H)) show_ssd = H.species.show_ssd
|
|
if(show_ssd && !client && !teleop)
|
|
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [T.him] up!</span>", \
|
|
"<span class='notice'>You shake [src], but [T.he] [T.does] not respond... Maybe [T.he] [T.has] S.S.D?</span>")
|
|
else if(lying || src.sleeping)
|
|
src.sleeping = max(0,src.sleeping-5)
|
|
if(src.sleeping == 0)
|
|
src.resting = 0
|
|
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [T.him] up!</span>", \
|
|
"<span class='notice'>You shake [src] trying to wake [T.him] up!</span>")
|
|
else
|
|
var/mob/living/carbon/human/hugger = M
|
|
var/datum/gender/TM = gender_datums[M.get_visible_gender()]
|
|
if(M.resting == 1) //Are they resting on the ground?
|
|
M.visible_message("<span class='notice'>[M] grabs onto [src] and pulls [TM.himself] up</span>", \
|
|
"<span class='notice'>You grip onto [src] and pull yourself up off the ground!</span>")
|
|
if(M.fire_stacks >= (src.fire_stacks + 3)) //Fire checks.
|
|
src.adjust_fire_stacks(1)
|
|
M.adjust_fire_stacks(-1)
|
|
if(M.on_fire)
|
|
src.IgniteMob()
|
|
if(do_after(M, 0.5 SECONDS)) //.5 second delay. Makes it a bit stronger than just typing rest.
|
|
M.resting = 0 //Hoist yourself up up off the ground. No para/stunned/weakened removal.
|
|
else if(istype(hugger))
|
|
hugger.species.hug(hugger,src)
|
|
else
|
|
M.visible_message("<span class='notice'>[M] hugs [src] to make [T.him] feel better!</span>", \
|
|
"<span class='notice'>You hug [src] to make [T.him] feel better!</span>")
|
|
if(M.fire_stacks >= (src.fire_stacks + 3))
|
|
src.adjust_fire_stacks(1)
|
|
M.adjust_fire_stacks(-1)
|
|
if(M.on_fire)
|
|
src.IgniteMob()
|
|
AdjustParalysis(-3)
|
|
AdjustStunned(-3)
|
|
AdjustWeakened(-3)
|
|
|
|
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
|
|
|
/mob/living/carbon/proc/eyecheck()
|
|
return 0
|
|
|
|
/mob/living/carbon/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /obj/screen/fullscreen/flash)
|
|
if(eyecheck() < intensity || override_blindness_check)
|
|
return ..()
|
|
|
|
// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching.
|
|
// Stop! ... Hammertime! ~Carn
|
|
|
|
/mob/living/carbon/proc/getDNA()
|
|
return dna
|
|
|
|
/mob/living/carbon/proc/setDNA(var/datum/dna/newDNA)
|
|
dna = newDNA
|
|
|
|
// ++++ROCKDTBEN++++ MOB PROCS //END
|
|
|
|
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
|
..()
|
|
var/temp_inc = max(min(BODYTEMP_HEATING_MAX*(1-get_heat_protection()), exposed_temperature - bodytemperature), 0)
|
|
bodytemperature += temp_inc
|
|
|
|
/mob/living/carbon/can_use_hands()
|
|
if(handcuffed)
|
|
return 0
|
|
if(buckled && ! istype(buckled, /obj/structure/bed/chair)) // buckling does not restrict hands
|
|
return 0
|
|
return 1
|
|
|
|
/mob/living/carbon/restrained()
|
|
if (handcuffed)
|
|
return 1
|
|
return
|
|
|
|
/mob/living/carbon/u_equip(obj/item/W as obj)
|
|
if(!W) return 0
|
|
|
|
else if (W == handcuffed)
|
|
handcuffed = null
|
|
update_inv_handcuffed()
|
|
if(buckled && buckled.buckle_require_restraints)
|
|
buckled.unbuckle_mob()
|
|
|
|
else if (W == legcuffed)
|
|
legcuffed = null
|
|
update_inv_legcuffed()
|
|
else
|
|
..()
|
|
|
|
return
|
|
|
|
//generates realistic-ish pulse output based on preset levels
|
|
/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate
|
|
var/temp = 0 //see setup.dm:694
|
|
switch(src.pulse)
|
|
if(PULSE_NONE)
|
|
return "0"
|
|
if(PULSE_SLOW)
|
|
temp = rand(40, 60)
|
|
return num2text(method ? temp : temp + rand(-10, 10))
|
|
if(PULSE_NORM)
|
|
temp = rand(60, 90)
|
|
return num2text(method ? temp : temp + rand(-10, 10))
|
|
if(PULSE_FAST)
|
|
temp = rand(90, 120)
|
|
return num2text(method ? temp : temp + rand(-10, 10))
|
|
if(PULSE_2FAST)
|
|
temp = rand(120, 160)
|
|
return num2text(method ? temp : temp + rand(-10, 10))
|
|
if(PULSE_THREADY)
|
|
return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread"
|
|
// output for machines^ ^^^^^^^output for people^^^^^^^^^
|
|
|
|
/mob/living/carbon/verb/mob_sleep()
|
|
set name = "Sleep"
|
|
set category = "IC"
|
|
|
|
if(usr.sleeping)
|
|
usr << "<font color='red'>You are already sleeping</font>"
|
|
return
|
|
if(alert(src,"You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes")
|
|
usr.sleeping = 20 //Short nap
|
|
|
|
/mob/living/carbon/Bump(var/atom/movable/AM, yes)
|
|
if(now_pushing || !yes)
|
|
return
|
|
..()
|
|
if(istype(AM, /mob/living/carbon) && prob(10))
|
|
src.spread_disease_to(AM, "Contact")
|
|
|
|
/mob/living/carbon/cannot_use_vents()
|
|
return
|
|
|
|
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)
|
|
if(buckled)
|
|
return 0
|
|
stop_pulling()
|
|
src << "<span class='warning'>You slipped on [slipped_on]!</span>"
|
|
playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
|
|
Weaken(Floor(stun_duration/2))
|
|
return 1
|
|
|
|
/mob/living/carbon/proc/add_chemical_effect(var/effect, var/magnitude = 1)
|
|
if(effect in chem_effects)
|
|
chem_effects[effect] += magnitude
|
|
else
|
|
chem_effects[effect] = magnitude
|
|
|
|
/mob/living/carbon/get_default_language()
|
|
if(default_language && can_speak(default_language))
|
|
return default_language
|
|
|
|
if(!species)
|
|
return null
|
|
return species.default_language ? all_languages[species.default_language] : null
|
|
|
|
/mob/living/carbon/proc/should_have_organ(var/organ_check)
|
|
return 0
|
|
|
|
/mob/living/carbon/can_feel_pain(var/check_organ)
|
|
if(isSynthetic())
|
|
return 0
|
|
return !(species.flags & NO_PAIN)
|