Merge branch 'master' into pol-moved

This commit is contained in:
Aronai Sieyes
2020-05-12 11:22:43 -04:00
committed by GitHub
608 changed files with 8598 additions and 5698 deletions

View 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
..()

View File

@@ -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)

View File

@@ -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.

View File

@@ -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

View File

@@ -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
/*

View File

@@ -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)

View File

@@ -28,7 +28,7 @@
var/rads = radiation/25
radiation -= rads
nutrition += rads
adjust_nutrition(rads)
heal_overall_damage(rads,rads)
adjustOxyLoss(-(rads))
adjustToxLoss(-(rads))

View File

@@ -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

View File

@@ -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

View File

@@ -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 ..()

View File

@@ -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)

View File

@@ -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

View File

@@ -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))

View File

@@ -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

View File

@@ -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)

View File

@@ -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.

View File

@@ -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.

View File

@@ -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)))

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -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()
. = ..()
. += {"

View File

@@ -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

View File

@@ -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.

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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 ..()

View 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

View File

@@ -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.

View File

@@ -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

View File

@@ -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!

View File

@@ -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

View File

@@ -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)

View File

@@ -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")

View File

@@ -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

View File

@@ -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")

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
)

View File

@@ -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
)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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()

View 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)

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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()