mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-01-04 06:22:38 +00:00
Merge branch 'master' into pol-moved
This commit is contained in:
93
code/modules/mob/_modifiers/changeling.dm
Normal file
93
code/modules/mob/_modifiers/changeling.dm
Normal file
@@ -0,0 +1,93 @@
|
||||
/datum/modifier/changeling
|
||||
name = "changeling"
|
||||
desc = "Changeling modifier."
|
||||
|
||||
var/required_chems = 1 // Default is to require at least 1 chem unit. This does not consume it.
|
||||
|
||||
var/chem_maintenance = 1 // How many chems are expended per cycle, if we are consuming chems.
|
||||
|
||||
var/max_genetic_damage = 100
|
||||
|
||||
var/max_stat = 0
|
||||
|
||||
var/use_chems = FALSE // Do we have an upkeep cost on chems?
|
||||
|
||||
var/exterior_modifier = FALSE // Should we be checking the origin mob for chems?
|
||||
|
||||
/datum/modifier/changeling/check_if_valid()
|
||||
var/mob/living/L = null
|
||||
if(exterior_modifier)
|
||||
if(origin)
|
||||
L = origin.resolve()
|
||||
else
|
||||
expire()
|
||||
return
|
||||
|
||||
if((!exterior_modifier && !holder.changeling_power(required_chems, 0, max_genetic_damage, max_stat)) || (exterior_modifier && L && !L.changeling_power(required_chems, 0, max_genetic_damage, max_stat)))
|
||||
expire()
|
||||
else
|
||||
..()
|
||||
|
||||
/datum/modifier/changeling/tick()
|
||||
..()
|
||||
|
||||
if(use_chems)
|
||||
var/mob/living/L = null
|
||||
|
||||
if(exterior_modifier)
|
||||
L = origin.resolve()
|
||||
|
||||
else
|
||||
L = holder
|
||||
|
||||
L.mind.changeling.chem_charges = between(0, L.mind.changeling.chem_charges - chem_maintenance, L.mind.changeling.chem_storage)
|
||||
|
||||
/datum/modifier/changeling/thermal_sight
|
||||
name = "Thermal Adaptation"
|
||||
desc = "Our eyes are capable of seeing into the infrared spectrum to accurately identify prey through walls."
|
||||
vision_flags = SEE_MOBS
|
||||
|
||||
on_expired_text = "<span class='alien'>Your sight returns to what it once was.</span>"
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
/datum/modifier/changeling/thermal_sight/check_if_valid()
|
||||
var/mob/living/L = null
|
||||
|
||||
if(exterior_modifier)
|
||||
L = origin.resolve()
|
||||
|
||||
else
|
||||
L = holder
|
||||
|
||||
if(!L)
|
||||
expire()
|
||||
return
|
||||
|
||||
var/datum/changeling/changeling = L.changeling_power(0,0,100,CONSCIOUS)
|
||||
|
||||
if(!changeling)
|
||||
expire()
|
||||
return
|
||||
|
||||
if(!changeling.thermal_sight)
|
||||
expire()
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/datum/modifier/changeling/thermal_sight/expire()
|
||||
var/mob/living/L = null
|
||||
|
||||
if(exterior_modifier)
|
||||
L = origin.resolve()
|
||||
|
||||
else
|
||||
L = holder
|
||||
|
||||
if(L)
|
||||
var/datum/changeling/changeling = L.changeling_power(0,0,100,CONSCIOUS)
|
||||
|
||||
if(changeling)
|
||||
changeling.thermal_sight = FALSE
|
||||
|
||||
..()
|
||||
@@ -51,6 +51,8 @@
|
||||
var/emp_modifier // Added to the EMP strength, which is an inverse scale from 1 to 4, with 1 being the strongest EMP. 5 is a nullification.
|
||||
var/explosion_modifier // Added to the bomb strength, which is an inverse scale from 1 to 3, with 1 being gibstrength. 4 is a nullification.
|
||||
|
||||
var/vision_flags // Vision flags to add to the mob. SEE_MOB, SEE_OBJ, etc.
|
||||
|
||||
/datum/modifier/New(var/new_holder, var/new_origin)
|
||||
holder = new_holder
|
||||
if(new_origin)
|
||||
|
||||
@@ -83,7 +83,7 @@ the artifact triggers the rage.
|
||||
|
||||
/datum/modifier/berserk/on_applied()
|
||||
if(ishuman(holder)) // Most other mobs don't really use nutrition and can't get it back.
|
||||
holder.nutrition = max(0, holder.nutrition - nutrition_cost)
|
||||
holder.adjust_nutrition(-nutrition_cost)
|
||||
holder.visible_message("<span class='critical'>\The [holder] descends into an all consuming rage!</span>")
|
||||
|
||||
// End all stuns.
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
if(ishuman(holder))
|
||||
var/mob/living/carbon/human/H = holder
|
||||
var/starting_nutrition = H.nutrition
|
||||
H.nutrition = max(0, H.nutrition - 10)
|
||||
H.adjust_nutrition(-10)
|
||||
var/healing_amount = starting_nutrition - H.nutrition
|
||||
if(healing_amount < 0) // If you are eating enough to somehow outpace this, congratulations, you are gluttonous enough to gain a boon.
|
||||
healing_amount *= -2
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
signlang_verb = list("gestures with their hands", "gestures with their ears and tail", "gestures with their ears, tail and hands")
|
||||
colour = "tajaran"
|
||||
key = "l"
|
||||
flags = WHITELISTED | SIGNLANG | NO_STUTTER | NONVERBAL
|
||||
flags = WHITELISTED | SIGNLANG | NO_STUTTER //nonverbal define was not needed here, and i need to use it ~Layne
|
||||
|
||||
/datum/language/tajsign/broadcast(var/mob/living/speaker, var/message, var/speaker_mask)
|
||||
log_say("(SIGN) [message]", speaker)
|
||||
@@ -219,6 +219,19 @@
|
||||
space_chance = 20
|
||||
syllables = list("z", "dz", "i", "iv", "ti", "az", "hix", "xo", "av", "xo", "x", "za", "at", "vi")
|
||||
|
||||
/datum/language/promethean
|
||||
name = LANGUAGE_PROMETHEAN
|
||||
desc = "A complex language composed of guttural noises and bioluminescent signals"
|
||||
signlang_verb = list("flickers","flashes","rapidly flashes a light","quickly flickers a light")
|
||||
speech_verb = "gurgles"
|
||||
ask_verb = "gurgles"
|
||||
exclaim_verb = "gurgles"
|
||||
colour = "promethean"
|
||||
key = "t"
|
||||
flags = WHITELISTED | NONVERBAL
|
||||
space_chance = 20
|
||||
syllables = list("gur","gul","gug","gel","ger","geg","gir","gil","gig","gor","gol","gog","ug","ul","ur","uu","el","eg","er","oe","ig","il","ir","oi","og","ol","or","oo")
|
||||
|
||||
|
||||
//Syllable Lists
|
||||
/*
|
||||
|
||||
@@ -6,16 +6,14 @@
|
||||
var/turf/T = loc
|
||||
light_amount = T.get_lumcount() * 5
|
||||
|
||||
nutrition += light_amount
|
||||
adjust_nutrition(light_amount)
|
||||
|
||||
if(nutrition > 500)
|
||||
nutrition = 500
|
||||
if(light_amount > 2) //if there's enough light, heal
|
||||
adjustBruteLoss(-1)
|
||||
adjustFireLoss(-1)
|
||||
adjustToxLoss(-1)
|
||||
adjustOxyLoss(-1)
|
||||
|
||||
|
||||
|
||||
|
||||
if(!client)
|
||||
handle_npc(src)
|
||||
handle_npc(src)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
var/rads = radiation/25
|
||||
radiation -= rads
|
||||
nutrition += rads
|
||||
adjust_nutrition(rads)
|
||||
heal_overall_damage(rads,rads)
|
||||
adjustOxyLoss(-(rads))
|
||||
adjustToxLoss(-(rads))
|
||||
|
||||
@@ -196,24 +196,20 @@
|
||||
return //Doesn't do anything right now because none of the things that can be done to a regular MMI make any sense for these
|
||||
|
||||
/obj/item/device/mmi/digital/examine(mob/user)
|
||||
if(!..(user))
|
||||
return
|
||||
|
||||
var/msg = "<span class='info'>*---------*</span>\nThis is [bicon(src)] \a <EM>[src]</EM>!\n[desc]\n"
|
||||
msg += "<span class='warning'>"
|
||||
. = ..()
|
||||
|
||||
if(src.brainmob && src.brainmob.key)
|
||||
switch(src.brainmob.stat)
|
||||
if(CONSCIOUS)
|
||||
if(!src.brainmob.client) msg += "It appears to be in stand-by mode.\n" //afk
|
||||
if(UNCONSCIOUS) msg += "<span class='warning'>It doesn't seem to be responsive.</span>\n"
|
||||
if(DEAD) msg += "<span class='deadsay'>It appears to be completely inactive.</span>\n"
|
||||
if(!src.brainmob.client)
|
||||
. += "<span class='warning'>It appears to be in stand-by mode.</span>" //afk
|
||||
if(UNCONSCIOUS)
|
||||
. += "<span class='warning'>It doesn't seem to be responsive.</span>"
|
||||
if(DEAD)
|
||||
. += "<span class='deadsay'>It appears to be completely inactive.</span>"
|
||||
else
|
||||
msg += "<span class='deadsay'>It appears to be completely inactive.</span>\n"
|
||||
msg += "</span><span class='info'>*---------*</span>"
|
||||
to_chat(user,msg)
|
||||
return
|
||||
|
||||
. += "<span class='deadsay'>It appears to be completely inactive.</span>"
|
||||
|
||||
/obj/item/device/mmi/digital/emp_act(severity)
|
||||
if(!src.brainmob)
|
||||
return
|
||||
|
||||
@@ -85,25 +85,6 @@
|
||||
M.show_message("<font color='blue'>The positronic brain buzzes and beeps, and the golden lights fade away. Perhaps you could try again?</font>")
|
||||
playsound(src, 'sound/misc/buzzbeep.ogg', 50, 1)
|
||||
|
||||
/obj/item/device/mmi/digital/posibrain/examine(mob/user)
|
||||
if(!..(user))
|
||||
return
|
||||
|
||||
var/msg = "<span class='info'>*---------*</span>\nThis is [bicon(src)] \a <EM>[src]</EM>!\n[desc]\n"
|
||||
msg += "<span class='warning'>"
|
||||
|
||||
if(src.brainmob && src.brainmob.key)
|
||||
switch(src.brainmob.stat)
|
||||
if(CONSCIOUS)
|
||||
if(!src.brainmob.client) msg += "It appears to be in stand-by mode.\n" //afk
|
||||
if(UNCONSCIOUS) msg += "<span class='warning'>It doesn't seem to be responsive.</span>\n"
|
||||
if(DEAD) msg += "<span class='deadsay'>It appears to be completely inactive.</span>\n"
|
||||
else
|
||||
msg += "<span class='deadsay'>It appears to be completely inactive.</span>\n"
|
||||
msg += "</span><span class='info'>*---------*</span>"
|
||||
to_chat(user,msg)
|
||||
return
|
||||
|
||||
/obj/item/device/mmi/digital/posibrain/emp_act(severity)
|
||||
if(!src.brainmob)
|
||||
return
|
||||
|
||||
@@ -1,401 +1,402 @@
|
||||
/mob/living/carbon/Initialize()
|
||||
. = ..()
|
||||
//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 = GLOB.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/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
. = ..()
|
||||
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())
|
||||
to_chat(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(0.2 * shock_damage, BURN, def_zone, used_weapon="Electrocution") //shock the target organ
|
||||
src.apply_damage(0.4 * shock_damage, BURN, BP_TORSO, used_weapon="Electrocution") //shock the torso more
|
||||
src.apply_damage(0.2 * shock_damage, BURN, null, used_weapon="Electrocution") //shock a random part!
|
||||
src.apply_damage(0.2 * shock_damage, BURN, null, used_weapon="Electrocution") //shock a random part!
|
||||
|
||||
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( \
|
||||
"<span class='notice'>[src] examines [T.himself].</span>", \
|
||||
"<span class='notice'>You check yourself for injuries.</span>" \
|
||||
)
|
||||
|
||||
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/nest)) // 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)
|
||||
to_chat(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(atom/A)
|
||||
if(now_pushing)
|
||||
return
|
||||
..()
|
||||
if(istype(A, /mob/living/carbon) && prob(10))
|
||||
spread_disease_to(A, "Contact")
|
||||
|
||||
/mob/living/carbon/cannot_use_vents()
|
||||
return
|
||||
|
||||
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)
|
||||
if(buckled)
|
||||
return 0
|
||||
stop_pulling()
|
||||
to_chat(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, 1))
|
||||
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)
|
||||
if(can_speak(default_language))
|
||||
return default_language
|
||||
else
|
||||
return GLOB.all_languages[LANGUAGE_GIBBERISH]
|
||||
|
||||
if(!species)
|
||||
return null
|
||||
|
||||
return species.default_language ? GLOB.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)
|
||||
|
||||
/mob/living/carbon/needs_to_breathe()
|
||||
if(does_not_breathe)
|
||||
return FALSE
|
||||
return ..()
|
||||
/mob/living/carbon/Initialize()
|
||||
. = ..()
|
||||
//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 = GLOB.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/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
. = ..()
|
||||
if(src.nutrition && src.stat != 2)
|
||||
adjust_nutrition(-DEFAULT_HUNGER_FACTOR / 10)
|
||||
if(src.m_intent == "run")
|
||||
adjust_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())
|
||||
to_chat(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(0.2 * shock_damage, BURN, def_zone, used_weapon="Electrocution") //shock the target organ
|
||||
src.apply_damage(0.4 * shock_damage, BURN, BP_TORSO, used_weapon="Electrocution") //shock the torso more
|
||||
src.apply_damage(0.2 * shock_damage, BURN, null, used_weapon="Electrocution") //shock a random part!
|
||||
src.apply_damage(0.2 * shock_damage, BURN, null, used_weapon="Electrocution") //shock a random part!
|
||||
|
||||
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( \
|
||||
"<span class='notice'>[src] examines [T.himself].</span>", \
|
||||
"<span class='notice'>You check yourself for injuries.</span>" \
|
||||
)
|
||||
|
||||
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/nest)) // 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)
|
||||
to_chat(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(atom/A)
|
||||
if(now_pushing)
|
||||
return
|
||||
..()
|
||||
if(istype(A, /mob/living/carbon) && prob(10))
|
||||
spread_disease_to(A, "Contact")
|
||||
|
||||
/mob/living/carbon/cannot_use_vents()
|
||||
return
|
||||
|
||||
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)
|
||||
if(buckled)
|
||||
return 0
|
||||
stop_pulling()
|
||||
to_chat(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, 1))
|
||||
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)
|
||||
if(can_speak(default_language))
|
||||
return default_language
|
||||
else
|
||||
return GLOB.all_languages[LANGUAGE_GIBBERISH]
|
||||
|
||||
if(!species)
|
||||
return null
|
||||
|
||||
return species.default_language ? GLOB.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)
|
||||
|
||||
/mob/living/carbon/needs_to_breathe()
|
||||
if(does_not_breathe)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/mob/living/carbon/human/examine(mob/user)
|
||||
// . = ..() //Note that we don't call parent. We build the list by ourselves.
|
||||
|
||||
var/skip_gear = 0
|
||||
var/skip_body = 0
|
||||
|
||||
if(alpha <= EFFECTIVE_INVIS)
|
||||
src.loc.examine(user)
|
||||
return
|
||||
return src.loc.examine(user) // Returns messages as if they examined wherever the human was
|
||||
|
||||
var/looks_synth = looksSynthetic()
|
||||
|
||||
@@ -75,12 +76,6 @@
|
||||
BP_L_LEG = skip_body & EXAMINE_SKIPLEGS,
|
||||
BP_R_LEG = skip_body & EXAMINE_SKIPLEGS)
|
||||
|
||||
var/list/msg = list("<span class='info'>*---------*<br>This is ")
|
||||
|
||||
msg += "[bicon(src)] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated
|
||||
|
||||
msg += "<EM>[src.name]</EM>"
|
||||
|
||||
var/datum/gender/T = gender_datums[get_visible_gender()]
|
||||
|
||||
if((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)) //big suits/masks/helmets make it hard to tell their gender
|
||||
@@ -98,6 +93,7 @@
|
||||
// Just in case someone VVs the gender to something strange. It'll runtime anyway when it hits usages, better to CRASH() now with a helpful message.
|
||||
CRASH("Gender datum was null; key was '[((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)) ? PLURAL : gender]'")
|
||||
|
||||
var/name_ender = ""
|
||||
if(!((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)))
|
||||
if(looks_synth)
|
||||
var/use_gender = "a synthetic"
|
||||
@@ -106,16 +102,12 @@
|
||||
else if(gender == FEMALE)
|
||||
use_gender = "a gynoid"
|
||||
|
||||
msg += ", <b><font color='#555555'>[use_gender]!</font></b>"
|
||||
name_ender = ", <b><font color='#555555'>[use_gender]!</font></b>[species.get_additional_examine_text(src)]"
|
||||
|
||||
else if(species.name != "Human")
|
||||
msg += ", <b><font color='[species.get_flesh_colour(src)]'>\a [species.get_examine_name()]!</font></b>"
|
||||
name_ender = ", <b><font color='[species.get_flesh_colour(src)]'>\a [species.get_examine_name()]!</font></b>[species.get_additional_examine_text(src)]"
|
||||
|
||||
var/extra_species_text = species.get_additional_examine_text(src)
|
||||
if(extra_species_text)
|
||||
msg += "[extra_species_text]"
|
||||
|
||||
msg += "<br>"
|
||||
var/list/msg = list("<span class='info'>*---------*","This is [bicon(src)] <EM>[src.name]</EM>[name_ender]")
|
||||
|
||||
//uniform
|
||||
if(w_uniform && !(skip_gear & EXAMINE_SKIPJUMPSUIT) && w_uniform.show_examine)
|
||||
@@ -138,16 +130,16 @@
|
||||
tie_msg += " Attached to it is [english_list(accessories_visible)]."
|
||||
|
||||
if(w_uniform.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] [(w_uniform.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [w_uniform.name]![tie_msg]</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] [(w_uniform.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [w_uniform.name]![tie_msg]</span>"
|
||||
else
|
||||
msg += "[T.He] [T.is] wearing [bicon(w_uniform)] \a [w_uniform].[tie_msg]<br>"
|
||||
msg += "[T.He] [T.is] wearing [bicon(w_uniform)] \a [w_uniform].[tie_msg]"
|
||||
|
||||
//head
|
||||
if(head && !(skip_gear & EXAMINE_SKIPHELMET) && head.show_examine)
|
||||
if(head.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] [(head.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [head.name] on [T.his] head!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] [(head.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [head.name] on [T.his] head!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.is] wearing [bicon(head)] \a [head] on [T.his] head.<br>"
|
||||
msg += "[T.He] [T.is] wearing [bicon(head)] \a [head] on [T.his] head."
|
||||
|
||||
//suit/armour
|
||||
if(wear_suit)
|
||||
@@ -158,73 +150,73 @@
|
||||
tie_msg += " Attached to it is [english_list(U.accessories)]."
|
||||
|
||||
if(wear_suit.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] [(wear_suit.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [wear_suit.name][tie_msg]!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] [(wear_suit.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [wear_suit.name][tie_msg]!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.is] wearing [bicon(wear_suit)] \a [wear_suit].[tie_msg]<br>"
|
||||
msg += "[T.He] [T.is] wearing [bicon(wear_suit)] \a [wear_suit].[tie_msg]"
|
||||
|
||||
//suit/armour storage
|
||||
if(s_store && !(skip_gear & EXAMINE_SKIPSUITSTORAGE) && s_store.show_examine)
|
||||
if(s_store.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.is] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] [(s_store.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [s_store.name] on [T.his] [wear_suit.name]!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] [(s_store.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [s_store.name] on [T.his] [wear_suit.name]!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.is] carrying [bicon(s_store)] \a [s_store] on [T.his] [wear_suit.name].<br>"
|
||||
msg += "[T.He] [T.is] carrying [bicon(s_store)] \a [s_store] on [T.his] [wear_suit.name]."
|
||||
|
||||
//back
|
||||
if(back && !(skip_gear & EXAMINE_SKIPBACKPACK) && back.show_examine)
|
||||
if(back.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(back)] [back.gender==PLURAL?"some":"a"] [(back.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [back] on [T.his] back.</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(back)] [back.gender==PLURAL?"some":"a"] [(back.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [back] on [T.his] back.</span>"
|
||||
else
|
||||
msg += "[T.He] [T.has] [bicon(back)] \a [back] on [T.his] back.<br>"
|
||||
msg += "[T.He] [T.has] [bicon(back)] \a [back] on [T.his] back."
|
||||
|
||||
//left hand
|
||||
if(l_hand && l_hand.show_examine)
|
||||
if(l_hand.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.is] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] [(l_hand.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [l_hand.name] in [T.his] left hand!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] [(l_hand.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [l_hand.name] in [T.his] left hand!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.is] holding [bicon(l_hand)] \a [l_hand] in [T.his] left hand.<br>"
|
||||
msg += "[T.He] [T.is] holding [bicon(l_hand)] \a [l_hand] in [T.his] left hand."
|
||||
|
||||
//right hand
|
||||
if(r_hand && r_hand.show_examine)
|
||||
if(r_hand.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.is] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] [(r_hand.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [r_hand.name] in [T.his] right hand!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] [(r_hand.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [r_hand.name] in [T.his] right hand!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.is] holding [bicon(r_hand)] \a [r_hand] in [T.his] right hand.<br>"
|
||||
msg += "[T.He] [T.is] holding [bicon(r_hand)] \a [r_hand] in [T.his] right hand."
|
||||
|
||||
//gloves
|
||||
if(gloves && !(skip_gear & EXAMINE_SKIPGLOVES) && gloves.show_examine)
|
||||
if(gloves.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] [(gloves.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [gloves.name] on [T.his] hands!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] [(gloves.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [gloves.name] on [T.his] hands!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.has] [bicon(gloves)] \a [gloves] on [T.his] hands.<br>"
|
||||
msg += "[T.He] [T.has] [bicon(gloves)] \a [gloves] on [T.his] hands."
|
||||
else if(blood_DNA && !(skip_body & EXAMINE_SKIPHANDS))
|
||||
msg += "<span class='warning'>[T.He] [T.has] [(hand_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained hands!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.has] [(hand_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained hands!</span>"
|
||||
|
||||
//handcuffed?
|
||||
if(handcuffed && handcuffed.show_examine)
|
||||
if(istype(handcuffed, /obj/item/weapon/handcuffs/cable))
|
||||
msg += "<span class='warning'>[T.He] [T.is] [bicon(handcuffed)] restrained with cable!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] [bicon(handcuffed)] restrained with cable!</span>"
|
||||
else
|
||||
msg += "<span class='warning'>[T.He] [T.is] [bicon(handcuffed)] handcuffed!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] [bicon(handcuffed)] handcuffed!</span>"
|
||||
|
||||
//buckled
|
||||
if(buckled)
|
||||
msg += "<span class='warning'>[T.He] [T.is] [bicon(buckled)] buckled to [buckled]!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] [bicon(buckled)] buckled to [buckled]!</span>"
|
||||
|
||||
//belt
|
||||
if(belt && !(skip_gear & EXAMINE_SKIPBELT) && belt.show_examine)
|
||||
if(belt.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] [(belt.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [belt.name] about [T.his] waist!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] [(belt.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [belt.name] about [T.his] waist!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.has] [bicon(belt)] \a [belt] about [T.his] waist.<br>"
|
||||
msg += "[T.He] [T.has] [bicon(belt)] \a [belt] about [T.his] waist."
|
||||
|
||||
//shoes
|
||||
if(shoes && !(skip_gear & EXAMINE_SKIPSHOES) && shoes.show_examine)
|
||||
if(shoes.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] [(shoes.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [shoes.name] on [T.his] feet!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] [(shoes.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [shoes.name] on [T.his] feet!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.is] wearing [bicon(shoes)] \a [shoes] on [T.his] feet.<br>"
|
||||
msg += "[T.He] [T.is] wearing [bicon(shoes)] \a [shoes] on [T.his] feet."
|
||||
else if(feet_blood_DNA && !(skip_body & EXAMINE_SKIPHANDS))
|
||||
msg += "<span class='warning'>[T.He] [T.has] [(feet_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained feet!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.has] [(feet_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained feet!</span>"
|
||||
|
||||
//mask
|
||||
if(wear_mask && !(skip_gear & EXAMINE_SKIPMASK) && wear_mask.show_examine)
|
||||
@@ -233,24 +225,24 @@
|
||||
descriptor = "in [T.his] mouth"
|
||||
|
||||
if(wear_mask.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] [(wear_mask.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [wear_mask.name] [descriptor]!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] [(wear_mask.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [wear_mask.name] [descriptor]!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.has] [bicon(wear_mask)] \a [wear_mask] [descriptor].<br>"
|
||||
msg += "[T.He] [T.has] [bicon(wear_mask)] \a [wear_mask] [descriptor]."
|
||||
|
||||
//eyes
|
||||
if(glasses && !(skip_gear & EXAMINE_SKIPEYEWEAR) && glasses.show_examine)
|
||||
if(glasses.blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] [(glasses.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [glasses] covering [T.his] eyes!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] [(glasses.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [glasses] covering [T.his] eyes!</span>"
|
||||
else
|
||||
msg += "[T.He] [T.has] [bicon(glasses)] \a [glasses] covering [T.his] eyes.<br>"
|
||||
msg += "[T.He] [T.has] [bicon(glasses)] \a [glasses] covering [T.his] eyes."
|
||||
|
||||
//left ear
|
||||
if(l_ear && !(skip_gear & EXAMINE_SKIPEARS) && l_ear.show_examine)
|
||||
msg += "[T.He] [T.has] [bicon(l_ear)] \a [l_ear] on [T.his] left ear.<br>"
|
||||
msg += "[T.He] [T.has] [bicon(l_ear)] \a [l_ear] on [T.his] left ear."
|
||||
|
||||
//right ear
|
||||
if(r_ear && !(skip_gear & EXAMINE_SKIPEARS) && r_ear.show_examine)
|
||||
msg += "[T.He] [T.has] [bicon(r_ear)] \a [r_ear] on [T.his] right ear.<br>"
|
||||
msg += "[T.He] [T.has] [bicon(r_ear)] \a [r_ear] on [T.his] right ear."
|
||||
|
||||
//ID
|
||||
if(wear_id && wear_id.show_examine)
|
||||
@@ -262,35 +254,35 @@
|
||||
var/obj/item/weapon/card/id/idcard = wear_id
|
||||
id = idcard.registered_name
|
||||
if(id && (id != real_name) && (get_dist(src, usr) <= 1) && prob(10))
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(wear_id)] \a [wear_id] yet something doesn't seem right...</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] wearing [bicon(wear_id)] \a [wear_id] yet something doesn't seem right...</span>"
|
||||
else*/
|
||||
msg += "[T.He] [T.is] wearing [bicon(wear_id)] \a [wear_id].<br>"
|
||||
msg += "[T.He] [T.is] wearing [bicon(wear_id)] \a [wear_id]."
|
||||
|
||||
//Jitters
|
||||
if(is_jittery)
|
||||
if(jitteriness >= 300)
|
||||
msg += "<span class='warning'><B>[T.He] [T.is] convulsing violently!</B></span><br>"
|
||||
msg += "<span class='warning'><B>[T.He] [T.is] convulsing violently!</B></span>"
|
||||
else if(jitteriness >= 200)
|
||||
msg += "<span class='warning'>[T.He] [T.is] extremely jittery.</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] extremely jittery.</span>"
|
||||
else if(jitteriness >= 100)
|
||||
msg += "<span class='warning'>[T.He] [T.is] twitching ever so slightly.</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] twitching ever so slightly.</span>"
|
||||
|
||||
//splints
|
||||
for(var/organ in BP_ALL)
|
||||
var/obj/item/organ/external/o = get_organ(organ)
|
||||
if(o && o.splinted && o.splinted.loc == o)
|
||||
msg += "<span class='warning'>[T.He] [T.has] \a [o.splinted] on [T.his] [o.name]!</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.has] \a [o.splinted] on [T.his] [o.name]!</span>"
|
||||
|
||||
if(suiciding)
|
||||
msg += "<span class='warning'>[T.He] appears to have commited suicide... there is no hope of recovery.</span><br>"
|
||||
msg += "<span class='warning'>[T.He] appears to have commited suicide... there is no hope of recovery.</span>"
|
||||
|
||||
if(mSmallsize in mutations)
|
||||
msg += "[T.He] [T.is] very short!<br>"
|
||||
msg += "[T.He] [T.is] very short!"
|
||||
|
||||
if (src.stat)
|
||||
msg += "<span class='warning'>[T.He] [T.is]n't responding to anything around [T.him] and seems to be asleep.</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is]n't responding to anything around [T.him] and seems to be asleep.</span>"
|
||||
if((stat == 2 || src.losebreath) && get_dist(user, src) <= 3)
|
||||
msg += "<span class='warning'>[T.He] [T.does] not appear to be breathing.</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.does] not appear to be breathing.</span>"
|
||||
if(istype(user, /mob/living/carbon/human) && !user.stat && Adjacent(user))
|
||||
user.visible_message("<b>[usr]</b> checks [src]'s pulse.", "You check [src]'s pulse.")
|
||||
spawn(15)
|
||||
@@ -301,16 +293,16 @@
|
||||
to_chat(user, "<span class='deadsay'>[T.He] [T.has] a pulse!</span>")
|
||||
|
||||
if(fire_stacks)
|
||||
msg += "[T.He] [T.is] covered in some liquid.<br>"
|
||||
msg += "[T.He] [T.is] covered in some liquid."
|
||||
if(on_fire)
|
||||
msg += "<span class='warning'>[T.He] [T.is] on fire!.</span><br>"
|
||||
msg += "<span class='warning'>[T.He] [T.is] on fire!.</span>"
|
||||
|
||||
var/ssd_msg = species.get_ssd(src)
|
||||
if(ssd_msg && (!should_have_organ("brain") || has_brain()) && stat != DEAD)
|
||||
if(!key)
|
||||
msg += "<span class='deadsay'>[T.He] [T.is] [ssd_msg]. It doesn't look like [T.he] [T.is] waking up anytime soon.</span><br>"
|
||||
msg += "<span class='deadsay'>[T.He] [T.is] [ssd_msg]. It doesn't look like [T.he] [T.is] waking up anytime soon.</span>"
|
||||
else if(!client)
|
||||
msg += "<span class='deadsay'>[T.He] [T.is] [ssd_msg].</span><br>"
|
||||
msg += "<span class='deadsay'>[T.He] [T.is] [ssd_msg].</span>"
|
||||
|
||||
var/list/wound_flavor_text = list()
|
||||
var/list/is_bleeding = list()
|
||||
@@ -323,9 +315,9 @@
|
||||
|
||||
var/obj/item/organ/external/E = organs_by_name[organ_tag]
|
||||
if(!E)
|
||||
wound_flavor_text["[organ_descriptor]"] = "<span class='warning'><b>[T.He] [T.is] missing [T.his] [organ_descriptor].</b></span><br>"
|
||||
wound_flavor_text["[organ_descriptor]"] = "<span class='warning'><b>[T.He] [T.is] missing [T.his] [organ_descriptor].</b></span>"
|
||||
else if(E.is_stump())
|
||||
wound_flavor_text["[organ_descriptor]"] = "<span class='warning'><b>[T.He] [T.has] a stump where [T.his] [organ_descriptor] should be.</b></span><br>"
|
||||
wound_flavor_text["[organ_descriptor]"] = "<span class='warning'><b>[T.He] [T.has] a stump where [T.his] [organ_descriptor] should be.</b></span>"
|
||||
else
|
||||
continue
|
||||
|
||||
@@ -334,47 +326,51 @@
|
||||
if((temp.organ_tag in hidden) && hidden[temp.organ_tag])
|
||||
continue //Organ is hidden, don't talk about it
|
||||
if(temp.status & ORGAN_DESTROYED)
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'><b>[T.He] [T.is] missing [T.his] [temp.name].</b></span><br>"
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'><b>[T.He] [T.is] missing [T.his] [temp.name].</b></span>"
|
||||
continue
|
||||
|
||||
if(!looks_synth && temp.robotic == ORGAN_ROBOT)
|
||||
if(!(temp.brute_dam + temp.burn_dam))
|
||||
wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name].<br>"
|
||||
wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name]."
|
||||
else
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a [temp.name] with [temp.get_wounds_desc()]!</span><br>"
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a [temp.name] with [temp.get_wounds_desc()]!</span>"
|
||||
continue
|
||||
else if(temp.wounds.len > 0 || temp.open)
|
||||
if(temp.is_stump() && temp.parent_organ && organs_by_name[temp.parent_organ])
|
||||
var/obj/item/organ/external/parent = organs_by_name[temp.parent_organ]
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] has [temp.get_wounds_desc()] on [T.his] [parent.name].</span><br>"
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] has [temp.get_wounds_desc()] on [T.his] [parent.name].</span>"
|
||||
else
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] has [temp.get_wounds_desc()] on [T.his] [temp.name].</span><br>"
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] has [temp.get_wounds_desc()] on [T.his] [temp.name].</span>"
|
||||
else
|
||||
wound_flavor_text["[temp.name]"] = ""
|
||||
if(temp.dislocated == 2)
|
||||
wound_flavor_text["[temp.name]"] += "<span class='warning'>[T.His] [temp.joint] is dislocated!</span><br>"
|
||||
wound_flavor_text["[temp.name]"] += "<span class='warning'>[T.His] [temp.joint] is dislocated!</span>"
|
||||
if(temp.brute_dam > temp.min_broken_damage || (temp.status & (ORGAN_BROKEN | ORGAN_MUTATED)))
|
||||
wound_flavor_text["[temp.name]"] += "<span class='warning'>[T.His] [temp.name] is dented and swollen!</span><br>"
|
||||
wound_flavor_text["[temp.name]"] += "<span class='warning'>[T.His] [temp.name] is dented and swollen!</span>"
|
||||
|
||||
if(temp.germ_level > INFECTION_LEVEL_TWO && !(temp.status & ORGAN_DEAD))
|
||||
wound_flavor_text["[temp.name]"] += "<span class='warning'>[T.His] [temp.name] looks very infected!</span><br>"
|
||||
wound_flavor_text["[temp.name]"] += "<span class='warning'>[T.His] [temp.name] looks very infected!</span>"
|
||||
else if(temp.status & ORGAN_DEAD)
|
||||
wound_flavor_text["[temp.name]"] += "<span class='warning'>[T.His] [temp.name] looks rotten!</span><br>"
|
||||
wound_flavor_text["[temp.name]"] += "<span class='warning'>[T.His] [temp.name] looks rotten!</span>"
|
||||
|
||||
if(temp.status & ORGAN_BLEEDING)
|
||||
is_bleeding["[temp.name]"] += "<span class='danger'>[T.His] [temp.name] is bleeding!</span><br>"
|
||||
is_bleeding["[temp.name]"] += "<span class='danger'>[T.His] [temp.name] is bleeding!</span>"
|
||||
|
||||
if(temp.applied_pressure == src)
|
||||
applying_pressure = "<span class='info'>[T.He] is applying pressure to [T.his] [temp.name].</span><br>"
|
||||
applying_pressure = "<span class='info'>[T.He] is applying pressure to [T.his] [temp.name].</span>"
|
||||
|
||||
for(var/limb in wound_flavor_text)
|
||||
msg += wound_flavor_text[limb]
|
||||
var/flavor = wound_flavor_text[limb]
|
||||
if(flavor)
|
||||
msg += flavor
|
||||
for(var/limb in is_bleeding)
|
||||
msg += is_bleeding[limb]
|
||||
var/blood = is_bleeding[limb]
|
||||
if(blood)
|
||||
msg += blood
|
||||
for(var/implant in get_visible_implants(0))
|
||||
msg += "<span class='danger'>[src] [T.has] \a [implant] sticking out of [T.his] flesh!</span><br>"
|
||||
msg += "<span class='danger'>[src] [T.has] \a [implant] sticking out of [T.his] flesh!</span>"
|
||||
if(digitalcamo)
|
||||
msg += "[T.He] [T.is] repulsively uncanny!<br>"
|
||||
msg += "[T.He] [T.is] repulsively uncanny!"
|
||||
|
||||
if(hasHUD(user,"security"))
|
||||
var/perpname = name
|
||||
@@ -392,8 +388,8 @@
|
||||
if(R.fields["name"] == perpname)
|
||||
criminal = R.fields["criminal"]
|
||||
|
||||
msg += "<span class = 'deptradio'>Criminal status:</span> <a href='?src=\ref[src];criminal=1'>\[[criminal]\]</a><br>"
|
||||
msg += "<span class = 'deptradio'>Security records:</span> <a href='?src=\ref[src];secrecord=`'>\[View\]</a> <a href='?src=\ref[src];secrecordadd=`'>\[Add comment\]</a><br>"
|
||||
msg += "<span class='deptradio'>Criminal status:</span> <a href='?src=\ref[src];criminal=1'>\[[criminal]\]</a>"
|
||||
msg += "<span class='deptradio'>Security records:</span> <a href='?src=\ref[src];secrecord=`'>\[View\]</a> <a href='?src=\ref[src];secrecordadd=`'>\[Add comment\]</a>"
|
||||
|
||||
if(hasHUD(user,"medical"))
|
||||
var/perpname = name
|
||||
@@ -411,15 +407,17 @@
|
||||
if (R.fields["name"] == perpname)
|
||||
medical = R.fields["p_stat"]
|
||||
|
||||
msg += "<span class = 'deptradio'>Physical status:</span> <a href='?src=\ref[src];medical=1'>\[[medical]\]</a><br>"
|
||||
msg += "<span class = 'deptradio'>Medical records:</span> <a href='?src=\ref[src];medrecord=`'>\[View\]</a> <a href='?src=\ref[src];medrecordadd=`'>\[Add comment\]</a><br>"
|
||||
msg += "<span class='deptradio'>Physical status:</span> <a href='?src=\ref[src];medical=1'>\[[medical]\]</a>"
|
||||
msg += "<span class='deptradio'>Medical records:</span> <a href='?src=\ref[src];medrecord=`'>\[View\]</a> <a href='?src=\ref[src];medrecordadd=`'>\[Add comment\]</a>"
|
||||
|
||||
|
||||
if(print_flavor_text())
|
||||
msg += "[print_flavor_text()]<br>"
|
||||
var/flavor_text = print_flavor_text()
|
||||
if(flavor_text)
|
||||
msg += "[flavor_text]"
|
||||
|
||||
msg += "*---------*</span><br>"
|
||||
msg += applying_pressure
|
||||
msg += "*---------*</span>"
|
||||
if(applying_pressure)
|
||||
msg += applying_pressure
|
||||
|
||||
var/show_descs = show_descriptors_to(user)
|
||||
if(show_descs)
|
||||
@@ -428,9 +426,9 @@
|
||||
if(pose)
|
||||
if(!findtext(pose, regex("\[.?!]$"))) // Will be zero if the last character is not a member of [.?!]
|
||||
pose = addtext(pose,".") //Makes sure all emotes end with a period.
|
||||
msg += "<br>[T.He] [pose]"
|
||||
msg += "<br>[T.He] [pose]" //<br> intentional, extra gap.
|
||||
|
||||
to_chat(user, jointext(msg, null))
|
||||
return msg
|
||||
|
||||
//Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records.
|
||||
/proc/hasHUD(mob/M as mob, hudtype)
|
||||
|
||||
@@ -151,6 +151,11 @@
|
||||
if (prob(50) && !shielded)
|
||||
Paralyse(10)
|
||||
|
||||
var/blastsoak = getsoak(null, "bomb")
|
||||
|
||||
b_loss = max(1, b_loss - blastsoak)
|
||||
f_loss = max(1, f_loss - blastsoak)
|
||||
|
||||
var/update = 0
|
||||
|
||||
// focus most of the blast on one organ
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
if(can_feel_pain())
|
||||
if(halloss >= 10) tally += (halloss / 10) //halloss shouldn't slow you down if you can't even feel it
|
||||
|
||||
var/hungry = (500 - nutrition)/5 // So overeat would be 100 and default level would be 80
|
||||
var/hungry = (MAX_NUTRITION - nutrition) / 5
|
||||
if (hungry >= 70) tally += hungry/50
|
||||
|
||||
if(istype(buckled, /obj/structure/bed/chair/wheelchair))
|
||||
|
||||
@@ -302,7 +302,7 @@
|
||||
|
||||
var/delay_length = round(active_regen_delay * species.active_regen_mult)
|
||||
if(do_after(src,delay_length))
|
||||
nutrition -= 200
|
||||
adjust_nutrition(-200)
|
||||
|
||||
for(var/obj/item/organ/I in internal_organs)
|
||||
if(I.robotic >= ORGAN_ROBOT) // No free robofix.
|
||||
@@ -345,5 +345,5 @@
|
||||
active_regen = FALSE
|
||||
else
|
||||
to_chat(src, "<span class='critical'>Your regeneration is interrupted!</span>")
|
||||
nutrition -= 75
|
||||
adjust_nutrition(-75)
|
||||
active_regen = FALSE
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
if(rad_organ && !rad_organ.is_broken())
|
||||
var/rads = radiation/25
|
||||
radiation -= rads
|
||||
nutrition += rads
|
||||
adjust_nutrition(rads)
|
||||
adjustBruteLoss(-(rads))
|
||||
adjustFireLoss(-(rads))
|
||||
adjustOxyLoss(-(rads))
|
||||
@@ -786,7 +786,7 @@
|
||||
|
||||
if(bodytemperature < species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects.
|
||||
if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up.
|
||||
nutrition -= 2
|
||||
adjust_nutrition(-2)
|
||||
var/recovery_amt = max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
|
||||
//to_world("Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]")
|
||||
// log_debug("Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]")
|
||||
@@ -809,8 +809,8 @@
|
||||
//Handle normal clothing
|
||||
for(var/obj/item/clothing/C in list(head,wear_suit,w_uniform,shoes,gloves,wear_mask))
|
||||
if(C)
|
||||
if(C.max_heat_protection_temperature && C.max_heat_protection_temperature >= temperature)
|
||||
. |= C.heat_protection
|
||||
if(C.handle_high_temperature(temperature))
|
||||
. |= C.get_heat_protection_flags()
|
||||
|
||||
//See proc/get_heat_protection_flags(temperature) for the description of this proc.
|
||||
/mob/living/carbon/human/proc/get_cold_protection_flags(temperature)
|
||||
@@ -818,8 +818,8 @@
|
||||
//Handle normal clothing
|
||||
for(var/obj/item/clothing/C in list(head,wear_suit,w_uniform,shoes,gloves,wear_mask))
|
||||
if(C)
|
||||
if(C.min_cold_protection_temperature && C.min_cold_protection_temperature <= temperature)
|
||||
. |= C.cold_protection
|
||||
if(C.handle_low_temperature(temperature))
|
||||
. |= C.get_cold_protection_flags()
|
||||
|
||||
/mob/living/carbon/human/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
|
||||
var/thermal_protection_flags = get_heat_protection_flags(temperature)
|
||||
@@ -916,15 +916,7 @@
|
||||
for(var/datum/modifier/mod in modifiers)
|
||||
if(!isnull(mod.metabolism_percent))
|
||||
nutrition_reduction *= mod.metabolism_percent
|
||||
|
||||
nutrition = max (0, nutrition - nutrition_reduction)
|
||||
|
||||
if (nutrition > 450)
|
||||
if(overeatduration < 600) //capped so people don't take forever to unfat
|
||||
overeatduration++
|
||||
else
|
||||
if(overeatduration > 1)
|
||||
overeatduration -= 2 //doubled the unfat rate
|
||||
adjust_nutrition(-nutrition_reduction)
|
||||
|
||||
// TODO: stomach and bloodstream organ.
|
||||
if(!isSynthetic())
|
||||
@@ -1371,6 +1363,10 @@
|
||||
see_in_dark = 8
|
||||
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
|
||||
for(var/datum/modifier/M in modifiers)
|
||||
if(!isnull(M.vision_flags))
|
||||
sight |= M.vision_flags
|
||||
|
||||
if(!glasses_processed && (species.get_vision_flags(src) > 0))
|
||||
sight |= species.get_vision_flags(src)
|
||||
if(!seer && !glasses_processed && seedarkness)
|
||||
@@ -1448,7 +1444,7 @@
|
||||
if(air_master.current_cycle%3==1)
|
||||
if(!(M.status_flags & GODMODE))
|
||||
M.adjustBruteLoss(5)
|
||||
nutrition += 10
|
||||
adjust_nutrition(10)
|
||||
|
||||
/mob/living/carbon/human/proc/handle_changeling()
|
||||
if(mind && mind.changeling)
|
||||
|
||||
@@ -37,13 +37,27 @@
|
||||
winset(client, "input", "text=[null]")
|
||||
|
||||
/mob/living/carbon/human/speech_bubble_appearance()
|
||||
if(isSynthetic())
|
||||
var/datum/robolimb/robo = isSynthetic()
|
||||
return robo.speech_bubble_appearance
|
||||
else
|
||||
if(species)
|
||||
return species.speech_bubble_appearance
|
||||
return "normal"
|
||||
var/sounds_synth = FALSE
|
||||
var/datum/robolimb/robo = isSynthetic() //Will get torso manufacturer
|
||||
if(robo)
|
||||
sounds_synth = looksSynthetic() //Based on lifelike robolimb vars
|
||||
|
||||
// Not lifelike and got manufacturer
|
||||
if(sounds_synth)
|
||||
return robo.speech_bubble_appearance || "synthetic"
|
||||
|
||||
// Not lifelike synth, might have synth voice box
|
||||
if(!robo)
|
||||
var/obj/item/organ/internal/V = internal_organs_by_name[O_VOICE]
|
||||
if(V?.robotic >= ORGAN_ROBOT)
|
||||
return "synthetic"
|
||||
|
||||
// Species might have custom one
|
||||
if(species.speech_bubble_appearance)
|
||||
return species.speech_bubble_appearance
|
||||
|
||||
// NORMIE
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/say_understands(var/mob/other, var/datum/language/speaking = null)
|
||||
if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
|
||||
|
||||
@@ -30,8 +30,8 @@ var/datum/species/shapeshifter/promethean/prometheans
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
|
||||
health_hud_intensity = 2
|
||||
num_alternate_languages = 3
|
||||
species_language = LANGUAGE_SOL_COMMON
|
||||
secondary_langs = list(LANGUAGE_SOL_COMMON) // For some reason, having this as their species language does not allow it to be chosen.
|
||||
species_language = LANGUAGE_PROMETHEAN
|
||||
secondary_langs = list(LANGUAGE_PROMETHEAN, LANGUAGE_SOL_COMMON) // For some reason, having this as their species language does not allow it to be chosen.
|
||||
assisted_langs = list(LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) // Prometheans are weird, let's just assume they can use basically any language.
|
||||
|
||||
breath_type = null
|
||||
@@ -180,32 +180,32 @@ var/datum/species/shapeshifter/promethean/prometheans
|
||||
if(!(H.shoes || (H.wear_suit && (H.wear_suit.body_parts_covered & FEET))))
|
||||
for(var/obj/O in T)
|
||||
O.clean_blood()
|
||||
H.nutrition = min(500, max(0, H.nutrition + rand(5, 15)))
|
||||
H.adjust_nutrition(rand(5, 15))
|
||||
if (istype(T, /turf/simulated))
|
||||
var/turf/simulated/S = T
|
||||
T.clean_blood()
|
||||
S.dirt = 0
|
||||
H.nutrition = min(500, max(0, H.nutrition + rand(10, 20)))
|
||||
H.adjust_nutrition(rand(10, 20))
|
||||
if(H.clean_blood(1))
|
||||
H.nutrition = min(500, max(0, H.nutrition + rand(5, 15)))
|
||||
H.adjust_nutrition(rand(5, 15))
|
||||
if(H.r_hand)
|
||||
if(H.r_hand.clean_blood())
|
||||
H.nutrition = min(500, max(0, H.nutrition + rand(5, 15)))
|
||||
H.adjust_nutrition(rand(5, 15))
|
||||
if(H.l_hand)
|
||||
if(H.l_hand.clean_blood())
|
||||
H.nutrition = min(500, max(0, H.nutrition + rand(5, 15)))
|
||||
H.adjust_nutrition(rand(5, 15))
|
||||
if(H.head)
|
||||
if(H.head.clean_blood())
|
||||
H.update_inv_head(0)
|
||||
H.nutrition = min(500, max(0, H.nutrition + rand(5, 15)))
|
||||
H.adjust_nutrition(rand(5, 15))
|
||||
if(H.wear_suit)
|
||||
if(H.wear_suit.clean_blood())
|
||||
H.update_inv_wear_suit(0)
|
||||
H.nutrition = min(500, max(0, H.nutrition + rand(5, 15)))
|
||||
H.adjust_nutrition(rand(5, 15))
|
||||
if(H.w_uniform)
|
||||
if(H.w_uniform.clean_blood())
|
||||
H.update_inv_w_uniform(0)
|
||||
H.nutrition = min(500, max(0, H.nutrition + rand(5, 15)))
|
||||
H.adjust_nutrition(rand(5, 15))
|
||||
//End cleaning code.
|
||||
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
@@ -288,8 +288,7 @@ var/datum/species/shapeshifter/promethean/prometheans
|
||||
if(ToxReg)
|
||||
strain_negation += to_pay * max(0, (1 - ToxReg.get_strain_percent()))
|
||||
|
||||
H.nutrition -= (3 * nutrition_cost) //Costs Nutrition when damage is being repaired, corresponding to the amount of damage being repaired.
|
||||
H.nutrition = max(0, H.nutrition) //Ensure it's not below 0.
|
||||
H.adjust_nutrition(-(3 * nutrition_cost)) // Costs Nutrition when damage is being repaired, corresponding to the amount of damage being repaired.
|
||||
|
||||
var/agony_to_apply = ((1 / starve_mod) * (nutrition_cost - strain_negation)) //Regenerating damage causes minor pain over time, if the organs responsible are nonexistant or too high on strain. Small injures will be no issue, large ones will cause problems.
|
||||
|
||||
|
||||
@@ -586,11 +586,9 @@
|
||||
if(isturf(H.loc)) //else, there's considered to be no light
|
||||
var/turf/T = H.loc
|
||||
light_amount = T.get_lumcount() * 10
|
||||
H.nutrition += light_amount
|
||||
H.adjust_nutrition(light_amount)
|
||||
H.shock_stage -= light_amount
|
||||
|
||||
if(H.nutrition > 450)
|
||||
H.nutrition = 450
|
||||
if(light_amount >= 3) //if there's enough light, heal
|
||||
H.adjustBruteLoss(-(round(light_amount/2)))
|
||||
H.adjustFireLoss(-(round(light_amount/2)))
|
||||
|
||||
@@ -121,9 +121,7 @@
|
||||
|
||||
if(check_alien_ability(50,1,O_RESIN))
|
||||
visible_message("<span class='alium'><B>[src] has planted some alien weeds!</B></span>")
|
||||
var/obj/O = new /obj/effect/alien/weeds/node(loc)
|
||||
if(O)
|
||||
O.color = "#321D37"
|
||||
new /obj/effect/alien/weeds/node(get_turf(src), "#321D37")
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/Spit(var/atom/A)
|
||||
|
||||
@@ -731,7 +731,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
|
||||
var/obj/item/clothing/suit/suit = wear_suit
|
||||
var/suit_sprite
|
||||
|
||||
if(suit.index)
|
||||
if(istype(suit) && suit.index)
|
||||
suit_sprite = "[INV_SUIT_DEF_ICON]_[suit.index].dmi"
|
||||
else if(istype(suit, /obj/item/clothing) && !isnull(suit.update_icon_define))
|
||||
suit_sprite = suit.update_icon_define
|
||||
|
||||
@@ -189,6 +189,13 @@
|
||||
see_invisible = SEE_INVISIBLE_NOLIGHTING
|
||||
else
|
||||
see_invisible = initial(see_invisible)
|
||||
|
||||
sight = initial(sight)
|
||||
|
||||
for(var/datum/modifier/M in modifiers)
|
||||
if(!isnull(M.vision_flags))
|
||||
sight |= M.vision_flags
|
||||
|
||||
return
|
||||
|
||||
/mob/living/proc/handle_hud_icons()
|
||||
|
||||
@@ -1039,7 +1039,7 @@ default behaviour is:
|
||||
if(getBruteLoss() < 50)
|
||||
adjustBruteLoss(3)
|
||||
else
|
||||
nutrition -= 40
|
||||
adjust_nutrition(-40)
|
||||
adjustToxLoss(-3)
|
||||
|
||||
spawn(350)
|
||||
@@ -1302,6 +1302,9 @@ default behaviour is:
|
||||
/mob/living/proc/needs_to_breathe()
|
||||
return !isSynthetic()
|
||||
|
||||
/mob/living/proc/adjust_nutrition(amount)
|
||||
nutrition = between(0, nutrition + amount, max_nutrition)
|
||||
|
||||
/mob/living/vv_get_header()
|
||||
. = ..()
|
||||
. += {"
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
var/brainloss = 0 //'Retardation' damage caused by someone hitting you in the head with a bible or being infected with brainrot.
|
||||
var/halloss = 0 //Hallucination damage. 'Fake' damage obtained through hallucinating or the holodeck. Sleeping should cause it to wear off.
|
||||
|
||||
var/nutrition = 400
|
||||
var/max_nutrition = MAX_NUTRITION
|
||||
|
||||
var/hallucination = 0 //Directly affects how long a mob will hallucinate for
|
||||
var/list/atom/hallucinations = list() //A list of hallucinated people that try to attack the mob. See /obj/effect/fake_attacker in hallucinations.dm
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
return !P.can_hit_target(src, P.permutated, src == P.original, TRUE)
|
||||
return (!mover.density || !density || lying)
|
||||
|
||||
/mob/CanZASPass(turf/T, is_zone)
|
||||
return ATMOS_PASS_YES
|
||||
|
||||
/mob/living/SelfMove(turf/n, direct)
|
||||
// If on walk intent, don't willingly step into hazardous tiles.
|
||||
// Unless the walker is confused.
|
||||
|
||||
@@ -259,8 +259,7 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
//Handle nonverbal languages here
|
||||
for(var/datum/multilingual_say_piece/S in message_pieces)
|
||||
if(S.speaking.flags & NONVERBAL)
|
||||
if(prob(30))
|
||||
custom_emote(1, "[pick(S.speaking.signlang_verb)].")
|
||||
custom_emote(1, "[pick(S.speaking.signlang_verb)].")
|
||||
|
||||
//These will contain the main receivers of the message
|
||||
var/list/listening = list()
|
||||
|
||||
@@ -1,42 +1,39 @@
|
||||
/mob/living/silicon/ai/examine(mob/user)
|
||||
if(!..(user))
|
||||
return
|
||||
. = ..()
|
||||
|
||||
var/msg = ""
|
||||
if (src.stat == DEAD)
|
||||
msg += "<span class='deadsay'>It appears to be powered-down.</span>\n"
|
||||
. += "<span class='deadsay'>It appears to be powered-down.</span>"
|
||||
else
|
||||
msg += "<span class='warning'>"
|
||||
if (src.getBruteLoss())
|
||||
if (src.getBruteLoss() < 30)
|
||||
msg += "It looks slightly dented.\n"
|
||||
. += "<span class='warning'>It looks slightly dented.</span>"
|
||||
else
|
||||
msg += "<B>It looks severely dented!</B>\n"
|
||||
. += "<span class='warning'><B>It looks severely dented!</B></span>"
|
||||
if (src.getFireLoss())
|
||||
if (src.getFireLoss() < 30)
|
||||
msg += "It looks slightly charred.\n"
|
||||
. += "<span class='warning'>It looks slightly charred.</span>"
|
||||
else
|
||||
msg += "<B>Its casing is melted and heat-warped!</B>\n"
|
||||
. += "<span class='warning'><B>Its casing is melted and heat-warped!</B></span>"
|
||||
if (src.getOxyLoss() && (aiRestorePowerRoutine != 0 && !APU_power))
|
||||
if (src.getOxyLoss() > 175)
|
||||
msg += "<B>It seems to be running on backup power. Its display is blinking a \"BACKUP POWER CRITICAL\" warning.</B>\n"
|
||||
. += "<span class='warning'><B>It seems to be running on backup power. Its display is blinking a \"BACKUP POWER CRITICAL\" warning.</B></span>"
|
||||
else if(src.getOxyLoss() > 100)
|
||||
msg += "<B>It seems to be running on backup power. Its display is blinking a \"BACKUP POWER LOW\" warning.</B>\n"
|
||||
. += "<span class='warning'><B>It seems to be running on backup power. Its display is blinking a \"BACKUP POWER LOW\" warning.</B></span>"
|
||||
else
|
||||
msg += "It seems to be running on backup power.\n"
|
||||
. += "<span class='warning'>It seems to be running on backup power.</span>"
|
||||
|
||||
if (src.stat == UNCONSCIOUS)
|
||||
msg += "It is non-responsive and displaying the text: \"RUNTIME: Sensory Overload, stack 26/3\".\n"
|
||||
msg += "</span>"
|
||||
. += "<span class='warning'>It is non-responsive and displaying the text: \"RUNTIME: Sensory Overload, stack 26/3\".</span>"
|
||||
|
||||
if(deployed_shell)
|
||||
msg += "The wireless networking light is blinking.\n"
|
||||
msg += "*---------*"
|
||||
. += "The wireless networking light is blinking."
|
||||
|
||||
. += "*---------*"
|
||||
|
||||
if(hardware && (hardware.owner == src))
|
||||
msg += "<br>"
|
||||
msg += hardware.get_examine_desc()
|
||||
to_chat(user,msg)
|
||||
. += hardware.get_examine_desc()
|
||||
|
||||
user.showLaws(src)
|
||||
return
|
||||
|
||||
/mob/proc/showLaws(var/mob/living/silicon/S)
|
||||
return
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
/mob/living/silicon/pai/examine(mob/user)
|
||||
..(user, infix = ", personal AI")
|
||||
. = ..(user, infix = ", personal AI")
|
||||
|
||||
var/msg = ""
|
||||
switch(src.stat)
|
||||
if(CONSCIOUS)
|
||||
if(!src.client) msg += "\nIt appears to be in stand-by mode." //afk
|
||||
if(UNCONSCIOUS) msg += "\n<span class='warning'>It doesn't seem to be responding.</span>"
|
||||
if(DEAD) msg += "\n<span class='deadsay'>It looks completely unsalvageable.</span>"
|
||||
msg += "\n*---------*"
|
||||
if(!src.client) . += "It appears to be in stand-by mode." //afk
|
||||
if(UNCONSCIOUS) . += "<span class='warning'>It doesn't seem to be responding.</span>"
|
||||
if(DEAD) . += "<span class='deadsay'>It looks completely unsalvageable.</span>"
|
||||
. += "*---------*"
|
||||
|
||||
if(print_flavor_text()) msg += "\n[print_flavor_text()]\n"
|
||||
if(print_flavor_text()) . += "\n[print_flavor_text()]\n"
|
||||
|
||||
if (pose)
|
||||
if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 )
|
||||
if(!findtext(pose, regex("\[.?!]$"))) // Will be zero if the last character is not a member of [.?!]
|
||||
pose = addtext(pose,".") //Makes sure all emotes end with a period.
|
||||
msg += "\nIt is [pose]"
|
||||
|
||||
to_chat(user,msg)
|
||||
. += "<br>It is [pose]" //Extra <br> intentional
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
var/force_holder = null //
|
||||
|
||||
/obj/item/weapon/gripper/examine(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(wrapped)
|
||||
to_chat(user, "<span class='notice'>\The [src] is holding \the [wrapped].</span>")
|
||||
wrapped.examine(user)
|
||||
. += "<span class='notice'>\The [src] is holding \the [wrapped].</span>"
|
||||
. += wrapped.examine(user)
|
||||
|
||||
/obj/item/weapon/gripper/CtrlClick(mob/user)
|
||||
drop_item()
|
||||
|
||||
@@ -63,9 +63,9 @@
|
||||
visible_message("\The [src] voices a strident beep, indicating a drone chassis is prepared.")
|
||||
|
||||
/obj/machinery/drone_fabricator/examine(mob/user)
|
||||
..(user)
|
||||
. = ..()
|
||||
if(produce_drones && drone_progress >= 100 && istype(user,/mob/observer/dead) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
to_chat(user, "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>")
|
||||
. += "<br><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>"
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/create_drone(var/client/player)
|
||||
|
||||
|
||||
@@ -1,46 +1,41 @@
|
||||
/mob/living/silicon/robot/examine(mob/user)
|
||||
var/custom_infix = custom_name ? ", [modtype] [braintype]" : ""
|
||||
..(user, infix = custom_infix)
|
||||
. = ..(user, infix = custom_infix)
|
||||
|
||||
var/msg = ""
|
||||
msg += "<span class='warning'>"
|
||||
if (src.getBruteLoss())
|
||||
if (src.getBruteLoss() < 75)
|
||||
msg += "It looks slightly dented.\n"
|
||||
. += "<span class='warning'>It looks slightly dented.</span>"
|
||||
else
|
||||
msg += "<B>It looks severely dented!</B>\n"
|
||||
. += "<span class='warning'><B>It looks severely dented!</B></span>"
|
||||
if (src.getFireLoss())
|
||||
if (src.getFireLoss() < 75)
|
||||
msg += "It looks slightly charred.\n"
|
||||
. += "<span class='warning'>It looks slightly charred.</span>"
|
||||
else
|
||||
msg += "<B>It looks severely burnt and heat-warped!</B>\n"
|
||||
msg += "</span>"
|
||||
. += "<span class='warning'><B>It looks severely burnt and heat-warped!</B></span>"
|
||||
|
||||
if(opened)
|
||||
msg += "<span class='warning'>Its cover is open and the power cell is [cell ? "installed" : "missing"].</span>\n"
|
||||
. += "<span class='warning'>Its cover is open and the power cell is [cell ? "installed" : "missing"].</span>"
|
||||
else
|
||||
msg += "Its cover is closed.\n"
|
||||
. += "Its cover is closed."
|
||||
|
||||
if(!has_power)
|
||||
msg += "<span class='warning'>It appears to be running on backup power.</span>\n"
|
||||
. += "<span class='warning'>It appears to be running on backup power.</span>"
|
||||
|
||||
switch(src.stat)
|
||||
if(CONSCIOUS)
|
||||
if(shell)
|
||||
msg += "It appears to be an [deployed ? "active" : "empty"] AI shell.\n"
|
||||
. += "It appears to be an [deployed ? "active" : "empty"] AI shell."
|
||||
else if(!src.client)
|
||||
msg += "It appears to be in stand-by mode.\n" //afk
|
||||
if(UNCONSCIOUS) msg += "<span class='warning'>It doesn't seem to be responding.</span>\n"
|
||||
if(DEAD) msg += "<span class='deadsay'>It looks completely unsalvageable.</span>\n"
|
||||
msg += "*---------*"
|
||||
. += "It appears to be in stand-by mode." //afk
|
||||
if(UNCONSCIOUS) . += "<span class='warning'>It doesn't seem to be responding.</span>"
|
||||
if(DEAD) . += "<span class='deadsay'>It looks completely unsalvageable.</span>"
|
||||
. += "*---------*"
|
||||
|
||||
if(print_flavor_text()) msg += "\n[print_flavor_text()]\n"
|
||||
if(print_flavor_text()) . += "<br>[print_flavor_text()]"
|
||||
|
||||
if (pose)
|
||||
if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 )
|
||||
if(!findtext(pose, regex("\[.?!]$"))) // Will be zero if the last character is not a member of [.?!]
|
||||
pose = addtext(pose,".") //Makes sure all emotes end with a period.
|
||||
msg += "\nIt is [pose]"
|
||||
. += "<br>It is [pose]" //Extra <br> intentional
|
||||
|
||||
to_chat(user,msg)
|
||||
user.showLaws(src)
|
||||
return
|
||||
|
||||
@@ -430,10 +430,9 @@
|
||||
max_doors = 5
|
||||
|
||||
/obj/item/weapon/inflatable_dispenser/examine(var/mob/user)
|
||||
if(!..(user))
|
||||
return
|
||||
to_chat(user, "It has [stored_walls] wall segment\s and [stored_doors] door segment\s stored.")
|
||||
to_chat(user, "It is set to deploy [mode ? "doors" : "walls"]")
|
||||
. = ..()
|
||||
. += "It has [stored_walls] wall segment\s and [stored_doors] door segment\s stored."
|
||||
. += "It is set to deploy [mode ? "doors" : "walls"]"
|
||||
|
||||
/obj/item/weapon/inflatable_dispenser/attack_self()
|
||||
mode = !mode
|
||||
|
||||
@@ -336,6 +336,8 @@
|
||||
next_alarm_notice = world.time + SecondsToTicks(10)
|
||||
if(alarm.hidden)
|
||||
return
|
||||
if(alarm.origin && !(get_z(alarm.origin) in using_map.get_map_levels(get_z(src), TRUE)))
|
||||
return
|
||||
|
||||
var/list/alarms = queued_alarms[alarm_handler]
|
||||
if(was_raised)
|
||||
|
||||
@@ -72,6 +72,23 @@
|
||||
if(istype(O, /obj/item/weapon/material/knife))
|
||||
harvest(user)
|
||||
|
||||
if(user.a_intent == I_HELP && harvest_tool && istype(O, harvest_tool) && stat != DEAD)
|
||||
if(world.time > (harvest_recent + harvest_cooldown))
|
||||
livestock_harvest(O, user)
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] can't be [harvest_verb] so soon.</span>")
|
||||
return
|
||||
|
||||
if(can_tame(O, user))
|
||||
to_chat(user, "<span class='notice'>You offer \the [src] \the [O].</span>")
|
||||
if(tame_prob(O, user))
|
||||
to_chat(user, "<span class='notice'>\The [src] appears to accept \the [O], seemingly calmed.</span>")
|
||||
do_tame(O,user)
|
||||
else
|
||||
fail_tame(O, user)
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
42
code/modules/mob/living/simple_mob/harvesting.dm
Normal file
42
code/modules/mob/living/simple_mob/harvesting.dm
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
/mob/living/simple_mob
|
||||
// What do you hit the mob with (on help) to get something from it?
|
||||
var/obj/harvest_tool
|
||||
// How long do we have to wait until it's harvestable again?
|
||||
var/harvest_cooldown = 10 MINUTES
|
||||
// How long does it take to harvest?
|
||||
var/harvest_delay = 30 SECONDS
|
||||
// What world.time was the last harvest?
|
||||
var/harvest_recent = 0
|
||||
// How many times can we roll at max on the chance table?
|
||||
var/harvest_per_hit = 1
|
||||
// Verb for harvesting. "sheared" "clipped" etc.
|
||||
var/harvest_verb = "harvested"
|
||||
// Associative list of paths and their chances. path = straws in the lot
|
||||
var/list/harvest_results
|
||||
|
||||
/mob/living/simple_mob/examine(mob/user)
|
||||
. = ..()
|
||||
if(user && harvest_tool && (get_dist(user, src) <= 3))
|
||||
. += "<span class='notice'>\The [src] can be [harvest_verb] with a [initial(harvest_tool.name)] every [round(harvest_cooldown, 0.1)] minutes.</span>"
|
||||
var/time_to_harvest = (harvest_recent + harvest_cooldown) - world.time
|
||||
if(time_to_harvest > 0)
|
||||
. += "<span class='notice'>It can be [harvest_verb] in [time_to_harvest / (1 MINUTE)] second(s).</span>"
|
||||
else
|
||||
. += "<span class='notice'>It can be [harvest_verb] now.</span>"
|
||||
|
||||
/mob/living/simple_mob/proc/livestock_harvest(var/obj/item/tool, var/mob/living/user)
|
||||
if(!LAZYLEN(harvest_results)) // Might be a unique interaction of an object using the proc to do something weird, or just someone's a donk.
|
||||
harvest_recent = world.time
|
||||
return
|
||||
|
||||
if(istype(tool, harvest_tool)) // Sanity incase something incorrect is passed in.
|
||||
harvest_recent = world.time
|
||||
|
||||
var/max_harvests = rand(1,harvest_per_hit)
|
||||
|
||||
for(var/I = 1 to max_harvests)
|
||||
var/new_path = pickweight(harvest_results)
|
||||
new new_path(get_turf(user))
|
||||
|
||||
return
|
||||
@@ -100,6 +100,12 @@
|
||||
|
||||
say_list_type = /datum/say_list/spider
|
||||
|
||||
tame_items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/xenomeat = 10,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/crab = 40,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat = 20
|
||||
)
|
||||
|
||||
var/poison_type = "spidertoxin" // The reagent that gets injected when it attacks.
|
||||
var/poison_chance = 10 // Chance for injection to occur.
|
||||
var/poison_per_bite = 5 // Amount added per injection.
|
||||
|
||||
@@ -45,6 +45,11 @@
|
||||
poison_per_bite = 0.5
|
||||
poison_type = "phoron"
|
||||
|
||||
tame_items = list(
|
||||
/obj/item/weapon/tank/phoron = 20,
|
||||
/obj/item/stack/material/phoron = 30
|
||||
)
|
||||
|
||||
var/exploded = FALSE
|
||||
var/explosion_dev_range = 1
|
||||
var/explosion_heavy_range = 2
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
/mob/living/simple_mob/animal/passive/crab/sif/Initialize()
|
||||
..()
|
||||
adjust_scale(rand(5,15) / 10)
|
||||
adjust_scale(rand(5,12) / 10)
|
||||
|
||||
// Meat!
|
||||
|
||||
|
||||
@@ -166,11 +166,15 @@
|
||||
/mob/living/simple_mob/animal/passive/fish/icebass/update_icon()
|
||||
overlays.Cut()
|
||||
..()
|
||||
|
||||
if(!dorsal_image)
|
||||
dorsal_image = image(icon, "[icon_state]_mask-body")
|
||||
if(!belly_image)
|
||||
belly_image = image(icon, "[icon_state]_mask-belly")
|
||||
|
||||
dorsal_image.icon_state = "[icon_state]_mask-body"
|
||||
belly_image.icon_state = "[icon_state]_mask-belly"
|
||||
|
||||
dorsal_image.color = dorsal_color
|
||||
belly_image.color = belly_color
|
||||
|
||||
@@ -237,6 +241,8 @@
|
||||
if(!head_image)
|
||||
head_image = image(icon, "[icon_state]_mask")
|
||||
|
||||
head_image.icon_state = "[icon_state]_mask"
|
||||
|
||||
head_image.color = head_color
|
||||
|
||||
overlays += head_image
|
||||
|
||||
@@ -90,9 +90,9 @@
|
||||
my_headset = null
|
||||
|
||||
/mob/living/simple_mob/animal/passive/bird/parrot/examine(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(my_headset)
|
||||
to_chat(user, "It is wearing \a [my_headset].")
|
||||
. += "It is wearing \a [my_headset]."
|
||||
|
||||
/mob/living/simple_mob/animal/passive/bird/parrot/Initialize()
|
||||
if(my_headset)
|
||||
|
||||
@@ -40,6 +40,23 @@
|
||||
say_list_type = /datum/say_list/diyaab
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/retaliate/cooperative
|
||||
|
||||
// What do you hit the mob with (on help) to get something from it?
|
||||
harvest_tool = /obj/item/weapon/tool/wirecutters
|
||||
// How long do we have to wait until it's harvestable again?
|
||||
harvest_cooldown = 10 MINUTES
|
||||
// How long does it take to harvest?
|
||||
harvest_delay = 30 SECONDS
|
||||
// What world.time was the last harvest?
|
||||
harvest_recent = 0
|
||||
// How many times do we roll on the chance table?
|
||||
harvest_per_hit = 1
|
||||
// Verb for harvesting. "sheared" "clipped" etc.
|
||||
harvest_verb = "sheared"
|
||||
// Associative list of paths and their chances. path = straws in the lot
|
||||
harvest_results = list(
|
||||
/obj/item/stack/material/cloth/diyaab = 10
|
||||
)
|
||||
|
||||
/datum/say_list/diyaab
|
||||
speak = list("Awrr?", "Aowrl!", "Worrl.")
|
||||
emote_see = list("sniffs the air cautiously","looks around")
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
Family units have been observed to form gangs and scavenge from Sivian domeciles and \
|
||||
various food transports during stressful months. \
|
||||
It is advised to seal and hide any form of food near even lone individuals, as they will become \
|
||||
increasingly aggressive."
|
||||
increasingly aggressive in order to acquire it."
|
||||
value = CATALOGUER_REWARD_EASY
|
||||
|
||||
/mob/living/simple_mob/animal/sif/duck
|
||||
@@ -38,6 +38,11 @@
|
||||
attack_edge = 1 // Razor-edged wings, and 'claws' made for digging through ice.
|
||||
attacktext = list("nipped", "bit", "cut", "clawed")
|
||||
|
||||
tame_items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/sliceable/bread = 90,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/slice/bread = 25
|
||||
)
|
||||
|
||||
say_list_type = /datum/say_list/duck
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/retaliate/cooperative
|
||||
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
|
||||
attacktext = list("bit", "buffeted", "slashed")
|
||||
|
||||
tame_items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown = 90,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/crab = 10,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat = 5
|
||||
)
|
||||
|
||||
say_list_type = /datum/say_list/glitterfly
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive/glitterfly
|
||||
|
||||
@@ -81,6 +87,17 @@
|
||||
/mob/living/simple_mob/animal/sif/glitterfly/rare/Initialize()
|
||||
..()
|
||||
|
||||
/mob/living/simple_mob/animal/sif/glitterfly/unique_tame_check(var/obj/O, var/mob/user)
|
||||
. = ..()
|
||||
|
||||
if(.)
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown))
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = O
|
||||
|
||||
if(G.seed && G.seed.kitchen_tag == "berries")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/say_list/glitterfly
|
||||
speak = list("Pi..","Po...", "Pa...")
|
||||
emote_see = list("vibrates","flutters", "twirls")
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
icon_state = "bigcat"
|
||||
icon_living = "bigcat"
|
||||
icon_dead = "bigcat_dead"
|
||||
icon_rest = "bigcat_rest"
|
||||
icon_rest = "bigcat_sleep"
|
||||
icon = 'icons/mob/64x64.dmi'
|
||||
|
||||
default_pixel_x = -16
|
||||
@@ -42,7 +42,7 @@
|
||||
movement_cooldown = 1
|
||||
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 25
|
||||
melee_damage_upper = 20
|
||||
attack_armor_pen = 40
|
||||
base_attack_cooldown = 2 SECONDS
|
||||
attacktext = list("gouged", "bit", "cut", "clawed", "whipped")
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
special_attack_min_range = 0
|
||||
special_attack_max_range = 4
|
||||
special_attack_cooldown = 30 SECONDS
|
||||
special_attack_cooldown = 1 MINUTE
|
||||
|
||||
// Players have 2 seperate cooldowns for these, while the AI must choose one. Both respect special_attack_cooldown
|
||||
var/last_strike_time = 0
|
||||
@@ -108,11 +108,11 @@
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.get_active_hand())
|
||||
var/obj/item/I = H.get_active_hand()
|
||||
if(I.force >= 1.20 * melee_damage_upper)
|
||||
if(I.force <= 1.25 * melee_damage_upper)
|
||||
return TRUE
|
||||
else if(istype(L, /mob/living/simple_mob))
|
||||
var/mob/living/simple_mob/S = L
|
||||
if(S.melee_damage_upper > 1.20 * melee_damage_upper)
|
||||
if(S.melee_damage_upper > 1.5 * melee_damage_upper)
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_mob/animal/sif/kururak/handle_special()
|
||||
@@ -122,7 +122,7 @@
|
||||
|
||||
/mob/living/simple_mob/animal/sif/kururak/apply_melee_effects(atom/A) // Only gains instinct.
|
||||
instinct += rand(1, 2)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/animal/sif/kururak/should_special_attack(atom/A)
|
||||
return has_modifier_of_type(/datum/modifier/ace)
|
||||
@@ -136,6 +136,8 @@
|
||||
set_AI_busy(TRUE)
|
||||
rending_strike(A)
|
||||
set_AI_busy(FALSE)
|
||||
a_intent = I_HURT
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/animal/sif/kururak/verb/do_flash()
|
||||
set category = "Abilities"
|
||||
@@ -186,11 +188,8 @@
|
||||
flash_strength *= H.species.flash_mod
|
||||
if(flash_strength > 0)
|
||||
to_chat(H, span("alien","You are disoriented by \the [src]!"))
|
||||
H.Confuse(flash_strength + 5)
|
||||
H.Blind(flash_strength)
|
||||
H.eye_blurry = max(H.eye_blurry, flash_strength + 5)
|
||||
H.flash_eyes()
|
||||
H.adjustHalLoss(flash_strength / 5)
|
||||
H.apply_damage(flash_strength * H.species.flash_burn/5, BURN, BP_HEAD, 0, 0, "Photon burns")
|
||||
|
||||
else if(issilicon(L))
|
||||
@@ -280,9 +279,11 @@
|
||||
visible_message(span("danger","\The [src] rakes its claws against \the [A]."))
|
||||
var/obj/mecha/M = A
|
||||
M.take_damage(damage_to_apply)
|
||||
if(prob(3) && do_after(src, 5))
|
||||
visible_message(span("critical","\The [src]'s strike ripped \the [M]'s access hatch open, allowing it to drag [M.occupant] out!"))
|
||||
M.go_out()
|
||||
if(prob(3))
|
||||
visible_message(span("critical","\The [src] begins digging its claws into \the [M]'s hatch!"))
|
||||
if(do_after(src, 1 SECOND))
|
||||
visible_message(span("critical","\The [src] rips \the [M]'s access hatch open, dragging [M.occupant] out!"))
|
||||
M.go_out()
|
||||
|
||||
else
|
||||
A.attack_generic(src, damage_to_apply, "rakes its claws against") // Well it's not a mob, and it's not a mech.
|
||||
@@ -329,6 +330,15 @@
|
||||
else
|
||||
remove_modifiers_of_type(/datum/modifier/ace)
|
||||
|
||||
/mob/living/simple_mob/animal/sif/kururak/hibernate/Initialize()
|
||||
..()
|
||||
lay_down()
|
||||
instinct = 0
|
||||
|
||||
/*
|
||||
* Kururak AI
|
||||
*/
|
||||
|
||||
/datum/ai_holder/simple_mob/intentional/kururak
|
||||
hostile = FALSE
|
||||
retaliate = TRUE
|
||||
@@ -359,6 +369,8 @@
|
||||
else
|
||||
hostile = initial(hostile)
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/ai_holder/simple_mob/intentional/kururak/pre_special_attack(atom/A)
|
||||
holder.a_intent = I_HURT
|
||||
if(isliving(A))
|
||||
@@ -378,9 +390,16 @@
|
||||
else if(istype(A, /obj/mecha))
|
||||
holder.a_intent = I_GRAB
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/ai_holder/simple_mob/intentional/kururak/post_special_attack(atom/A)
|
||||
holder.a_intent = I_HURT
|
||||
return ..()
|
||||
|
||||
/datum/ai_holder/simple_mob/intentional/kururak/post_melee_attack()
|
||||
if(holder.has_modifier_of_type(/datum/modifier/ace))
|
||||
request_help()
|
||||
return ..()
|
||||
|
||||
// Kururak Ace modifier, given to the one with the highest Instinct.
|
||||
|
||||
|
||||
@@ -187,6 +187,7 @@
|
||||
desc = "What appears to be an oversized rodent with hands. This one has a curious look in its eyes."
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/intentional/sakimm
|
||||
randomize_size = FALSE // Most likely to have a hat.
|
||||
melee_attack_delay = 0 // For some reason, having a delay makes item pick-up not work.
|
||||
|
||||
/datum/ai_holder/simple_mob/intentional/sakimm
|
||||
hostile = FALSE
|
||||
@@ -256,14 +257,10 @@
|
||||
|
||||
for(var/possible_target in possible_targets)
|
||||
var/atom/A = possible_target
|
||||
if(found(A))
|
||||
. = list(A)
|
||||
break
|
||||
if(istype(A, /mob/living) && !can_pick_mobs)
|
||||
continue
|
||||
if(can_attack(A)) // Can we attack it?
|
||||
. += A
|
||||
continue
|
||||
|
||||
for(var/obj/item/I in .)
|
||||
last_search = world.time
|
||||
|
||||
@@ -44,6 +44,12 @@
|
||||
player_msg = "You have the ability to <b>berserk at will</b>, which will grant strong physical bonuses for \
|
||||
a short period of time, however it will tire you and you will be much weaker for awhile after it expires."
|
||||
|
||||
tame_items = list(
|
||||
/obj/item/organ = 70,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/crab = 30,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat = 20
|
||||
)
|
||||
|
||||
say_list_type = /datum/say_list/savik
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/savik
|
||||
|
||||
@@ -57,6 +63,12 @@
|
||||
if(health <= (maxHealth * 0.5)) // At half health, and fighting someone currently.
|
||||
berserk()
|
||||
|
||||
/mob/living/simple_mob/animal/sif/savik/fail_tame(var/obj/O, var/mob/user)
|
||||
..()
|
||||
|
||||
if(prob(30)) // They don't like people messing with them and their food.
|
||||
berserk()
|
||||
|
||||
/datum/ai_holder/simple_mob/savik
|
||||
mauling = TRUE
|
||||
|
||||
|
||||
@@ -93,7 +93,9 @@
|
||||
rally_pack()
|
||||
return ..()
|
||||
|
||||
|
||||
// These ones only retaliate. Used for a PoI.
|
||||
// These ones only retaliate. Used for PoIs.
|
||||
/mob/living/simple_mob/animal/sif/shantak/retaliate
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/retaliate
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/retaliate
|
||||
|
||||
/mob/living/simple_mob/animal/sif/shantak/leader/autofollow/retaliate
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/retaliate
|
||||
|
||||
@@ -2,4 +2,9 @@
|
||||
/mob/living/simple_mob/animal/sif
|
||||
minbodytemp = 175
|
||||
cold_resist = 0.75
|
||||
heat_resist = -0.5
|
||||
heat_resist = -0.5
|
||||
|
||||
tame_items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/crab = 20,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat = 10
|
||||
)
|
||||
|
||||
@@ -89,6 +89,11 @@
|
||||
firing_lanes = TRUE // But not your buddies!
|
||||
conserve_ammo = TRUE // And don't go wasting bullets!
|
||||
|
||||
/datum/ai_holder/simple_mob/merc/ranged/sniper
|
||||
vision_range = 14 // We're a person with a long-ranged gun.
|
||||
|
||||
/datum/ai_holder/simple_mob/merc/ranged/sniper/max_range(atom/movable/AM)
|
||||
return holder.ICheckRangedAttack(AM) ? 14 : 1
|
||||
|
||||
////////////////////////////////
|
||||
// Melee
|
||||
@@ -174,6 +179,27 @@
|
||||
base_attack_cooldown = 5 // Two attacks a second or so.
|
||||
reload_max = 20
|
||||
|
||||
// Rifles
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/rifle
|
||||
icon_state = "syndicateranged_rifle"
|
||||
icon_living = "syndicateranged_rifle"
|
||||
|
||||
loot_list = list(/obj/item/weapon/gun/projectile/automatic/z8 = 100)
|
||||
|
||||
projectilesound = 'sound/weapons/Gunshot_heavy.ogg'
|
||||
projectiletype = /obj/item/projectile/bullet/rifle/a762
|
||||
projectile_dispersion = 8
|
||||
projectile_accuracy = -15
|
||||
base_attack_cooldown = 5
|
||||
reload_max = 30
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/rifle/mag
|
||||
loot_list = list(/obj/item/weapon/gun/magnetic/railgun/flechette = 100)
|
||||
projectiletype = /obj/item/projectile/bullet/magnetic/flechette
|
||||
|
||||
projectilesound = 'sound/weapons/rapidslice.ogg'
|
||||
reload_max = 10
|
||||
|
||||
// Laser Rifle
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/laser
|
||||
icon_state = "syndicateranged_laser"
|
||||
@@ -214,6 +240,89 @@
|
||||
projectile_accuracy = -40
|
||||
special_attack_charges = 5
|
||||
|
||||
// Technician, also kind of a miniboss. Carries a dartgun and manhack launcher.
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/technician
|
||||
icon_state = "syndicateranged_technician"
|
||||
icon_living = "syndicateranged_technician"
|
||||
projectiletype = /obj/item/projectile/fake_syringe/poison // Toxin dart.
|
||||
projectilesound = 'sound/weapons/Gunshot_old.ogg'
|
||||
|
||||
loot_list = list(/obj/item/weapon/gun/projectile/dartgun = 100,
|
||||
/obj/item/weapon/gun/launcher/grenade = 100,
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/mercenary = 50,
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/mercenary = 30
|
||||
)
|
||||
|
||||
reload_max = 5
|
||||
reload_time = 1 SECOND
|
||||
|
||||
// Manhacks.
|
||||
grenade_type = /obj/item/weapon/grenade/spawnergrenade/manhacks/mercenary
|
||||
|
||||
projectile_dispersion = 8
|
||||
projectile_accuracy = -40
|
||||
special_attack_charges = 5
|
||||
|
||||
// Sniper, definitely a miniboss, based on its massive range advantage, and method of battle.
|
||||
// Creates a beam for 2 seconds, fire after another .5, then a 5 second reload.
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/sniper
|
||||
icon_state = "syndicateranged_sniper"
|
||||
icon_living = "syndicateranged_sniper"
|
||||
projectiletype = /obj/item/projectile/bullet/rifle/a145/highvel // Really scary bullet.
|
||||
projectilesound = 'sound/weapons/Gunshot_cannon.ogg'
|
||||
|
||||
projectile_accuracy = 75
|
||||
|
||||
reload_max = 1
|
||||
reload_time = 5 SECONDS
|
||||
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/merc/ranged/sniper
|
||||
|
||||
ranged_attack_delay = 2.5 SECONDS
|
||||
|
||||
loot_list = list(/obj/item/sniper_rifle_part/barrel = 50,
|
||||
/obj/item/sniper_rifle_part/stock = 50,
|
||||
/obj/item/sniper_rifle_part/trigger_group = 50,
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/mercenary = 90
|
||||
)
|
||||
|
||||
// Babyfrags.
|
||||
grenade_type = /obj/item/weapon/grenade/explosive/mini
|
||||
// Babyfrags go a long way.
|
||||
special_attack_min_range = 6
|
||||
special_attack_max_range = 10
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/sniper/ranged_pre_animation(atom/A)
|
||||
Beam(get_turf(A), icon_state = "sniper_beam", time = 2 SECONDS, maxdistance = 15)
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/sniper/shoot_target(atom/A)
|
||||
set waitfor = FALSE
|
||||
setClickCooldown(get_attack_speed())
|
||||
|
||||
face_atom(A)
|
||||
|
||||
var/atom/orig_targ = A
|
||||
|
||||
if(ranged_attack_delay)
|
||||
A = get_turf(orig_targ)
|
||||
ranged_pre_animation(A)
|
||||
handle_attack_delay(A, ranged_attack_delay) // This will sleep this proc for a bit, which is why waitfor is false.
|
||||
|
||||
if(needs_reload)
|
||||
if(reload_count >= reload_max)
|
||||
try_reload()
|
||||
return FALSE
|
||||
|
||||
visible_message("<span class='danger'><b>\The [src]</b> fires at \the [orig_targ]!</span>")
|
||||
shoot(A)
|
||||
if(casingtype)
|
||||
new casingtype(loc)
|
||||
|
||||
if(ranged_attack_delay)
|
||||
ranged_post_animation(A)
|
||||
|
||||
return TRUE
|
||||
|
||||
////////////////////////////////
|
||||
// Space Mercs
|
||||
@@ -274,24 +383,39 @@
|
||||
// PoI Mercs
|
||||
////////////////////////////////
|
||||
|
||||
// None of these drop weapons, until we have a better way to balance them
|
||||
// Most likely to drop a broken weapon matching them, if it's a gun.
|
||||
/mob/living/simple_mob/humanoid/merc/melee/poi
|
||||
loot_list = list()
|
||||
loot_list = list(/obj/item/weapon/material/knife/tacknife/combatknife = 100)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/melee/sword/poi
|
||||
loot_list = list()
|
||||
loot_list = list(/obj/item/weapon/melee/energy/sword/color = 20,
|
||||
/obj/item/weapon/shield/energy = 40
|
||||
)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/poi
|
||||
loot_list = list()
|
||||
loot_list = list(/obj/random/projectile/scrapped_pistol = 100)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/smg/poi
|
||||
loot_list = list()
|
||||
loot_list = list(/obj/random/projectile/scrapped_smg = 100)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/laser/poi
|
||||
loot_list = list()
|
||||
loot_list = list(/obj/random/projectile/scrapped_laser = 100)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/ionrifle
|
||||
loot_list = list()
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/ionrifle/poi
|
||||
loot_list = list(/obj/random/projectile/scrapped_ionrifle = 100)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/grenadier/poi
|
||||
loot_list = list()
|
||||
loot_list = list(/obj/random/projectile/scrapped_shotgun = 100)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/rifle/poi
|
||||
loot_list = list(/obj/random/projectile/scrapped_bulldog = 100)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/rifle/mag/poi
|
||||
loot_list = list(/obj/random/projectile/scrapped_flechette = 100)
|
||||
|
||||
/mob/living/simple_mob/humanoid/merc/ranged/technician/poi
|
||||
loot_list = list(/obj/random/projectile/scrapped_dartgun = 100,
|
||||
/obj/random/projectile/scrapped_grenadelauncher = 100,
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/mercenary = 50,
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/mercenary = 30
|
||||
)
|
||||
@@ -41,9 +41,9 @@
|
||||
// this is to prevent easy checks from the opposing force.
|
||||
/mob/living/simple_mob/illusion/examine(mob/user)
|
||||
if(copying)
|
||||
copying.examine(user)
|
||||
return
|
||||
..()
|
||||
return copying.examine(user)
|
||||
else
|
||||
return list("???")
|
||||
|
||||
/mob/living/simple_mob/illusion/bullet_act(obj/item/projectile/P)
|
||||
if(!P)
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
Mining drones have a slow-firing, armor-piercing beam that can destroy rocks.
|
||||
They will, if "tamed", collect ore and deposit it into nearby oreboxes when adjacent.
|
||||
*/
|
||||
|
||||
/datum/category_item/catalogue/technology/drone/mining_drone
|
||||
name = "Drone - Mining Drone"
|
||||
desc = "A crude modification of the commonly seen combat drone model, usually created\
|
||||
from the salvaged husks that litter debris fields. Capable of crude problem solving,\
|
||||
the drone's targeting system has been repurposed for locating suitable ores, though even\
|
||||
that is only functional in certain conditions.\
|
||||
<br><br>\
|
||||
These drones are armed with high-power mining emitters, which makes their decrepit forms\
|
||||
just as lethal as they were in their prime. Modified thrust vectoring devices allow them\
|
||||
to gather ore effectively without expending mechanical energy."
|
||||
value = CATALOGUER_REWARD_MEDIUM
|
||||
|
||||
/mob/living/simple_mob/mechanical/mining_drone
|
||||
name = "mining drone"
|
||||
desc = "An automated drone with a worn-out appearance, but an ominous gaze."
|
||||
catalogue_data = list(/datum/category_item/catalogue/technology/drone/mining_drone)
|
||||
|
||||
icon_state = "miningdrone"
|
||||
icon_living = "miningdrone"
|
||||
icon_dead = "miningdrone_dead"
|
||||
has_eye_glow = TRUE
|
||||
|
||||
faction = "malf_drone"
|
||||
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
movement_cooldown = 5
|
||||
hovering = TRUE
|
||||
|
||||
base_attack_cooldown = 5
|
||||
projectiletype = /obj/item/projectile/energy/excavate
|
||||
projectilesound = 'sound/weapons/pulse3.ogg'
|
||||
|
||||
response_help = "pokes"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "hits"
|
||||
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/ranged/kiting/threatening
|
||||
say_list_type = /datum/say_list/malf_drone
|
||||
|
||||
tame_items = list(
|
||||
/obj/item/weapon/ore/verdantium = 90,
|
||||
/obj/item/weapon/ore/hydrogen = 90,
|
||||
/obj/item/weapon/ore/osmium = 70,
|
||||
/obj/item/weapon/ore/diamond = 70,
|
||||
/obj/item/weapon/ore/gold = 55,
|
||||
/obj/item/weapon/ore/silver = 55,
|
||||
/obj/item/weapon/ore/lead = 40,
|
||||
/obj/item/weapon/ore/marble = 30,
|
||||
/obj/item/weapon/ore/coal = 25,
|
||||
/obj/item/weapon/ore/iron = 25,
|
||||
/obj/item/weapon/ore/glass = 15,
|
||||
/obj/item/weapon/ore = 5
|
||||
)
|
||||
|
||||
var/datum/effect/effect/system/ion_trail_follow/ion_trail = null
|
||||
var/obj/item/shield_projector/shields = null
|
||||
var/obj/item/weapon/storage/bag/ore/my_storage = null
|
||||
|
||||
var/last_search = 0
|
||||
var/search_cooldown = 5 SECONDS
|
||||
|
||||
/mob/living/simple_mob/mechanical/mining_drone/Initialize()
|
||||
ion_trail = new
|
||||
ion_trail.set_up(src)
|
||||
ion_trail.start()
|
||||
|
||||
my_storage = new /obj/item/weapon/storage/bag/ore(src)
|
||||
shields = new /obj/item/shield_projector/rectangle/automatic/drone(src)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/mechanical/mining_drone/Destroy()
|
||||
QDEL_NULL(ion_trail)
|
||||
QDEL_NULL(shields)
|
||||
QDEL_NULL(my_storage)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/mechanical/mining_drone/death()
|
||||
my_storage.forceMove(get_turf(src))
|
||||
my_storage = null
|
||||
..(null,"suddenly breaks apart.")
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_mob/mechanical/mining_drone/Process_Spacemove(var/check_drift = 0)
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_mob/mechanical/mining_drone/IIsAlly(mob/living/L)
|
||||
. = ..()
|
||||
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(!istype(H))
|
||||
return .
|
||||
|
||||
if(!.)
|
||||
var/has_tool = FALSE
|
||||
var/obj/item/I = H.get_active_hand()
|
||||
if(istype(I,/obj/item/weapon/pickaxe))
|
||||
has_tool = TRUE
|
||||
return has_tool
|
||||
|
||||
/mob/living/simple_mob/mechanical/mining_drone/handle_special()
|
||||
if(my_storage && (get_AI_stance() in list(STANCE_APPROACH, STANCE_IDLE, STANCE_FOLLOW)) && !is_AI_busy() && isturf(loc) && (world.time > last_search + search_cooldown) && (my_storage.contents.len < my_storage.max_storage_space))
|
||||
last_search = world.time
|
||||
|
||||
for(var/turf/T in view(world.view,src))
|
||||
if(my_storage.contents.len >= my_storage.max_storage_space)
|
||||
break
|
||||
|
||||
if((locate(/obj/item/weapon/ore) in T) && prob(40))
|
||||
src.Beam(T, icon_state = "holo_beam", time = 0.5 SECONDS)
|
||||
my_storage.rangedload(T, src)
|
||||
|
||||
if(my_storage.contents.len >= my_storage.max_storage_space)
|
||||
visible_message("<span class='notice'>\The [src] emits a shrill beep, indicating its storage is full.</span>")
|
||||
|
||||
var/obj/structure/ore_box/OB = locate() in view(2, src)
|
||||
|
||||
if(istype(OB) && my_storage && my_storage.contents.len)
|
||||
src.Beam(OB, icon_state = "rped_upgrade", time = 1 SECONDS)
|
||||
for(var/obj/item/I in my_storage)
|
||||
my_storage.remove_from_storage(I, OB)
|
||||
@@ -68,3 +68,11 @@
|
||||
/mob/living/simple_mob/mechanical/mecha/combat/durand/defensive/Initialize()
|
||||
set_defense_mode(TRUE)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/mechanical/mecha/combat/durand/defensive/mercenary
|
||||
desc = "An aging combat exosuit utilized by many corporations. It was originally developed to fight in the First Contact War.\
|
||||
This one has been retrofitted into a turret."
|
||||
|
||||
projectiletype = /obj/item/projectile/beam/heavylaser/fakeemitter
|
||||
|
||||
pilot_type = /mob/living/simple_mob/humanoid/merc/ranged
|
||||
|
||||
@@ -133,18 +133,13 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/construct/examine(mob/user)
|
||||
..(user)
|
||||
var/msg = "<span cass='info'>*---------*\nThis is [bicon(src)] \a <EM>[src]</EM>!\n"
|
||||
if (src.health < src.getMaxHealth())
|
||||
msg += "<span class='warning'>"
|
||||
if (src.health >= src.getMaxHealth()/2)
|
||||
msg += "It looks slightly dented.\n"
|
||||
. = ..(user)
|
||||
var/max = getMaxHealth()
|
||||
if (health < max)
|
||||
if (health >= max/2)
|
||||
. += "<span class='warning'>It looks slightly dented.</span>"
|
||||
else
|
||||
msg += "<B>It looks severely dented!</B>\n"
|
||||
msg += "</span>"
|
||||
msg += "*---------*</span>"
|
||||
|
||||
to_chat(user,msg)
|
||||
. += "<span class='warning'><B>It looks severely dented!</B></span>"
|
||||
|
||||
//Constructs levitate, can fall from a shuttle with no harm, and are piloted by either damned spirits or some otherworldly entity. Let 'em float in space.
|
||||
/mob/living/simple_mob/construct/Process_Spacemove()
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// Handles hunger, starvation, growth, and eatting humans.
|
||||
|
||||
// Might be best to make this a /mob/living proc and override.
|
||||
/mob/living/simple_mob/slime/xenobio/proc/adjust_nutrition(input, var/heal = 1)
|
||||
nutrition = between(0, nutrition + input, get_max_nutrition())
|
||||
/mob/living/simple_mob/slime/xenobio/adjust_nutrition(input, var/heal = 1)
|
||||
..(input)
|
||||
|
||||
if(input > 0)
|
||||
// Gain around one level per 50 nutrition.
|
||||
@@ -19,10 +18,6 @@
|
||||
adjustOxyLoss(-input * 0.2)
|
||||
adjustCloneLoss(-input * 0.2)
|
||||
|
||||
|
||||
/mob/living/simple_mob/slime/xenobio/proc/get_max_nutrition() // Can't go above it
|
||||
return is_adult ? 1200 : 1000
|
||||
|
||||
/mob/living/simple_mob/slime/xenobio/proc/get_grow_nutrition() // Above it we grow, below it we can eat
|
||||
return is_adult ? 1000 : 800
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
desc = "The most basic of slimes. The grey slime has no remarkable qualities, however it remains one of the most useful colors for scientists."
|
||||
layer = MOB_LAYER + 1 // Need them on top of other mobs or it looks weird when consuming something.
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/xenobio_slime // This should never be changed for xenobio slimes.
|
||||
max_nutrition = 1000
|
||||
var/is_adult = FALSE // Slimes turn into adults when fed enough. Adult slimes are somewhat stronger, and can reproduce if fed enough.
|
||||
var/maxHealth_adult = 200
|
||||
var/power_charge = 0 // Disarm attacks can shock someone if high/lucky enough.
|
||||
@@ -73,25 +74,25 @@
|
||||
..()
|
||||
|
||||
/mob/living/simple_mob/slime/xenobio/examine(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(hat)
|
||||
to_chat(user, "It is wearing \a [hat].")
|
||||
. += "It is wearing \a [hat]."
|
||||
|
||||
if(stat == DEAD)
|
||||
to_chat(user, "It appears to be dead.")
|
||||
. += "It appears to be dead."
|
||||
else if(incapacitated(INCAPACITATION_DISABLED))
|
||||
to_chat(user, "It appears to be incapacitated.")
|
||||
. += "It appears to be incapacitated."
|
||||
else if(harmless)
|
||||
to_chat(user, "It appears to have been pacified.")
|
||||
. += "It appears to have been pacified."
|
||||
else
|
||||
if(has_AI())
|
||||
var/datum/ai_holder/simple_mob/xenobio_slime/AI = ai_holder
|
||||
if(AI.rabid)
|
||||
to_chat(user, "It seems very, very angry and upset.")
|
||||
. += "It seems very, very angry and upset."
|
||||
else if(AI.obedience >= 5)
|
||||
to_chat(user, "It looks rather obedient.")
|
||||
. += "It looks rather obedient."
|
||||
else if(AI.discipline)
|
||||
to_chat(user, "It has been subjugated by force, at least for now.")
|
||||
. += "It has been subjugated by force, at least for now."
|
||||
|
||||
/mob/living/simple_mob/slime/xenobio/proc/make_adult()
|
||||
if(is_adult)
|
||||
@@ -101,6 +102,7 @@
|
||||
melee_damage_lower = round(melee_damage_lower * 2) // 20
|
||||
melee_damage_upper = round(melee_damage_upper * 2) // 30
|
||||
maxHealth = maxHealth_adult
|
||||
max_nutrition = 1200
|
||||
amount_grown = 0
|
||||
update_icon()
|
||||
update_name()
|
||||
|
||||
62
code/modules/mob/living/simple_mob/taming.dm
Normal file
62
code/modules/mob/living/simple_mob/taming.dm
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
/mob/living/simple_mob
|
||||
// Assoc list of items that can be given to a mob to befriend it, and the percent success.
|
||||
var/list/tame_items
|
||||
// List of mobs who are 'friends'.
|
||||
var/list/tamers
|
||||
|
||||
/mob/living/simple_mob/IIsAlly(mob/living/L)
|
||||
. = ..()
|
||||
|
||||
if(!. && LAZYLEN(tamers))
|
||||
listclearnulls(tamers)
|
||||
if(L in tamers)
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_mob/proc/can_tame(var/obj/O, var/mob/user)
|
||||
if(!LAZYLEN(tame_items))
|
||||
return FALSE
|
||||
|
||||
if(!user)
|
||||
return FALSE
|
||||
|
||||
if(!O)
|
||||
return FALSE
|
||||
|
||||
for(var/path in tame_items)
|
||||
if(istype(O, path) && unique_tame_check(O,user))
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_mob/proc/unique_tame_check(var/obj/O, var/mob/user)
|
||||
if(do_after(user, 0.5 SECONDS, src))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_mob/proc/tame_prob(var/obj/O, var/mob/user)
|
||||
for(var/path in tame_items)
|
||||
if(istype(O, path))
|
||||
if(prob(tame_items[path]))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_mob/proc/do_tame(var/obj/O, var/mob/user)
|
||||
if(!user)
|
||||
return
|
||||
|
||||
if(!LAZYLEN(tamers))
|
||||
tamers = list()
|
||||
|
||||
handle_tame_item(O, user)
|
||||
|
||||
tamers |= user
|
||||
ai_holder.forget_everything()
|
||||
|
||||
/mob/living/simple_mob/proc/handle_tame_item(var/obj/O, var/mob/user)
|
||||
user.drop_from_inventory(O)
|
||||
qdel(O)
|
||||
|
||||
/mob/living/simple_mob/proc/fail_tame(var/obj/O, var/mob/user)
|
||||
user.drop_from_inventory(O)
|
||||
qdel(O)
|
||||
@@ -15,7 +15,7 @@
|
||||
if(matches) matches += " and "
|
||||
matches += "ID ([client.computer_id])"
|
||||
if(!config.disable_cid_warn_popup)
|
||||
spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
|
||||
spawn() alert("You appear to have logged in with another key this round, which is not permitted. Please contact an administrator if you believe this message to be in error.")
|
||||
if(matches)
|
||||
if(M.client)
|
||||
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(src)] has the same [matches] as [key_name_admin(M)].</font>", 1)
|
||||
|
||||
@@ -229,7 +229,10 @@
|
||||
return 1
|
||||
|
||||
face_atom(A)
|
||||
A.examine(src)
|
||||
var/list/results = A.examine(src)
|
||||
if(!results || !results.len)
|
||||
results = list("You were unable to examine that. Tell a developer!")
|
||||
to_chat(src, jointext(results, "<br>"))
|
||||
|
||||
/mob/verb/pointed(atom/A as mob|obj|turf in view())
|
||||
set name = "Point To"
|
||||
|
||||
@@ -112,9 +112,7 @@
|
||||
var/bodytemperature = 310.055 //98.7 F
|
||||
var/drowsyness = 0.0//Carbon
|
||||
var/charges = 0.0
|
||||
var/nutrition = 400.0//Carbon
|
||||
|
||||
var/overeatduration = 0 // How long this guy is overeating //Carbon
|
||||
var/paralysis = 0.0
|
||||
var/stunned = 0.0
|
||||
var/weakened = 0.0
|
||||
|
||||
@@ -364,6 +364,7 @@
|
||||
|
||||
var/turf/T = join_props["turf"]
|
||||
var/join_message = join_props["msg"]
|
||||
var/announce_channel = join_props["channel"] || "Common"
|
||||
|
||||
if(!T || !join_message)
|
||||
return 0
|
||||
@@ -377,10 +378,10 @@
|
||||
character = job_master.EquipRank(character, rank, 1) //equips the human
|
||||
UpdateFactionList(character)
|
||||
|
||||
// AIs don't need a spawnpoint, they must spawn at an empty core
|
||||
if(character.mind.assigned_role == "AI")
|
||||
var/datum/job/J = SSjob.get_job(rank)
|
||||
|
||||
character = character.AIize(move=0) // AIize the character, but don't move them yet
|
||||
// AIs don't need a spawnpoint, they must spawn at an empty core
|
||||
if(J.mob_type & JOB_SILICON_AI)
|
||||
|
||||
// IsJobAvailable for AI checks that there is an empty core available in this list
|
||||
var/obj/structure/AIcore/deactivated/C = empty_playable_ai_cores[1]
|
||||
@@ -388,11 +389,14 @@
|
||||
|
||||
character.loc = C.loc
|
||||
|
||||
// AIize the character, but don't move them yet
|
||||
character = character.AIize(move = FALSE) // Dupe of code in /datum/controller/subsystem/ticker/proc/create_characters() for non-latespawn, unify?
|
||||
|
||||
AnnounceCyborg(character, rank, "has been transferred to the empty core in \the [character.loc.loc]")
|
||||
ticker.mode.latespawn(character)
|
||||
|
||||
qdel(C)
|
||||
qdel(src)
|
||||
qdel(C) //Deletes empty core (really?)
|
||||
qdel(src) //Deletes new_player
|
||||
return
|
||||
|
||||
// Equip our custom items only AFTER deploying to spawn points eh?
|
||||
@@ -406,25 +410,23 @@
|
||||
character.buckled.set_dir(character.dir)
|
||||
|
||||
ticker.mode.latespawn(character)
|
||||
|
||||
if(character.mind.assigned_role != "Cyborg")
|
||||
|
||||
if(J.mob_type & JOB_SILICON)
|
||||
AnnounceCyborg(character, rank, join_message, announce_channel, character.z)
|
||||
else
|
||||
AnnounceArrival(character, rank, join_message, announce_channel, character.z)
|
||||
data_core.manifest_inject(character)
|
||||
ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
|
||||
|
||||
qdel(src) // Delete new_player mob
|
||||
|
||||
//Grab some data from the character prefs for use in random news procs.
|
||||
|
||||
AnnounceArrival(character, rank, join_message)
|
||||
else
|
||||
AnnounceCyborg(character, rank, join_message)
|
||||
|
||||
qdel(src)
|
||||
|
||||
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message)
|
||||
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message, var/channel, var/zlevel)
|
||||
if (ticker.current_state == GAME_STATE_PLAYING)
|
||||
var/list/zlevels = zlevel ? using_map.get_map_levels(zlevel, TRUE) : null
|
||||
if(character.mind.role_alt_title)
|
||||
rank = character.mind.role_alt_title
|
||||
// can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc.
|
||||
global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer")
|
||||
global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer", channel, zlevels)
|
||||
|
||||
/mob/new_player/proc/LateChoices()
|
||||
var/name = client.prefs.be_random_name ? "friend" : client.prefs.real_name
|
||||
@@ -586,6 +588,9 @@
|
||||
/mob/new_player/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null)
|
||||
return
|
||||
|
||||
/mob/new_player/hear_holopad_talk(list/message_pieces, var/verb = "says", var/mob/speaker = null)
|
||||
return
|
||||
|
||||
// Prevents lobby players from seeing emotes, even with ghosteyes
|
||||
/mob/new_player/show_message(msg, type, alt, alt_type)
|
||||
return
|
||||
|
||||
@@ -1560,6 +1560,11 @@
|
||||
icon_state = "backstripe"
|
||||
body_parts = list(BP_TORSO)
|
||||
|
||||
heterochromia
|
||||
name = "Heterochromia (right eye)"
|
||||
icon_state = "heterochromia"
|
||||
body_parts = list(BP_HEAD)
|
||||
|
||||
//Taj specific stuff
|
||||
taj_belly
|
||||
name = "Belly Fur (Taj)"
|
||||
@@ -1642,6 +1647,12 @@
|
||||
body_parts = list(BP_HEAD, BP_TORSO, BP_GROIN, BP_R_LEG, BP_L_LEG)
|
||||
species_allowed = list(SPECIES_TESHARI)
|
||||
|
||||
teshi_heterochromia
|
||||
name = "Heterochromia (Teshari) (right eye)"
|
||||
icon_state = "teshi_heterochromia"
|
||||
body_parts = list(BP_HEAD)
|
||||
species_allowed = list(SPECIES_TESHARI)
|
||||
|
||||
//skin styles - WIP
|
||||
//going to have to re-integrate this with surgery
|
||||
//let the icon_state hold an icon preview for now
|
||||
|
||||
@@ -148,8 +148,8 @@
|
||||
/mob/proc/find_valid_prefixes(message)
|
||||
var/list/prefixes = list() // [["Common", start, end], ["Gutter", start, end]]
|
||||
for(var/i in 1 to length(message))
|
||||
// This grabs trimmed 3 character substrings, to allow for up to 1 prefix and 1 letter language keys
|
||||
var/selection = trim_right(lowertext(copytext(message, i, i + 2)))
|
||||
// This grabs 3 character substrings, to allow for up to 1 prefix, 1 letter language key, and one post-key character to more strictly control where the language breaks happen
|
||||
var/selection = lowertext(copytext(message, i, i + 3))
|
||||
// The first character in the selection will always be the prefix (if this is a valid language invocation)
|
||||
var/prefix = copytext(selection, 1, 2)
|
||||
var/language_key = copytext(selection, 2, 3)
|
||||
@@ -157,6 +157,18 @@
|
||||
// Okay, we're definitely now trying to invoke a language (probably)
|
||||
// This "[]" is probably unnecessary but BYOND will runtime if a number is used
|
||||
var/datum/language/L = GLOB.language_keys["[language_key]"]
|
||||
|
||||
// MULTILINGUAL_SPACE enforces a space after the language key
|
||||
if(client && (client.prefs.multilingual_mode == MULTILINGUAL_SPACE) && (text2ascii(copytext(selection, 3, 4)) != 32)) // If we're looking for a space and we don't find one
|
||||
continue
|
||||
|
||||
// MULTILINGUAL_DOUBLE_DELIMITER enforces a delimiter (valid prefix) after the language key
|
||||
if(client && (client.prefs.multilingual_mode == MULTILINGUAL_DOUBLE_DELIMITER) && !is_language_prefix(copytext(selection, 3, 4)))
|
||||
continue
|
||||
|
||||
if(client && (client.prefs.multilingual_mode in list(MULTILINGUAL_DEFAULT)))
|
||||
selection = copytext(selection, 1, 3) // These modes only use two characters, not three
|
||||
|
||||
// It's kinda silly that we have to check L != null and this isn't done for us by can_speak (it runtimes instead), but w/e
|
||||
if(L && can_speak(L))
|
||||
// So we have a valid language invocation, and we can speak that language, let's make a piece for it
|
||||
@@ -170,6 +182,10 @@
|
||||
// This covers the case of "no prefixes in use."
|
||||
prefixes[++prefixes.len] = list(get_default_language(), i, i)
|
||||
|
||||
// If multilingualism is disabled, then after the first pass we're guaranteed to have either found a language key at the start, or else there isn't one and we're using the default for the whole message
|
||||
if(client && (client.prefs.multilingual_mode == MULTILINGUAL_OFF))
|
||||
break
|
||||
|
||||
return prefixes
|
||||
|
||||
/mob/proc/strip_prefixes(message, mob/prefixer = null)
|
||||
|
||||
@@ -64,10 +64,34 @@
|
||||
invisibility = 101
|
||||
return ..()
|
||||
|
||||
/mob/proc/AIize(move=1)
|
||||
/mob/proc/AIize(var/move = TRUE)
|
||||
if(client)
|
||||
src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // stop the jams for AIs
|
||||
var/mob/living/silicon/ai/O = new (loc, using_map.default_law_type,,1)//No MMI but safety is in effect.
|
||||
|
||||
var/newloc = loc
|
||||
if(move)
|
||||
var/obj/loc_landmark
|
||||
for(var/obj/effect/landmark/start/sloc in landmarks_list)
|
||||
if (sloc.name != "AI")
|
||||
continue
|
||||
if ((locate(/mob/living) in sloc.loc) || (locate(/obj/structure/AIcore) in sloc.loc))
|
||||
continue
|
||||
loc_landmark = sloc
|
||||
if (!loc_landmark)
|
||||
for(var/obj/effect/landmark/tripai in landmarks_list)
|
||||
if (tripai.name == "tripai")
|
||||
if((locate(/mob/living) in tripai.loc) || (locate(/obj/structure/AIcore) in tripai.loc))
|
||||
continue
|
||||
loc_landmark = tripai
|
||||
if (!loc_landmark)
|
||||
to_chat(src, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.")
|
||||
for(var/obj/effect/landmark/start/sloc in landmarks_list)
|
||||
if (sloc.name == "AI")
|
||||
loc_landmark = sloc
|
||||
|
||||
newloc = loc_landmark.loc
|
||||
|
||||
var/mob/living/silicon/ai/O = new (newloc, using_map.default_law_type,,1)//No MMI but safety is in effect.
|
||||
O.invisibility = 0
|
||||
O.aiRestorePowerRoutine = 0
|
||||
|
||||
@@ -101,28 +125,6 @@
|
||||
if(LANGUAGE_ROOTLOCAL in B.alternate_languages)
|
||||
O.add_language(LANGUAGE_ROOTLOCAL, 1)
|
||||
|
||||
if(move)
|
||||
var/obj/loc_landmark
|
||||
for(var/obj/effect/landmark/start/sloc in landmarks_list)
|
||||
if (sloc.name != "AI")
|
||||
continue
|
||||
if ((locate(/mob/living) in sloc.loc) || (locate(/obj/structure/AIcore) in sloc.loc))
|
||||
continue
|
||||
loc_landmark = sloc
|
||||
if (!loc_landmark)
|
||||
for(var/obj/effect/landmark/tripai in landmarks_list)
|
||||
if (tripai.name == "tripai")
|
||||
if((locate(/mob/living) in tripai.loc) || (locate(/obj/structure/AIcore) in tripai.loc))
|
||||
continue
|
||||
loc_landmark = tripai
|
||||
if (!loc_landmark)
|
||||
to_chat(O, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.")
|
||||
for(var/obj/effect/landmark/start/sloc in landmarks_list)
|
||||
if (sloc.name == "AI")
|
||||
loc_landmark = sloc
|
||||
|
||||
O.loc = loc_landmark.loc
|
||||
|
||||
O.on_mob_init()
|
||||
|
||||
O.add_ai_verbs()
|
||||
|
||||
Reference in New Issue
Block a user