@@ -0,0 +1,156 @@
/mob/living/carbon/proc/print_happiness()
var/msg = "\n<span class='info'>I am a follower of <font color='red'>[religion]</font></span>.\n"
msg += "<span class='info'>I am [get_social_class()]</span>.\n"
msg += "<span class='info'>*---------*\n<EM>Current mood</EM>\n"
for(var/i in events)
var/datum/happiness_event/event = events[i]
msg += event.description

if(!events.len)
msg += "<span class='info'>I feel indifferent.</span>\n"


msg += "<span class='info'>*---------*</span>"
to_chat(src, msg)

/mob/living/carbon/proc/update_happiness()
var/old_happiness = happiness
var/old_icon = null
if(happiness_icon)
old_icon = happiness_icon.icon_state
happiness = 0
for(var/i in events)
var/datum/happiness_event/event = events[i]
happiness += event.happiness

switch(happiness)
if(-5000000 to MOOD_LEVEL_SAD4)
if(happiness_icon)
happiness_icon.icon_state = "mood7"

if(MOOD_LEVEL_SAD4 to MOOD_LEVEL_SAD3)
if(happiness_icon)
happiness_icon.icon_state = "mood6"

if(MOOD_LEVEL_SAD3 to MOOD_LEVEL_SAD2)
if(happiness_icon)
happiness_icon.icon_state = "mood5"

if(MOOD_LEVEL_SAD2 to MOOD_LEVEL_SAD1)
if(happiness_icon)
happiness_icon.icon_state = "mood5"

if(MOOD_LEVEL_SAD1 to MOOD_LEVEL_HAPPY1)
if(happiness_icon)
happiness_icon.icon_state = "mood4"

if(MOOD_LEVEL_HAPPY1 to MOOD_LEVEL_HAPPY2)
if(happiness_icon)
happiness_icon.icon_state = "mood4"

if(MOOD_LEVEL_HAPPY2 to MOOD_LEVEL_HAPPY3)
if(happiness_icon)
happiness_icon.icon_state = "mood3"

if(MOOD_LEVEL_HAPPY3 to MOOD_LEVEL_HAPPY4)
if(happiness_icon)
happiness_icon.icon_state = "mood2"

if(MOOD_LEVEL_HAPPY4 to INFINITY)
if(happiness_icon)
happiness_icon.icon_state = "mood1"

if(old_icon && old_icon != happiness_icon.icon_state)
if(old_happiness > happiness)
to_chat(src, "<span class='warning'>My mood gets worse.</span>")
else
to_chat(src, "<span class='info'>My mood gets better.</span>")

/mob/proc/flash_sadness()
if(prob(2))
flick("sadness",pain)
var/spoopysound = pick('sound/effects/badmood1.ogg','sound/effects/badmood2.ogg','sound/effects/badmood3.ogg','sound/effects/badmood4.ogg')
sound_to(src, spoopysound)

/mob/living/carbon/proc/handle_happiness()
switch(happiness)
if(-5000000 to MOOD_LEVEL_SAD4)
flash_sadness()
crit_mood_modifier = -10
if(MOOD_LEVEL_SAD4 to MOOD_LEVEL_SAD3)
flash_sadness()
crit_mood_modifier = -5
if(MOOD_LEVEL_SAD1 to MOOD_LEVEL_HAPPY2)
crit_mood_modifier = CRIT_SUCCESS_NORM
if(MOOD_LEVEL_HAPPY3 to MOOD_LEVEL_HAPPY4)
crit_mood_modifier = 5
if(MOOD_LEVEL_HAPPY4 to INFINITY)
crit_mood_modifier = 10


/mob/living/carbon/proc/add_event(category, type) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger.
var/datum/happiness_event/the_event
if(events[category])
the_event = events[category]
if(the_event.type != type)
clear_event(category)
return .()
else
return 0 //Don't have to update the event.
else
the_event = new type()

events[category] = the_event
update_happiness()

if(the_event.timeout)
spawn(the_event.timeout)
clear_event(category)

/mob/living/carbon/proc/clear_event(category)
var/datum/happiness_event/event = events[category]
if(!event)
return 0

events -= category
qdel(event)
update_happiness()

/mob/living/carbon/proc/handle_hygiene()
adjust_hygiene(-my_hygiene_factor)
var/image/smell = image('icons/effects/effects.dmi', "smell")//This is a hack, there has got to be a safer way to do this but I don't know it at the moment.
switch(hygiene)
if(HYGIENE_LEVEL_NORMAL to INFINITY)
add_event("hygiene", /datum/happiness_event/hygiene/clean)
overlays -= smell
if(HYGIENE_LEVEL_DIRTY to HYGIENE_LEVEL_NORMAL)
clear_event("hygiene")
overlays -= smell
if(0 to HYGIENE_LEVEL_DIRTY)
overlays -= smell
overlays += smell
add_event("hygiene", /datum/happiness_event/hygiene/smelly)

/mob/living/carbon/proc/adjust_hygiene(var/amount)
var/old_hygiene = hygiene
if(amount>0)
hygiene = min(hygiene+amount, HYGIENE_LEVEL_CLEAN)

else if(old_hygiene)
hygiene = max(hygiene+amount, 0)

/mob/living/carbon/proc/set_hygiene(var/amount)
if(amount >= 0)
hygiene = min(HYGIENE_LEVEL_CLEAN, amount)

/mob/living/carbon/proc/adjust_thirst(var/amount)
var/old_thirst = thirst
if(amount>0)
thirst = min(thirst+amount, THIRST_LEVEL_MAX)

else if(old_thirst)
thirst = max(thirst+amount, 0)

/mob/living/carbon/proc/set_thirst(var/amount)
if(amount >= 0)
thirst = min(THIRST_LEVEL_MAX, amount)
@@ -0,0 +1,179 @@
/datum/happiness_event
var/description
var/happiness = 0
var/timeout = 0

///For descriptions, use the span classes bold info, info, none, warning and boldwarning in order from great to horrible.

//thirst
/datum/happiness_event/thirst/filled
description = "<span class='binfo'>I've had enough to drink for a while!</span>\n"
happiness = 4

/datum/happiness_event/thirst/watered
description = "<span class='info'>I have recently had something to drink.</span>\n"
happiness = 2

/datum/happiness_event/thirst/thirsty
description = "<span class='warning'>I'm getting a bit thirsty.</span>\n"
happiness = -7

/datum/happiness_event/thirst/dehydrated
description = "<span class='danger'>I need water!</span>\n"
happiness = -14



//nutrition
/datum/happiness_event/nutrition/fat
description = "<span class='warning'><B>I'm so fat..</B></span>\n" //muh fatshaming
happiness = -4

/datum/happiness_event/nutrition/wellfed
description = "<span class='binfo'>My belly feels round and full.</span>\n"
happiness = 4

/datum/happiness_event/nutrition/fed
description = "<span class='info'>I have recently had some food.</span>\n"
happiness = 2

/datum/happiness_event/nutrition/hungry
description = "<span class='warning'>I'm getting a bit hungry.</span>\n"
happiness = -6

/datum/happiness_event/nutrition/starving
description = "<span class='danger'>I'm starving!</span>\n"
happiness = -12


//Hygiene
/datum/happiness_event/hygiene/clean
description = "<span class='info'>I feel so clean!\n"
happiness = 2

/datum/happiness_event/hygiene/smelly
description = "<span class='warning'>I smell like shit.\n"
happiness = -5

/datum/happiness_event/hygiene/vomitted
description = "<span class='warning'>Ugh, I've vomitted.\n"
happiness = -5
timeout = 1800



//Disgust
/datum/happiness_event/disgust/gross
description = "<span class='warning'>That was gross.</span>\n"
happiness = -2
timeout = 1800

/datum/happiness_event/disgust/verygross
description = "<span class='warning'>I think I'm going to puke...</span>\n"
happiness = -4
timeout = 1800

/datum/happiness_event/disgust/disgusted
description = "<span class='danger'>Oh god that's disgusting...</span>\n"
happiness = -6
timeout = 1800



//Generic events
/datum/happiness_event/favorite_food
description = "<span class='info'>I really liked eating that.</span>\n"
happiness = 3
timeout = 2400

/datum/happiness_event/nice_shower
description = "<span class='info'>I had a nice shower.</span>\n"
happiness = 1
timeout = 1800

/datum/happiness_event/handcuffed
description = "<span class='warning'>I guess my antics finally caught up with me..</span>\n"
happiness = -1

/datum/happiness_event/booze
description = "<span class='info'>Alcohol makes the pain go away.</span>\n"
happiness = 3
timeout = 2400

/datum/happiness_event/relaxed//For nicotine.
description = "<span class='info'>I feel relaxed.</span>\n"
happiness = 1
timeout = 1800

/datum/happiness_event/antsy//Withdrawl.
description = "<span class='danger'>I could use a smoke.</span>\n"
happiness = -3
timeout = 1800

/datum/happiness_event/hot_food //Hot food feels good!
description = "<span class='info'>I've eaten something warm.</span>\n"
happiness = 3
timeout = 1800

/datum/happiness_event/cold_drink //Cold drinks feel good!
description = "<span class='info'>I've had something refreshing.</span>\n"
happiness = 3
timeout = 1800

/datum/happiness_event/high
description = "<span class='binfo'>I'm high as fuck</span>\n"
happiness = 12



//Embarassment
/datum/happiness_event/hygiene/shit
description = "<span class='danger'>I shit myself. How embarassing.\n"
happiness = -12
timeout = 1800

/datum/happiness_event/hygiene/pee
description = "<span class='danger'>I pissed myself. How embarassing.\n"
happiness = -12
timeout = 1800

/datum/happiness_event/badsex
description = "<span class='warning'>Ugh, that sex was horrible.\n"
happiness = -4
timeout = 1800

//Good sex here too because why not.
/datum/happiness_event/came
description = "<span class='binfo'>I came!\n"
happiness = 10
timeout = 1800

//For when you get branded.
/datum/happiness_event/humiliated
description = "<span class='danger'>I've been humiliated, and I am embarassed.</span>\n"
happiness = -10
timeout = 1800

//And when you've seen someone branded
/datum/happiness_event/punished_heretic
description = "<span class='binfo'>I've seen a punished heretic.</span>\n"
happiness = 10
timeout = 1800


//Unused so far but I want to remember them to use them later.
/datum/happiness_event/disturbing
description = "<span class='danger'>I recently saw something disturbing</span>\n"
happiness = -2

/datum/happiness_event/clown
description = "<span class='info'>I recently saw a funny clown!</span>\n"
happiness = 1

/datum/happiness_event/cloned_corpse
description = "<span class='danger'>I recently saw my own corpse...</span>\n"
happiness = -6

/datum/happiness_event/surgery
description = "<span class='danger'>HE'S CUTTING ME OPEN!!</span>\n"
happiness = -8
@@ -0,0 +1,87 @@
/mob/proc/agony_scream()
if(stat)
return
var/screamsound = null
var/muzzled = istype(wear_mask, /obj/item/clothing/mask/muzzle)
var/message = null

if(ishuman(src))
var/mob/living/carbon/human/H = src
if(!muzzled)
if(H.isMonkey())
screamsound = "sound/voice/monkey_pain[rand(1,3)].ogg"

else if(H.isChild())
screamsound = "sound/voice/child_pain[rand(1,2)].ogg"

else if(src.gender == MALE)
screamsound = "sound/voice/man_pain[rand(1,3)].ogg"

else
screamsound = "sound/voice/woman_agony[rand(1,3)].ogg"
message = "screams in agony!"

else
message = "makes a loud noise!"
screamsound = "sound/voice/gagscream[rand(1,3)].wav"

if(screamsound)
playsound(src, screamsound, 50, 0, 1)

if(message)
custom_emote(2,message)

/mob/proc/gasp_sound()
var/gaspsound = null
var/muzzled = istype(wear_mask, /obj/item/clothing/mask/muzzle)
if(stat)
return

if(muzzled)
custom_emote(2,"[src.name] makes a muffled gasping noise.")
return

if(gender == MALE)
gaspsound = "sound/voice/gasp_male[rand(1,7)].ogg"

if(gender == FEMALE)
gaspsound = "sound/voice/gasp_female[rand(1,7)].ogg"

if(gaspsound)
playsound(src, gaspsound, 25, 0, 1)


/mob/proc/agony_moan()
if(stat)
return
var/moansound = null
var/message = null
if(stat)
return

var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle)
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(!muzzled)
if(H.isMonkey())
return

if(H.isChild())
moansound = 'sound/voice/child_moan1.ogg'

else if(src.gender == MALE)
moansound = "sound/voice/male_moan[rand(1,3)].ogg"

else
moansound = "sound/voice/female_moan[rand(1,3)].ogg"

message = "moans."
else
message = "makes a loud noise!"
moansound = "sound/voice/gagscream[rand(1,3)].wav"

if(moansound)
playsound(src, moansound, 50, 0, 1)

if(message)
custom_emote(2,message)
@@ -73,6 +73,11 @@
handle_organs()
if(species.death_sound)
playsound(loc, species.death_sound, 80, 1, 1)
spawn(50)
if(bowels >= 30)
handle_shit()
if(bladder >= 30)
handle_piss()
handle_hud_list()

/mob/living/carbon/human/proc/ChangeToHusk()
@@ -0,0 +1,209 @@
/mob/living/carbon/human/verb/blink_t()
set name = "Blink"
set category = "Emotes"

emote("blink",1)

/mob/living/carbon/human/verb/bow()
set name = "Bow"
set category = "Emotes"

emote("bow",1)

/mob/living/carbon/human/verb/salute()
set name = "Salute"
set category = "Emotes"

emote("salute",1)

/mob/living/carbon/human/verb/poo()
set name = "Poo"
set category = "Emotes"

emote("poo",1)

/mob/living/carbon/human/verb/pee()
set name = "Pee"
set category = "Emotes"

emote("pee",1)

/mob/living/carbon/human/verb/hem()
set name = "Hem"
set category = "Emotes"

emote("hem", 1)

/mob/living/carbon/human/verb/clap()
set name = "Clap"
set category = "Emotes"

emote("clap",1)

/mob/living/carbon/human/verb/eyebrow()
set name = "Eyebrow"
set category = "Emotes"

emote("eyebrow",1)
/*
/mob/living/carbon/human/verb/chuckle()
set name = "Chuckle"
set category = "Emotes"
emote("chuckle",1)
*/
/mob/living/carbon/human/verb/cough()
set name = "Cough"
set category = "Emotes"

emote("cough",1)

/mob/living/carbon/human/verb/frown()
set name = "Frown"
set category = "Emotes"

emote("frown",1)

/mob/living/carbon/human/verb/nod()
set name = "Nod"
set category = "Emotes"

emote("nod",1)

/mob/living/carbon/human/verb/blush()
set name = "Blush"
set category = "Emotes"

emote("blush",1)

/mob/living/carbon/human/verb/wave()
set name = "Wave"
set category = "Emotes"

emote("wave",1)

/mob/living/carbon/human/verb/giggle()
set name = "Giggle"
set category = "Emotes"

emote("giggle",1)

/mob/living/carbon/human/verb/look()
set name = "Look"
set category = "Emotes"

emote("look",1)

/mob/living/carbon/human/verb/grin()
set name = "Grin"
set category = "Emotes"

emote("grin",1)

/mob/living/carbon/human/verb/cry()
set name = "Cry"
set category = "Emotes"

emote("cry",1)

/mob/living/carbon/human/verb/sigh()
set name = "Sigh"
set category = "Emotes"

emote("sigh",1)

/mob/living/carbon/human/verb/laugh()
set name = "Laugh"
set category = "Emotes"

emote("laugh",1)

/mob/living/carbon/human/verb/mumble()
set name = "Mumble"
set category = "Emotes"

emote("mumble",1)

/mob/living/carbon/human/verb/grumble()
set name = "Grumble"
set category = "Emotes"

emote("grumble",1)

/mob/living/carbon/human/verb/groan()
set name = "Groan"
set category = "Emotes"

emote("groan",1)

/mob/living/carbon/human/verb/mmoan()
set name = "Moan"
set category = "Emotes"

emote("moan",1)

/mob/living/carbon/human/verb/raise()
set name = "Raise Hand"
set category = "Emotes"

emote("raise",1)

/mob/living/carbon/human/verb/shake()
set name = "Shake"
set category = "Emotes"

emote("shake",1)

/mob/living/carbon/human/verb/shrug()
set name = "Shrug"
set category = "Emotes"

emote("shrug",1)

/mob/living/carbon/human/verb/smile()
set name = "Smile"
set category = "Emotes"

emote("smile",1)

/mob/living/carbon/human/verb/whimper()
set name = "Whimper"
set category = "Emotes"

emote("whimper",1)

/mob/living/carbon/human/verb/wink()
set name = "Wink"
set category = "Emotes"

emote("wink",1)

/mob/living/carbon/human/verb/yawn()
set name = "Yawn"
set category = "Emotes"

emote("yawn",1)

/mob/living/carbon/human/verb/hug()
set name = "Hug"
set category = "Emotes"

emote("hug",1)

/mob/living/carbon/human/verb/scream()
set name = "Scream"
set category = "Emotes"

emote("scream",1)

/mob/living/carbon/human/verb/emoteclearthroat()
set name = "Clear Throat"
set category = "Emotes"

emote("clearthroat",1)

/mob/living/carbon/human/verb/fap()
set name = "Fap"
set category = "Emotes"

emote("fap",1)
@@ -1,4 +1,8 @@
/mob/living/carbon/human/examine(mob/user)
user.visible_message("<small>[user] looks at [src].</small>")
if(get_dist(user,src) > 5)//Don't get descriptions of things far away.
to_chat(user, "<span class='info'>It's too far away to see clearly.</span>")
return
var/skipgloves = 0
var/skipsuitstorage = 0
var/skipjumpsuit = 0
@@ -49,7 +53,7 @@
if(is_synth && species.type != /datum/species/machine)
species_name += "Cyborg "
species_name += "[species.name]"
msg += ", <b><font color='[species.get_flesh_colour(src)]'> \a [species_name]!</font></b>"
// msg += ", <b><font color='[species.get_flesh_colour(src)]'> \a [species_name]!</font></b>"
var/extra_species_text = species.get_additional_examine_text(src)
if(extra_species_text)
msg += "[extra_species_text]<br>"
@@ -129,6 +133,14 @@
//buckled
if(buckled)
msg += "<span class='warning'>[T.He] [T.is] \icon[buckled] buckled to [buckled]!</span>\n"
if(str > user.str && str < (user.str + 5))
msg += "[T.He] looks stronger than you.\n"

if(str > (user.str + 5))
msg += "<b>[T.He] looks a lot stronger than you.</b>\n"

if(str < user.str)
msg += "[T.He] looks weaker than you.\n"

//Jitters
if(is_jittery)
@@ -177,16 +189,39 @@

if(fire_stacks)
msg += "[T.He] looks flammable.\n"

if(on_fire)
msg += "<span class='warning'>[T.He] [T.is] on fire!.</span>\n"

msg += "<span class='warning'>"


if(nutrition < 100)
msg += "[T.He] [T.is] severely malnourished.\n"
else if(nutrition >= 500)
msg += "[T.He] [T.is] quite chubby.\n"


msg += "</span>"

var/ssd_msg = species.get_ssd(src)
if(ssd_msg && (!should_have_organ(BP_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>\n"
else if(!client)
msg += "<span class='deadsay'>[T.He] [T.is] [ssd_msg].</span>\n"

var/mhealth = (getBruteLoss() + getFireLoss())//How injured they look. Not not nescessarily how hurt they actually are.

if(mhealth >= 25 && mhealth < 50)//Is the person a little hurt?
msg += "<span class='warning'><b>[T.He] looks somewhat injured.\n</b></span>"

if(mhealth >= 50 && mhealth < 75)//Hurt.
msg += "<span class='warning'><b>[T.He] looks injured.</b></span>\n"

if(mhealth >= 75)//Or incredibly hurt.
msg += "<span class='warning'><b>[T.He] looks incredibly injured.</b>\n</span>"

var/list/wound_flavor_text = list()
var/applying_pressure = ""
var/list/shown_objects = list()
@@ -219,19 +254,19 @@
else
if(E.is_stump())
wound_flavor_text[E.name] += "<b>[T.He] [T.has] a stump where [T.his] [organ_descriptor] should be.</b>\n"
if(E.wounds.len && E.parent)
wound_flavor_text[E.name] += "[T.He] [T.has] [E.get_wounds_desc()] on [T.his] [E.parent.name].<br>"
//if((E.wounds.len || E.open) && E.parent)
// wound_flavor_text[E.name] += "[T.He] [T.has] [E.get_wounds_desc()] on [T.his] [E.parent.name].<br>"
else
if(!is_synth && E.robotic >= ORGAN_ROBOT && (E.parent && E.parent.robotic < ORGAN_ROBOT))
wound_flavor_text[E.name] = "[T.He] [T.has] a [E.name].\n"
var/wounddesc = E.get_wounds_desc()
if(wounddesc != "nothing")
wound_flavor_text[E.name] += "[T.He] [T.has] [wounddesc] on [T.his] [E.name].<br>"
//var/wounddesc = E.get_wounds_desc()
//if(wounddesc != "nothing")
// wound_flavor_text[E.name] += "[T.He] [T.has] [wounddesc] on [T.his] [E.name].<br>"
if(!hidden || distance <=1)
if(E.dislocated > 0)
wound_flavor_text[E.name] += "[T.His] [E.joint] is dislocated!<br>"
if(((E.status & ORGAN_BROKEN) && E.brute_dam > E.min_broken_damage) || (E.status & ORGAN_MUTATED))
wound_flavor_text[E.name] += "[T.His] [E.name] is dented and swollen!<br>"
wound_flavor_text[E.name] += "[T.His] [E.name] is broken!<br>"

for(var/datum/wound/wound in E.wounds)
if(wound.embedded_objects.len)
@@ -334,13 +369,13 @@
return 0
else
return 0

/*
/mob/living/carbon/human/verb/pose()
set name = "Set Pose"
set desc = "Sets a description which will be shown when someone examines you."
set category = "IC"
pose = sanitize(input(usr, "This is [src]. [get_visible_gender() == MALE ? "He" : get_visible_gender() == FEMALE ? "She" : "They"]...", "Pose", null) as text)
pose = sanitize(input(usr, "This is [src]. [get_visible_gender() == MALE ? "He" : get_visible_gender() == FEMALE ? "She" : "They"] [get_visible_gender() == NEUTER ? "are" : "is"]...", "Pose", null) as text)
/mob/living/carbon/human/verb/set_flavor()
set name = "Set Flavour Text"
@@ -383,3 +418,4 @@
HTML +="<a href='?src=\ref[src];flavor_change=done'>\[Done\]</a>"
HTML += "<tt>"
src << browse(jointext(HTML,null), "window=flavor_changes;size=430x300")
*/
@@ -41,6 +41,10 @@
GLOB.human_mob_list |= src
..()

add_teeth()
bladder = rand(0,100)
bowels = rand(0, 100)

if(dna)
dna.ready_dna(src)
dna.real_name = real_name
@@ -57,8 +61,9 @@
/mob/living/carbon/human/Stat()
. = ..()
if(statpanel("Status"))
stat("Intent:", "[a_intent]")
stat("Move Mode:", "[m_intent]")
stat("ST:", "[str]")//Stats!
stat("DX:", "[dex]")
stat("IT:", "[int]")

if(evacuation_controller)
var/eta_status = evacuation_controller.get_status_panel_eta()
@@ -295,19 +300,18 @@
/mob/living/carbon/human/proc/get_visible_name()
var/face_name = get_face_name()
var/id_name = get_id_name("")
if((face_name == "Unknown") && id_name && (id_name != face_name))
if(id_name && (id_name != face_name) && face_name != "Unknown")
return "[face_name] (as [id_name])"
else if(id_name && (id_name != face_name) && face_name == "Unknown")//Hacky af.
return id_name
return face_name

//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable
//Also used in AI tracking people by face, so added in checks for head coverings like masks and helmets
/mob/living/carbon/human/proc/get_face_name()
var/obj/item/organ/external/H = get_organ(BP_HEAD)
if(!H || H.disfigured || H.is_stump() || !real_name || (HUSK in mutations) || (wear_mask && (wear_mask.flags_inv&HIDEFACE)) || (head && (head.flags_inv&HIDEFACE))) //Face is unrecognizeable, use ID if able
if(istype(wear_mask))
return wear_mask.visible_name
else
return "Unknown"
return "Unknown"
return real_name

//gets name from ID or PDA itself, ID inside PDA doesn't matter
@@ -323,6 +327,13 @@
return I.registered_name
return

/mob/living/carbon/human/proc/get_job_name()
if(wear_id)
var/obj/item/weapon/card/id/I = wear_id.GetIdCard()
if(I)
return I.assignment


//gets ID card object from special clothes slot or null.
/mob/living/carbon/human/proc/get_idcard()
if(wear_id)
@@ -544,13 +555,22 @@
return
if("general")
var/msg = sanitize(input(usr,"Update the general description of your character. This will be shown regardless of clothing, and may include OOC notes and preferences.","Flavor Text",html_decode(flavor_texts[href_list["flavor_change"]])) as message, extra = 0)
flavor_texts[href_list["flavor_change"]] = msg
flavor_texts[href_list["flavor_change"]] = post_edit_cp1251(sanitize(msg, extra = 0))
return
else
var/msg = sanitize(input(usr,"Update the flavor text for your [href_list["flavor_change"]].","Flavor Text",html_decode(flavor_texts[href_list["flavor_change"]])) as message, extra = 0)
flavor_texts[href_list["flavor_change"]] = msg
set_flavor()
flavor_texts[href_list["flavor_change"]] = post_edit_cp1251(sanitize(msg, extra = 0))
// set_flavor()
return
//Crafting
if (href_list["craft"])
var/turf/T = get_step(src, dir)
if(!T.Adjacent(src))
return 0
var/rname = href_list["craft"]
var/datum/crafting_recipe/R = crafting_recipes[rname]
R.make(src, T)

..()
return

@@ -666,6 +686,9 @@
src.visible_message("<span class='warning'>[src] throws up!</span>","<span class='warning'>You throw up!</span>")
playsound(loc, 'sound/effects/splat.ogg', 50, 1)

adjust_hygiene(-25)
add_event("hygiene", /datum/happiness_event/hygiene/vomitted)

var/turf/location = loc
if (istype(location, /turf/simulated))
location.add_vomit_floor(src, toxvomit)
@@ -844,6 +867,7 @@

species.create_organs(src) // Reset our organs/limbs.
restore_all_organs() // Reapply robotics/amputated status from preferences.
add_teeth()

if(!client || !key) //Don't boot out anyone already in the mob.
for (var/obj/item/organ/internal/brain/H in world)
@@ -861,6 +885,14 @@
losebreath = 0

..()
/mob/living/carbon/human/proc/add_teeth()
var/obj/item/organ/external/head/U = locate() in organs
if(istype(U))
U.teeth_list.Cut() //Clear out their mouth of teeth
var/obj/item/stack/teeth/T = new species.teeth_type(U)
U.max_teeth = T.max_amount //Set max teeth for the head based on teeth spawntype
T.amount = T.max_amount
U.teeth_list += T

/mob/living/carbon/human/proc/is_lung_ruptured()
var/obj/item/organ/internal/lungs/L = internal_organs_by_name[BP_LUNGS]
@@ -1095,6 +1127,8 @@
if(istype(C) && !C.mob_can_equip(src, slot, 1))
unEquip(C)

add_teeth()

return 1

/mob/living/carbon/human/proc/bloody_doodle()
@@ -1440,53 +1474,96 @@
if(src != M)
..()
else
exam_self()

if((SKELETON in mutations) && (!w_uniform) && (!wear_suit))
play_xylophone()

/mob/living/carbon/human/proc/exam_self()
if(!stat)
visible_message( \
"<span class='notice'>[src] examines [gender==MALE ? "himself" : "herself"].</span>", \
"<span class='notice'>You check yourself for injuries.</span>" \
"<span class='notice'><b>Let's see how I am doing.</b></span>" \
)
else//We don't want to spam the chat that we're checking ourselves for injuries when we're out fucking cold.
to_chat(src, "<span class='notice'><b>Let's see how I am doing.</b></span>")



//var/feels = 1 + round(org.pain/100, 0.1)
//var/brutedamage = org.brute_dam * feels
//var/burndamage = org.burn_dam * feels
/*
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"
*/
for(var/obj/item/organ/external/org in organs)
var/list/status = list()
var/hurts = org.get_pain() + org.get_damage()

if(!(chem_effects[CE_PAINKILLER] > 50))
switch(hurts)
if(1 to 25)
status += "<small>pain</small>"
if(25 to 75)
status += "pain"
if(75 to INFINITY)
status += "<big>PAIN</big>"

if(org.is_stump())
status += "MISSING"
if(org.status & ORGAN_MUTATED)
status += "MISSHAPEN"
if(org.status & ORGAN_BLEEDING)
status += "BLEEDING"
if(org.dislocated == 2)
status += "DISLOCATED"
if(org.status & ORGAN_BROKEN)
status += "BROKEN"
if(org.status & ORGAN_DEAD)
status += "NECROTIC"
if(!org.is_usable() || org.is_dislocated())
status += "UNUSABLE"
if(status.len)
to_chat(src, "<b>[capitalize(org.name)]:</b> <span class='danger'>[english_list(status)]!</span>")
else
to_chat(src, "<b>[capitalize(org.name)]:</b> <span class='notice'>OK</span>")

for(var/obj/item/organ/external/org in organs)
var/list/status = list()

var/feels = 1 + round(org.pain/100, 0.1)
var/brutedamage = org.brute_dam * feels
var/burndamage = org.burn_dam * feels

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 += "misshapen"
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)
/mob/living/carbon/human/throw_impact(atom/hit_atom)
if(iswall(hit_atom))
var/damage = rand(0, 10)
var/smashsound = pick("sound/effects/gore/smash[rand(1,3)].ogg", "sound/effects/gore/trauma1.ogg")
playsound(loc, smashsound, 50, 1, -1)

if((SKELETON in mutations) && (!w_uniform) && (!wear_suit))
play_xylophone()
var/blocked = run_armor_check(BP_HEAD,"melee")
apply_damage(damage, BRUTE, BP_HEAD, blocked)

blocked = run_armor_check(BP_CHEST,"melee")
apply_damage(damage, BRUTE, BP_CHEST, blocked)

blocked = run_armor_check(BP_GROIN,"melee")
apply_damage(damage, BRUTE, BP_GROIN, blocked)

updatehealth()
if(damage)
hit_atom.add_blood(src)
..()

else
..()

/mob/living/carbon/human/proc/resuscitate()
if(!is_asystole() || !should_have_organ(BP_HEART))
@@ -159,7 +159,7 @@

if(src.grabbed_by.len || src.buckled || !src.canmove || src==H || H.species.flags & NO_BLOCK)
accurate = 1 // certain circumstances make it impossible for us to evade punches
rand_damage = 5
rand_damage = 3

// Process evasion and blocking
var/miss_type = 0
@@ -222,12 +222,16 @@
if(HULK in H.mutations)
real_damage *= 2 // Hulks do twice the damage
rand_damage *= 2
real_damage = max(1, real_damage)
real_damage = (max(1, real_damage) * strToDamageModifier(H.str))

var/armour = run_armor_check(hit_zone, "melee")
// Apply additional unarmed effects.
attack.apply_effects(H, src, armour, rand_damage, hit_zone)

// Nerf attacks done while lying by 1/3rd
if (H.lying)
real_damage = max(real_damage * 0.66, 1)

// Finally, apply damage to target
apply_damage(real_damage, (attack.deal_halloss ? PAIN : BRUTE), hit_zone, armour, damage_flags=attack.damage_flags())

@@ -393,6 +393,7 @@ This function restores all organs.
if(BRUTE)
damage = damage*species.brute_mod
created_wound = organ.take_damage(damage, 0, damage_flags, used_weapon)
receive_damage()
if(BURN)
damage = damage*species.burn_mod
created_wound = organ.take_damage(0, damage, damage_flags, used_weapon)
@@ -7,6 +7,14 @@ meteor_act
*/

/obj/item/proc/get_attack_name()
if(sharp && edge)
return "slices"
else if(sharp && !edge)
return "stabs"
else
return "hits"

/mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone)

def_zone = check_zone(def_zone)
@@ -172,21 +180,56 @@ meteor_act
to_chat(user, "<span class='danger'>They are missing that limb!</span>")
return null

var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")


if(blocked == 100)
visible_message("<span class='danger'>[user] [I.get_attack_name()] [src]'s [affecting.name] with the [I], but it does no damage!")
return null

if(hit_zone == BP_CHEST || hit_zone == BP_MOUTH || hit_zone == BP_THROAT || hit_zone == BP_HEAD)//If we're lying and we're trying to aim high, we won't be able to hit.
if(user.lying && !src.lying)
to_chat(user, "<span class='notice'><b>I can't reach their [affecting.name]!</span></b>")
return null

return hit_zone

/mob/living/carbon/human/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)

var/obj/item/organ/external/affecting = get_organ(hit_zone)
if(!affecting)
return //should be prevented by attacked_with_item() but for sanity.

visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] in the [affecting.name] with [I.name] by [user]!</span>")
var/aim_zone = user.zone_sel.selecting


var/obj/item/organ/external/aimed = get_organ(aim_zone)

var/organ_hit = affecting.name//This is spaghetti, but it's done so that it recognizes when you hit the throat, and when you hit something else instead.

if(aim_zone == BP_THROAT)
organ_hit = "throat"

var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")


if(hit_zone != aim_zone && (aim_zone != BP_MOUTH) && (aim_zone != BP_THROAT) && (aim_zone != BP_EYES))//This is ugly but it works.
visible_message("<span class='danger'>[user] aimed for [src]\'s [aimed.name], but [I.get_attack_name()] \his [organ_hit] instead. [(blocked < 20 && blocked > 1) ? "Slight damage was done." : ""]</span>")

else if(blocked < 20 && blocked > 1)//This is ugly and it doesn't work.
visible_message("<span class='danger'>[user] [I.get_attack_name()] [src]\'s [organ_hit] with the [I.name]! Slight damage was done.<span class='danger'>")//visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] in the [organ_hit] with [I.name] by [user]! It only did a little damage!</span>")

else
visible_message("<span class='danger'>[user] [I.get_attack_name()] [src]\'s [organ_hit] with the [I.name]!<span class='danger'>")//visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] in the [organ_hit] with [I.name] by [user]!</span>")

receive_damage()

standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)

return blocked

/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
hit_zone = user.zone_sel.selecting
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if(!affecting)
return 0
@@ -205,7 +248,34 @@ meteor_act

if(effective_force > 10 || effective_force >= 5 && prob(33))
forcesay(GLOB.hit_appends) //forcesay checks stat already
if((I.damtype == BRUTE || I.damtype == PAIN) && prob(25 + (effective_force * 2)))

//Ok this block of text handles cutting arteries, tendons, and limbs off.
//First we cut an artery, the reason for that, is that arteries are funninly enough, not that lethal, and don't have the biggest impact. They'll still make you bleed out, but they're less immediately lethal.
if(I.sharp && prob(I.sharpness * 2) && !(affecting.status & ORGAN_ARTERY_CUT))
affecting.sever_artery()
if(affecting.artery_name == "cartoid artery")
src.visible_message("<span class='danger'>[user] slices [src]'s throat!</span>")
else
src.visible_message("<span class='danger'>[user] slices open [src]'s [affecting.artery_name] artery!</span>")

//Next tendon, which disables the limb, but does not remove it, making it easier to fix, and less lethal, than losing it.
else if(I.sharp && (I.sharpness * 2) && !(affecting.status & ORGAN_TENDON_CUT) && affecting.has_tendon)//Yes this is the same exactly probability again. But I'm running it seperate because I don't want the two to be exclusive.
affecting.sever_tendon()
src.visible_message("<span class='danger'>[user] slices open [src]'s [affecting.tendon_name] tendon!</span>")

//Finally if we pass all that, we cut the limb off. This should reduce the number of one hit sword kills.
else if(I.sharp && I.edge)
if(prob(I.sharpness * strToDamageModifier(user.str)))
affecting.droplimb(0, DROPLIMB_EDGE)

var/obj/item/organ/external/head/O = locate(/obj/item/organ/external/head) in src.organs

if(I.damtype == BRUTE && !I.edge && prob(I.force * (hit_zone == BP_MOUTH ? 6 : 0)) && O)//Knocking out teeth.
if(O.knock_out_teeth(get_dir(user, src), round(rand(28, 38) * ((I.force*1.5)/100))))
src.visible_message("<span class='danger'>[src]'s teeth sail off in an arc!</span>", \
"<span class='userdanger'>[src]'s teeth sail off in an arc!</span>")

else if((I.damtype == BRUTE || I.damtype == PAIN) && prob(25 + (effective_force * 2)))//Knocking them out.
if(!stat)
if(headcheck(hit_zone))
//Harder to score a stun but if you do it lasts a bit longer
@@ -217,9 +287,10 @@ meteor_act
if(prob(effective_force + 10))
visible_message("<span class='danger'>[src] has been knocked down!</span>")
apply_effect(6, WEAKEN, blocked)

//Apply blood
attack_bloody(I, user, effective_force, hit_zone)
if(user.skillcheck(user.melee_skill,0,0) == CRIT_SUCCESS)
resolve_critical_hit()

return 1

@@ -259,6 +330,16 @@ meteor_act
if(BP_CHEST)
bloody_body(src)

//All this is copypasta'd from projectile code. Basically there's a cool splat animation when someone gets hit by something.
var/splatter_dir = dir
var/turf/target_loca = get_turf(src)
splatter_dir = get_dir(attacker, target_loca)
target_loca = get_step(target_loca, splatter_dir)
var/blood_color = "#C80000"
blood_color = src.species.blood_color
new /obj/effect/overlay/temp/dir_setting/bloodsplatter(target_loca, splatter_dir, blood_color)
target_loca.add_blood(src)

/mob/living/carbon/human/proc/projectile_hit_bloody(obj/item/projectile/P, var/effective_force, var/hit_zone)
if(P.damage_type != BRUTE || P.nodamage)
return
@@ -348,6 +429,7 @@ meteor_act

if(!zone)
visible_message("<span class='notice'>\The [O] misses [src] narrowly!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1)
return

O.throwing = 0 //it hit, so stop moving
@@ -490,3 +572,112 @@ meteor_act
perm += perm_by_part[part]

return perm

/mob/living/carbon/human/kick_act(var/mob/living/user)
if(!..())//If we can't kick then this doesn't happen.
return
if(user == src)//Can't kick yourself dummy.
return

var/hit_zone = user.zone_sel.selecting
var/too_high_message = "You can't reach that high."
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if(!affecting || affecting.is_stump())
to_chat(user, "<span class='danger'>They are missing that limb!</span>")
return

var/armour = run_armor_check(hit_zone, "melee")
switch(hit_zone)
if(BP_CHEST)//If we aim for the chest we kick them in the direction we're facing.
if(lying)
var/turf/target = get_turf(src.loc)
var/range = src.throw_range
var/throw_dir = get_dir(user, src)
for(var/i = 1; i < range; i++)
var/turf/new_turf = get_step(target, throw_dir)
target = new_turf
if(new_turf.density)
break
src.throw_at(target, rand(1,3), src.throw_speed)
if(user.lying)
to_chat(user, too_high_message)
return

if(BP_MOUTH)//If we aim for the mouth then we kick their teeth out.
if(lying)
if(istype(affecting, /obj/item/organ/external/head) && prob(95))
var/obj/item/organ/external/head/U = affecting
U.knock_out_teeth(get_dir(user, src), rand(1,3))//Knocking out one tooth at a time.
else
to_chat(user, too_high_message)
return

if(BP_HEAD)
if(!lying)
to_chat(user, too_high_message)
return

var/kickdam = rand(0,15)
user.adjustStaminaLoss(rand(10,15))//Kicking someone is a big deal.
if(kickdam)
playsound(user.loc, 'sound/weapons/kick.ogg', 50, 0)
apply_damage(kickdam, BRUTE, hit_zone, armour)
user.visible_message("<span class=danger>[user] kicks [src] in the [affecting.name]!<span>")
admin_attack_log(user, src, "Has kicked [src]", "Has been kicked by [user].")
else
user.visible_message("<span class=danger>[user] tried to kick [src] in the [affecting.name], but missed!<span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1)


//We crit failed, let's see what happens to us.
/mob/living/proc/resolve_critical_miss(var/obj/item/I)
var/result = rand(1,3)

if(!I)
visible_message("<span class='danger'>[src] punches themself in the face!</span>")
attack_hand(src)
return

switch(result)
if(1)//They drop their weapon.
visible_message("<span class='danger'><big>CRITICAL FAILURE! \The [I] flies out of [src]'s hand!</big></span>")
drop_from_inventory(I)
throw_at(get_edge_target_turf(I, pick(alldirs)), rand(1,3), throw_speed)//Throw that sheesh away
return
if(2)
visible_message("<span class='danger'><big>CRITICAL FAILURE! [src] botches the attack, stumbles, and falls!</big></span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1)
Weaken(1)
Stun(3)
return
if(3)
visible_message("<span class='danger'><big>CRITICAL FAILURE! [src] botches the attack and hits themself!</big></span>")
attackby(I, src)

/mob/living/proc/resolve_critical_hit()
var/result = rand(1,3)

switch(result)
if(1)
visible_message("<span class='danger'><big>CRITICAL HIT! IT MUST BE PAINFUL</big></span>")
apply_damage(rand(5,10), BRUTE)
return

if(2)
visible_message("<span class='danger'><big>CRITICAL HIT! [src] is stunned!</big></span>")
Weaken(1)
Stun(3)
return

if(3)
visible_message("<span class='danger'><big>CRITICAL HIT! [src] is knocked unconcious by the blow!</big></span>")
apply_effect(20, PARALYZE)
return

/*
//Add screaming here.
/mob/living/carbon/human/IgniteMob()
..()
if(!stat &&)
*/
@@ -110,7 +110,11 @@
var/obj/machinery/machine_visual //machine that is currently applying visual effects to this mob. Only used for camera monitors currently.

var/innate_heal = 1

var/shock_stage

var/obj/item/grab/current_grab_type // What type of grab they use when they grab someone.
var/skin_state = SKIN_NORMAL
var/obj/screen/fov = null//The screen object because I can't figure out how the hell TG does their screen objects so I'm just using legacy code.
var/usefov = 1
var/decaylevel = 0 //For rotting bodies
@@ -65,13 +65,18 @@

if(aiming && aiming.aiming_at) tally += 5 // Iron sights make you slower, it's a well-known fact.

if(facing_dir) tally += 3 //Locking direction will slow you down.

if(FAT in src.mutations)
tally += 1.5
if (bodytemperature < 283.222)
tally += (283.222 - bodytemperature) / 10 * 1.75

tally += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow

if(staminaloss >= 75)
tally += 2

if(mRun in mutations)
tally = 0

@@ -264,6 +264,8 @@ This saves us from having to call add_fingerprint() any time something is put in
src.belt = W
W.equipped(src, slot)
update_inv_belt(redraw_mob)
if(W.equipsound)//So like a sword being sheathed.
playsound(src, W.equipsound, 50, 1)
if(slot_wear_id)
src.wear_id = W
W.equipped(src, slot)
@@ -257,6 +257,7 @@
to_chat(src, "<span class='warning'>You feel strange!</span>")
adjustCloneLoss(5 * RADIATION_SPEED_COEFFICIENT)
emote("gasp")
gasp_sound()
if(radiation > 150)
damage = 8
radiation -= 4 * RADIATION_SPEED_COEFFICIENT
@@ -566,6 +567,8 @@
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
blinded = 1
silent = 0
handle_decay()

else //ALIVE. LIGHTS ARE ON
updatehealth() //TODO

@@ -577,11 +580,21 @@

if(hallucination_power)
handle_hallucinations()
handle_combat_mode()

handle_smelly_things()

handle_happiness()

handle_hygiene()

handle_lust()


if(get_shock() >= species.total_health)
if(!stat)
to_chat(src, "<span class='warning'>[species.halloss_message_self]</span>")
src.visible_message("<B>[src]</B> [species.halloss_message].")
//to_chat(src, "<span class='warning'>[species.halloss_message_self]</span>")
src.visible_message("<span class='warning'><B>[src]</B> gives into the pain!</span>")//("<B>[src]</B> [species.halloss_message].")
Paralyse(10)

if(paralysis || sleeping)
@@ -600,7 +613,7 @@
if(!paralysis)
emote("snore")
else
emote("groan")
agony_moan()//emote("groan")
if(prob(2) && is_asystole() && isSynthetic())
visible_message(src, "<b>[src]</b> [pick("emits low pitched whirr","beeps urgently")]")
//CONSCIOUS
@@ -648,6 +661,7 @@
if (nutrition > 0)
nutrition = max (0, nutrition - species.hunger_factor)

CheckStamina()
return 1

/mob/living/carbon/human/handle_regular_hud_updates()
@@ -754,6 +768,20 @@
if(150 to 250) nutrition_icon.icon_state = "nutrition3"
else nutrition_icon.icon_state = "nutrition4"

if(stamina_icon)
switch((staminaloss))
if(100 to INFINITY) stamina_icon.icon_state = "stamina10"
if(90 to 100) stamina_icon.icon_state = "stamina9"
if(80 to 90) stamina_icon.icon_state = "stamina8"
if(70 to 80) stamina_icon.icon_state = "stamina7"
if(60 to 70) stamina_icon.icon_state = "stamina6"
if(50 to 60) stamina_icon.icon_state = "stamina5"
if(40 to 50) stamina_icon.icon_state = "stamina4"
if(30 to 40) stamina_icon.icon_state = "stamina3"
if(20 to 30) stamina_icon.icon_state = "stamina2"
if(10 to 20) stamina_icon.icon_state = "stamina1"
else stamina_icon.icon_state = "stamina0"

if(isSynthetic())
var/obj/item/organ/internal/cell/C = internal_organs_by_name[BP_CELL]
if (istype(C))
@@ -820,6 +848,11 @@
bodytemp.icon_state = "temp-1"
else
bodytemp.icon_state = "temp0"
if(resting)
rest.icon_state = "rest1"
else
rest.icon_state = "rest0"

return 1

/mob/living/carbon/human/handle_random_events()
@@ -870,6 +903,7 @@
if(!(M.status_flags & GODMODE))
M.adjustBruteLoss(5)
nutrition += 10
handle_excrement()

/mob/living/carbon/human/proc/handle_changeling()
if(mind && mind.changeling)
@@ -884,56 +918,62 @@

if(is_asystole())
shock_stage = max(shock_stage, 61)
var/traumatic_shock = get_shock()
if(traumatic_shock >= max(30, 0.8*shock_stage))
if(get_shock() >= max(50, shock_stage))
shock_stage += 1
else
shock_stage = min(shock_stage, 160)
var/recovery = 1
if(traumatic_shock < 0.5 * shock_stage) //lower shock faster if pain is gone completely
recovery++
if(traumatic_shock < 0.25 * shock_stage)
recovery++
shock_stage = max(shock_stage - recovery, 0)
shock_stage = max(shock_stage-1, 0)
return

if(stat) return 0

if(shock_stage == 10)
// Please be very careful when calling custom_pain() from within code that relies on pain/trauma values. There's the
// possibility of a feedback loop from custom_pain() being called with a positive power, incrementing pain on a limb,
// which triggers this proc, which calls custom_pain(), etc. Make sure you call it with 0 power in these cases!
custom_pain("[pick("It hurts so much", "You really need some painkillers", "Dear god, the pain")]!", 10,nohalloss = 0)
custom_pain("[pick("It hurts so much", "You really need some painkillers", "Dear god, the pain")]!", 10, nohalloss = 0)

if(shock_stage >= 30)
if(shock_stage == 30) visible_message("<b>[src]</b> is having trouble keeping \his eyes open.")
if(shock_stage == 30)
visible_message("<b>[src]</b> is having trouble keeping \his eyes open.")
if(prob(30))
eye_blurry = max(2, eye_blurry)
stuttering = max(stuttering, 5)

if(shock_stage == 40)
custom_pain("[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!", 0)
src.agony_moan()
//emote("moan")

if (shock_stage >= 60)
if(shock_stage == 60) visible_message("<b>[src]</b>'s body becomes limp.")
//if(shock_stage == 60)
// visible_message("<b>[src]</b>'s body becomes limp.")
if (prob(2))
custom_pain("[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!", shock_stage, nohalloss = 0)
Weaken(10)
custom_pain("[pick("The pain is excruciating", "Please, just end the pain")]!", shock_stage, nohalloss = 0)
adjustStaminaLoss(20)
// flash_weak_pain()
// stuttering = max(stuttering, 5)

if(shock_stage >= 80)
if (prob(5))
custom_pain("[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!", shock_stage, nohalloss = 0)
Weaken(20)
custom_pain("[pick("The pain is excruciating", "Please, just end the pain")]!", shock_stage, nohalloss = 0)
adjustStaminaLoss(20)
// flash_weak_pain()
// stuttering = max(stuttering, 5)

if(shock_stage >= 120)
if (prob(2))
custom_pain("[pick("You black out", "You feel like you could die any moment now", "You're about to lose consciousness")]!", shock_stage, nohalloss = 0)
Paralyse(5)
// flash_pain()
// stuttering = max(stuttering, 5)

if(shock_stage == 150)
visible_message("<b>[src]</b> can no longer stand, collapsing!")
Weaken(20)
//visible_message("<b>[src]</b> can no longer stand, collapsing!")
adjustStaminaLoss(20)//Weaken(20)

if(shock_stage >= 150)
Weaken(20)
//if(shock_stage >= 150)
// Weaken(20)

/*
Called by life(), instead of having the individual hud items update icons each tick and check for status changes
@@ -1147,3 +1187,75 @@
..()
if(XRAY in mutations)
set_sight(sight|SEE_TURFS|SEE_MOBS|SEE_OBJS)

/mob/living/carbon/human/proc/handle_decay()
var/decaytime = world.time - timeofdeath
var/image/flies = image('icons/effects/effects.dmi', "rotten")//This is a hack, there has got to be a safer way to do this but I don't know it at the moment.

if(isSynthetic())
return

if(decaytime <= 6000) //10 minutes for decaylevel1 -- stinky
return

if(decaytime > 6000 && decaytime <= 12000)//20 minutes for decaylevel2 -- bloated and very stinky
decaylevel = 1
overlays -= flies
overlays += flies

if(decaytime > 12000 && decaytime <= 18000)//30 minutes for decaylevel3 -- rotting and gross
decaylevel = 2

if(decaytime > 18000 && decaytime <= 27000)//45 minutes for decaylevel4 -- skeleton
decaylevel = 3

if(decaytime > 27000)
decaylevel = 4
overlays -= flies
flies = null
ChangeToSkeleton()
return //No puking over skeletons, they don't smell at all!


for(var/mob/living/carbon/human/H in range(decaylevel, src))
if(prob(2))
if(istype(loc,/obj/item/bodybag))
return
if(H.wear_mask)
return
if(H.stat == DEAD)//This shouldn't even need to be a fucking check.
return
to_chat(H, "<spawn class='warning'>You smell something foul...")
H.add_event("disgust", /datum/happiness_event/disgust/verygross)
if(prob(75))
H.vomit()

//So that people will stop shitting in the fucking hallways all the time. Actually this will probably encourage them.
/mob/living/carbon/human/proc/handle_smelly_things()
if(wear_mask)
return

if(/obj/effect/decal/cleanable/poo in range(5, src))
if(prob(2))
to_chat(src, "<spawn class='warning'>Something smells like shit...")
add_event("disgust", /datum/happiness_event/disgust/verygross)
if(prob(50))
vomit()

for(var/obj/item/weapon/reagent_containers/food/snacks/poo/P in range(5, src))
if(istype(P.loc, /obj/machinery/disposal) || istype(P.loc, /obj/item/weapon/storage/bag))
return

if(prob(2))
to_chat(src, "<spawn class='warning'>Something smells like shit...")
add_event("disgust", /datum/happiness_event/disgust/verygross)
if(prob(50))
vomit()


/mob/living/carbon/human/proc/handle_gas_mask_sound()
//var/soundcooldown = world.time
if(istype(wear_mask, /obj/item/clothing/mask/gas))
//if((world.time - soundcooldown) >= 300)
var/mask_sound = pick('sound/effects/gasmask1.ogg','sound/effects/gasmask2.ogg','sound/effects/gasmask3.ogg','sound/effects/gasmask4.ogg','sound/effects/gasmask5.ogg','sound/effects/gasmask6.ogg','sound/effects/gasmask7.ogg','sound/effects/gasmask8.ogg','sound/effects/gasmask9.ogg','sound/effects/gasmask10.ogg')
playsound(src, mask_sound, 50, 1)
@@ -0,0 +1,67 @@
//Commented out debugging shit.
/*
/mob/living/carbon/human/verb/toggle_combat_mode()
set name = "Toggle Combat Mode"
set category = "Combat"
if(combat_mode)
combat_mode = 0
to_chat(src, "You toggle off combat mode.")
else
combat_mode = 1
to_chat(src, "You toggle on combat mode.")
/mob/living/carbon/human/verb/toggle_dodge_parry()
set name = "Toggle Defense Intent"
set category = "Combat"
if(defense_intent == I_DODGE)
defense_intent = I_PARRY
to_chat(src, "You will now parry.")
else
defense_intent = I_DODGE
to_chat(src, "You will now dodge.")
*/

//Going here till I find a better place for it.
/mob/living/proc/handle_combat_mode()//Makes it so that you can't regain stamina in combat mode.
if(combat_mode)
if(staminaloss < 25)
adjustStaminaLoss(1)

/mob/living/proc/attempt_dodge()//Handle parry is an object proc and it's, its own thing.
if(combat_mode && (defense_intent == I_DODGE) && !lying)//Todo, make use of the check_shield_arc proc to make sure you can't dodge from behind.
if(staminaloss < 50 && statscheck(dex, 20))//You gotta be the master of dexterity to dodge every time.
do_dodge()
return 1
else if(staminaloss >= 50 && prob(10))
do_dodge()
return 1

/mob/living/proc/do_dodge()
var/lol = pick(cardinal)//get a direction.
adjustStaminaLoss(15)//add some stamina loss
playsound(loc, 'sound/weapons/punchmiss.ogg', 80, 1)//play a sound
step(src,lol)//move them
visible_message("<b><big>[src.name] dodges out of the way!!</big></b>")//send a message
//be on our way


/mob/proc/surrender()//Surrending. I need to put this in a different file.
if(!incapacitated())
Stun(5)
Weaken(5)
visible_message("<b>[src] surrenders!</b>")
playsound(src, 'sound/effects/surrender.ogg', 50, 1)

/mob/proc/mob_rest()
if(resting && !stunned && !weakened)//The incapacitated proc includes resting for whatever fucking stupid reason I hate SS13 code so fucking much.
visible_message("<span class='notice'>[usr] is trying to get up.</span>")
if(do_after(src, 20))
resting = 0
rest.icon_state = "rest0"
return

else
resting = 1
rest.icon_state = "rest1"
@@ -49,7 +49,7 @@ var/global/list/sparring_attack_cache = list()

var/stun_chance = rand(0, 100)

if(attack_damage >= 5 && armour < 100 && !(target == user) && stun_chance <= attack_damage * 5) // 25% standard chance
if(attack_damage >= 3 && armour < 100 && !(target == user) && stun_chance <= attack_damage * 5) // 25% standard chance
switch(zone) // strong punches can have effects depending on where they hit
if(BP_HEAD, BP_EYES, BP_MOUTH)
// Induce blurriness
@@ -0,0 +1,120 @@
/////////////VISION CONE///////////////
//Vision cone code by Matt and Honkertron. This vision cone code allows for mobs and/or items to blocked out from a players field of vision.
//This code makes use of the "cone of effect" proc created by Lummox, contributed by Jtgibson. More info on that here:
//http://www.byond.com/forum/?post=195138
///////////////////////////////////////

//"Made specially for Otuska"
// - Honker



//Defines.
#define OPPOSITE_DIR(D) turn(D, 180)

client/
var/list/hidden_atoms = list()
var/list/hidden_mobs = list()



atom/proc/InCone(atom/center = usr, dir = NORTH)
if(get_dist(center, src) == 0 || src == center) return 0
var/d = get_dir(center, src)

if(!d || d == dir) return 1
if(dir & (dir-1))
return (d & ~dir) ? 0 : 1
if(!(d & dir)) return 0
var/dx = abs(x - center.x)
var/dy = abs(y - center.y)
if(dx == dy) return 1
if(dy > dx)
return (dir & (NORTH|SOUTH)) ? 1 : 0
return (dir & (EAST|WEST)) ? 1 : 0

mob/dead/InCone(mob/center = usr, dir = NORTH)
return

mob/living/InCone(mob/center = usr, dir = NORTH)
. = ..()
for(var/obj/item/weapon/grab/G in center)//TG doesn't have the grab item. But if you're porting it and you do then uncomment this.
if(src == G.affecting)
return 0
else
return .


proc/cone(atom/center = usr, dir = NORTH, list/list = oview(center))
for(var/atom/O in list) if(!O.InCone(center, dir)) list -= O
return list

mob/proc/update_vision_cone()
return

mob/living/carbon/human/update_vision_cone()
var/delay = 10
if(src.client)
var/image/I = null
for(I in src.client.hidden_atoms)
I.override = 0
spawn(delay)
qdel(I)
delay += 10
check_fov()
src.client.hidden_atoms = list()
src.client.hidden_mobs = list()
src.fov.dir = src.dir
if(fov.alpha != 0)
var/mob/living/M
for(M in cone(src, OPPOSITE_DIR(src.dir), view(10, src)))
I = image("split", M)
I.override = 1
src.client.images += I
src.client.hidden_atoms += I
src.client.hidden_mobs += M
if(src.pulling == M)//If we're pulling them we don't want them to be invisible, too hard to play like that.
I.override = 0

else if(M.footstep >= 1)
M.in_vision_cones[src.client] = 1

//Optional items can be made invisible too. Uncomment this part if you wish to items to be invisible.
//var/obj/item/O
//for(O in cone(src, OPPOSITE_DIR(src.dir), oview(src)))
// I = image("split", O)
// I.override = 1
// src.client.images += I
// src.client.hidden_atoms += I

else
return

mob/living/carbon/human/proc/SetFov(var/n)
if(!n)
hide_cone()
else
show_cone()

mob/living/carbon/human/proc/check_fov()

if(resting || lying || client.eye != client.mob)
src.fov.alpha = 0
return

else if(src.usefov)
show_cone()

else
hide_cone()

//Making these generic procs so you can call them anywhere.
mob/living/carbon/human/proc/show_cone()
if(src.fov)
src.fov.alpha = 255
src.usefov = 1

mob/living/carbon/human/proc/hide_cone()
if(src.fov)
src.fov.alpha = 0
src.usefov = 0
@@ -0,0 +1,15 @@
/mob/living/simple_animal/hostile/beepis
name = "beepis"
desc = "I don't know some fuckin' thing?"
icon_state = "beepis"
icon_living = "beepis"
icon_dead = "beepis_dead"
icon_gib = "beepis"
speak_chance = 0
turns_per_move = 5
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "hits the"
speed = 4
maxHealth = 25
health = 25
@@ -1,5 +1,7 @@
//handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying
/mob/proc/update_Login_details()
var/serbname = "[server_name]: [station_name()]"
winset(src, null, "mainwindow.title='[serbname]'")
//Multikey checks and logging
lastKnownIP = client.address
computer_id = client.computer_id
@@ -628,8 +628,8 @@

if(statpanel("Status"))
if(ticker && ticker.current_state != GAME_STATE_PREGAME)
stat("Local Time", stationtime2text())
stat("Local Date", stationdate2text())
//stat("Local Time", stationtime2text())
//stat("Local Date", stationdate2text())
stat("Round Duration", roundduration2text())
if(client.holder || isghost(client.mob))
stat("Location:", "([x], [y], [z]) [loc]")
@@ -704,8 +704,6 @@

if(lying)
set_density(0)
if(l_hand) unEquip(l_hand)
if(r_hand) unEquip(r_hand)
else
set_density(initial(density))
reset_layer()
@@ -725,6 +723,7 @@
regenerate_icons()
else if( lying != lying_prev )
update_icons()
update_vision_cone()

return canmove

@@ -773,6 +772,8 @@
if(status_flags & CANSTUN)
facing_dir = null
stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun
if(l_hand) unEquip(l_hand)
if(r_hand) unEquip(r_hand)
return

/mob/proc/SetStunned(amount) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned"
@@ -790,6 +791,7 @@
facing_dir = null
weakened = max(max(weakened,amount),0)
update_canmove() //updates lying, canmove and icons
resting = 1
return

/mob/proc/SetWeakened(amount)
@@ -808,6 +810,9 @@
if(status_flags & CANPARALYSE)
facing_dir = null
paralysis = max(max(paralysis,amount),0)
if(l_hand) unEquip(l_hand)
if(r_hand) unEquip(r_hand)
resting = 1
return

/mob/proc/SetParalysis(amount)
@@ -823,6 +828,9 @@
/mob/proc/Sleeping(amount)
facing_dir = null
sleeping = max(max(sleeping,amount),0)
if(l_hand) unEquip(l_hand)
if(r_hand) unEquip(r_hand)
resting =1
return

/mob/proc/SetSleeping(amount)
@@ -849,9 +857,6 @@
/mob/proc/get_species()
return ""

/mob/proc/flash_weak_pain()
flick("weak_pain",pain)

/mob/proc/get_visible_implants(var/class = 0)
var/list/visible_implants = list()
for(var/obj/item/O in embedded)
@@ -967,18 +972,10 @@ mob/proc/yank_out_object()
/mob/update_icon()
return

/mob/verb/face_direction()

set name = "Face Direction"
set category = "IC"
set src = usr

/mob/proc/face_direction()
set_face_dir()

if(!facing_dir)
to_chat(usr, "You are now not facing anything.")
else
to_chat(usr, "You are now facing [dir2text(facing_dir)].")

/mob/proc/set_face_dir(var/newdir)
if(!isnull(facing_dir) && newdir == facing_dir)
facing_dir = null
@@ -36,6 +36,20 @@
var/obj/screen/gun/move/gun_move_icon = null
var/obj/screen/gun/run/gun_run_icon = null
var/obj/screen/gun/mode/gun_setting_icon = null
var/obj/screen/stamina_icon = null
var/obj/screen/kick_icon = null
var/obj/screen/jump_icon = null
var/obj/screen/noise = null
var/obj/screen/fixeye = null
var/obj/screen/rest = null
var/obj/screen/combat_icon = null
var/obj/screen/combat_intent_icon = null
var/obj/screen/surrender = null
var/obj/screen/happiness_icon = null
var/obj/screen/wield_icon = null

var/obj/screen/noise2 = null//unused
var/obj/screen/noise3 = null//unused

var/obj/screen/movable/ability_master/ability_master = null

@@ -92,14 +106,22 @@

var/shakecamera = 0
var/a_intent = I_HELP//Living
var/defense_intent = I_DODGE//Living. For dodging and parrying.
var/m_intent = "run"//Living
var/middle_click_intent = null //For doing different things with middle click.
var/combat_mode = 0//Living
var/using_alt_hud = 0 //For the lunahud.
var/silent = null //Living. Can't talk. Value goes down every life proc.
var/obj/buckled = null//Living
var/obj/item/l_hand = null//Living
var/obj/item/r_hand = null//Living
var/obj/item/weapon/back = null//Human/Monkey
var/obj/item/weapon/storage/s_active = null//Carbon
var/obj/item/clothing/mask/wear_mask = null//Carbon


var/datum/hud/hud_used = null

var/list/grabbed_by = list( )

var/in_throw_mode = 0
@@ -161,4 +183,10 @@
var/memory = ""
var/flavor_text = ""

var/nabbing = 0 // Whether a creature with a CAN_NAB tag is grabbing normally or in nab mode.
var/nabbing = 0 // Whether a creature with a CAN_NAB tag is grabbing normally or in nab mode.

var/has_limbs = 1//For crawling

var/scrambling = 0//For crawling.

var/emote_cd = 0//Emote cooldown.
@@ -124,6 +124,8 @@ var/list/global/organ_rel_size = list(
zone = BP_HEAD
if(BP_MOUTH)
zone = BP_HEAD
if(BP_THROAT)
zone = BP_HEAD
return zone

// Returns zone with a certain probability. If the probability fails, or no zone is specified, then a random body part is chosen.
@@ -226,9 +228,9 @@ proc/slur(phrase)
if(1,3,5,8) newletter="[lowertext(newletter)]"
if(2,4,6,15) newletter="[uppertext(newletter)]"
if(7) newletter+="'"
//if(9,10) newletter="<b>[newletter]</b>"
//if(11,12) newletter="<big>[newletter]</big>"
//if(13) newletter="<small>[newletter]</small>"
if(9,10) newletter="<b>[newletter]</b>"
if(11,12) newletter="<big>[newletter]</big>"
if(13) newletter="<small>[newletter]</small>"
newphrase+="[newletter]";counter-=1
return newphrase

@@ -273,6 +275,35 @@ proc/Gibberish(t, p)//t is the inputted message, and any value higher than 70 fo

return returntext

/proc/lisp(message, intensity=100) //Intensity = how hard will the dude be lisped
message = html_decode(message)
message = prob(intensity) ? replacetext(message, "f", "ph") : message
message = prob(intensity) ? replacetext(message, "t", "ph") : message
message = prob(intensity) ? replacetext(message, "s", "sh") : message
message = prob(intensity) ? replacetext(message, "th", "hh") : message
message = prob(intensity) ? replacetext(message, "ck", "gh") : message
message = prob(intensity) ? replacetext(message, "c", "gh") : message
message = prob(intensity) ? replacetext(message, "k", "gh") : message
return message

/proc/tongueless(message)
message = html_decode(message)
message = replacetext(message, "c", "h")
message = replacetext(message, "d", "a")
message = replacetext(message, "i", "a")
message = replacetext(message, "k", "a")
message = replacetext(message, "j", "a")
message = replacetext(message, "l", "a")
message = replacetext(message, "n", "a")
message = replacetext(message, "q", "h")
message = replacetext(message, "r", "a")
message = replacetext(message, "s", "h")
message = replacetext(message, "t", "a")
message = replacetext(message, "v", "h")
message = replacetext(message, "x", "a")
message = replacetext(message, "y", "a")
message = replacetext(message, "z", "h")
return message

/proc/ninjaspeak(n)
/*
@@ -1,7 +1,7 @@
/var/obj/effect/lobby_image = new/obj/effect/lobby_image()

/obj/effect/lobby_image
name = "Baystation12"
name = "InterBay"
desc = "This shouldn't be read."
screen_loc = "WEST,SOUTH"

@@ -40,6 +40,6 @@
new_player_panel()
spawn(40)
if(client)
handle_privacy_poll()
//handle_privacy_poll() Fucking Bay POLL - removed.
client.playtitlemusic()
maybe_send_staffwarns("connected as new player")
@@ -0,0 +1,398 @@
/*#####SHIT AND PISS#####
##Ok there's a lot of stupid shit here. Literally, but let me explain a bit why I put this here.
##I feel like poo and pee add a degree of autistic realism that you wouldn't otherwise get. And I'm autistic about that kind of thing.
##This file contains all the reagents, decals, objects and life procs. These procs are used in human/life.dm and human/emote.dm
##Have some shitty fun. - Matt
*/

//####DEFINES####

/mob
var/bladder = 0
var/bowels = 0

//#####DECALS#####
/obj/effect/decal/cleanable/poo
name = "poo stain"
desc = "Well that stinks."
density = 0
anchored = 1
layer = 2
icon = 'icons/effects/pooeffect.dmi'
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7", "floor8")
var/dried = 0


/obj/effect/decal/cleanable/poo/New()
icon = 'icons/effects/pooeffect.dmi'
icon_state = pick(src.random_icon_states)
for(var/obj/effect/decal/cleanable/poo/shit in src.loc)
if(shit != src)
qdel(shit)
spawn(6000)
dried = 1
name = "dried poo stain"
desc = "It's a dried poo stain..."


/obj/effect/decal/cleanable/poo/tracks
icon_state = "tracks"
random_icon_states = null

/obj/effect/decal/cleanable/poo/drip
name = "drips of poo"
desc = "It's brown."
density = 0
anchored = 1
layer = 2
icon = 'icons/effects/pooeffect.dmi'
icon_state = "drip1"
random_icon_states = list("drip1", "drip2", "drip3", "drip4", "drip5")

//This proc is really deprecated.
/*/obj/effect/decal/cleanable/poo/proc/streak(var/list/directions)
spawn (0)
var/direction = pick(directions)
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
sleep(3)
if (i > 0)
new /obj/effect/decal/cleanable/poo(src.loc)
if (step_to(src, get_step(src, direction), 0))
break
*/

/obj/effect/decal/cleanable/poo/Crossed(AM as mob|obj, var/forceslip = 0)
if (istype(AM, /mob/living/carbon) && src.dried == 0)
var/mob/living/carbon/M = AM
if (M.m_intent == "walk")
return

if(prob(5))
M.slip("poo")

//These aren't needed for now.
///obj/effect/decal/cleanable/poo/tracks/Crossed(AM as mob|obj)
// return

//obj/effect/decal/cleanable/poo/drip/Crossed(AM as mob|obj)
// return

/obj/effect/decal/cleanable/urine
name = "urine stain"
desc = "Someone couldn't hold it.."
density = 0
anchored = 1
layer = 2
icon = 'icons/effects/pooeffect.dmi'
icon_state = "pee1"
random_icon_states = list("pee1", "pee2", "pee3")
var/dried = 0

/obj/effect/decal/cleanable/urine/Crossed(AM as mob|obj)
if (istype(AM, /mob/living/carbon))
var/mob/living/carbon/M = AM
if ((ishuman(M) && istype(M:shoes, /obj/item/clothing/shoes/galoshes)) || M.m_intent == "walk")
return

if((!dried) && prob(5))
M.slip("urine")

/obj/effect/decal/cleanable/urine/New()
..()
icon_state = pick(random_icon_states)
//spawn(10) src.reagents.add_reagent("urine",5)
for(var/obj/effect/decal/cleanable/urine/piss in src.loc)
if(piss != src)
qdel(piss)

spawn(800)
dried = 1
name = "dried urine stain"
desc = "That's a dried crusty urine stain. Fucking janitors."



/obj/effect/decal/cleanable/cum
name = "cum"
desc = "It's pie cream from a cream pie. Or not..."
density = 0
layer = 2
icon = 'honk/icons/effects/cum.dmi'
blood_DNA = list()
anchored = 1
random_icon_states = list("cum1", "cum3", "cum4", "cum5", "cum6", "cum7", "cum8", "cum9", "cum10", "cum11", "cum12")


/obj/effect/decal/cleanable/cum/New()
..()
icon_state = pick(random_icon_states)
for(var/obj/effect/decal/cleanable/cum/jizz in src.loc)
if(jizz != src)
qdel(jizz)


//#####REAGENTS#####

//SHIT
/datum/reagent/poo
name = "poo"
id = "poo"
description = "It's poo."
reagent_state = LIQUID
color = "#643200"
taste_description = "literal shit"


/datum/reagent/poo/on_mob_life(var/mob/living/M)
if(!M)
M = holder.my_atom

M.adjustToxLoss(1)
holder.remove_reagent(src.id, 0.2)
..()
return

//TO MAKE add_poo() PROC
/* reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
src = null
if(istype(M, /mob/living/carbon/human) && method==TOUCH)
if(M:wear_suit) M:wear_suit.add_poo()
if(M:w_uniform) M:w_uniform.add_poo()
if(M:shoes) M:shoes.add_poo()
if(M:gloves) M:gloves.add_poo()
if(M:head) M:head.add_poo()
//if(method==INGEST)
// if(prob(20))
// M.contract_disease(new /datum/disease/gastric_ejections)
// holder.add_reagent("gastricejections", 1)
// M:toxloss += 0.1
// holder.remove_reagent(src.id, 0.2)
*/

/datum/reagent/poo/touch_turf(var/turf/T)
src = null
if(!istype(T, /turf/space))
new /obj/effect/decal/cleanable/poo(T)

//URINE
/datum/reagent/urine
name = "urine"
id = "urine"
description = "It's pee."
reagent_state = LIQUID
color = COLOR_YELLOW
taste_description = "urine"

/datum/reagent/urine/touch_turf(var/turf/T)
src = null
if(!istype(T, /turf/space))
new /obj/effect/decal/cleanable/urine(T)

//SEMEN
/datum/reagent/semen
name = "semen"
id = "semen"
description = "It's semen."
reagent_state = LIQUID
color = COLOR_WHITE
taste_description = "salt"

/datum/reagent/semen/touch_turf(var/turf/T)
src = null
if(!istype(T, /turf/space))
new /obj/effect/decal/cleanable/cum(T)

/obj/item/weapon/reagent_containers/food/snacks/poo
name = "poo"
desc = "A chocolately surprise!"
icon = 'icons/obj/poop.dmi'
icon_state = "poop2"
item_state = "poop"

/obj/item/weapon/reagent_containers/food/snacks/poo/New()
..()
icon_state = pick("poop1", "poop2", "poop3", "poop4", "poop5", "poop6", "poop7")
reagents.add_reagent("poo", 10)
bitesize = 3

/obj/item/weapon/reagent_containers/food/snacks/poo/throw_impact(atom/hit_atom)
//if(prob(50)) //this is so we actually have a chance of recovering some from disposal.
// return
playsound(src.loc, "sound/effects/squishy.ogg", 40, 1)
var/turf/T = src.loc
if(!istype(T, /turf/space))
new /obj/effect/decal/cleanable/poo(T)
//qdel(src) THIS IS BAD AND YOU SHOULD FEEL BAD.
..()

//#####BOTTLES#####

//PISS
/obj/item/weapon/reagent_containers/glass/bottle/urine
name = "urine bottle"
desc = "A small bottle. Contains urine."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle15"

New()
..()
reagents.add_reagent("urine", 30)


//#####LIFE PROCS#####

//poo and pee counters. This is called in human/handle_stomach.
/mob/living/carbon/human/proc/handle_excrement()
if(bowels <= 0)
bowels = 0
if(bladder <= 0)
bladder = 0

if(bowels >= 250)
switch(bowels)
if(250 to 400)
if(prob(5))
to_chat(src, "<b>You need to use the bathroom.</b>")
bowels += 15
if(400 to 450)
if(prob(5))
to_chat(src, "<span class='danger'>You really need to use the restroom!</span>")
bowels += 15
if(450 to 500)
if(prob(2))
handle_shit()
else if(prob(10))
to_chat(src, "<span class='danger'>You're about to shit yourself!</span>")
bowels += 25
if(500 to 550)
if(prob(15))
handle_shit()
else if(prob(30))
to_chat(src, "<span class='danger'>OH MY GOD YOU HAVE TO SHIT!</span>")
bowels += 35
if(550 to INFINITY)
handle_shit()

if(bladder >= 100)//Your bladder is smaller than your colon
switch(bladder)
if(100 to 250)
if(prob(5))
to_chat(src, "<b>You need to use the bathroom.</b>")
bladder += 15
if(250 to 400)
if(prob(5))
to_chat(src, "<span class='danger'>You really need to use the restroom!</span>")
bladder += 15
if(400 to 500)
if(prob(2))
handle_piss()
else if(prob(10))
to_chat(src, "<span class='danger'>You're about to piss yourself!</span>")
bladder += 25
if(500 to 550)
if(prob(15))
handle_piss()
else if(prob(30))
to_chat(src, "<span class='danger'>OH MY GOD YOU HAVE TO PEE!</span>")
bladder += 35
if(550 to INFINITY)
handle_piss()

//Shitting
/mob/living/carbon/human/proc/handle_shit()
var/message = null
if (src.bowels >= 30)

//Poo in the loo.
var/obj/structure/toilet/T = locate() in src.loc
var/obj/machinery/disposal/toilet/T2 = locate() in src.loc
var/mob/living/M = locate() in src.loc
if(T && T.open)
message = "<B>[src]</B> defecates into \the [T]."

else if (T2 && T2.open)
message = "<B>[src]</B> defecates into \the [T2]."
var/obj/item/weapon/reagent_containers/food/snacks/poo/V = new/obj/item/weapon/reagent_containers/food/snacks/poo(src.loc)
if(reagents)
reagents.trans_to(V, rand(1,5))

if(T2.CanInsertItem(src)) //attempt to insert the shit into the toilet.
V.forceMove(T2)
else
shit_left++

else if(w_uniform)
message = "<B>[src]</B> shits \his pants."
reagents.add_reagent("poo", 10)
adjust_hygiene(-25)
add_event("shitself", /datum/happiness_event/hygiene/shit)

//Poo on the face.
else if(M != src && M.lying)//Can only shit on them if they're lying down.
message = "<span class='danger'><b>[src]</b> shits right on <b>[M]</b>'s face!</span>"
M.reagents.add_reagent("poo", 10)

//Poo on the floor.
else
message = "<B>[src]</B> [pick("shits", "craps", "poops")]."
var/obj/item/weapon/reagent_containers/food/snacks/poo/V = new/obj/item/weapon/reagent_containers/food/snacks/poo(src.loc)
if(reagents)
reagents.trans_to(V, rand(1,5))

shit_left++//Global var for round end, not how much piss is left.

playsound(src.loc, 'sound/effects/poo2.ogg', 60, 1)
bowels -= rand(60,80)

else
to_chat(src, "You don't have to.")
return

visible_message("[message]")

//Peeing
/mob/living/carbon/human/proc/handle_piss()
var/message = null
if (bladder < 30)
to_chat(src, "You don't have to.")
return

var/obj/structure/urinal/U = locate() in src.loc
var/obj/machinery/disposal/toilet/T = locate() in src.loc
var/obj/machinery/disposal/toilet/T2 = locate() in src.loc
var/obj/structure/sink/S = locate() in src.loc
var/obj/item/weapon/reagent_containers/RC = locate() in src.loc
if((U || S) && gender != FEMALE)//In the urinal or sink.
message = "<B>[src]</B> urinates into [U ? U : S]."
reagents.remove_any(rand(1,8))

else if( (T && T.open) || (T2 && T2.open) )//In the toilet.
message = "<B>[src]</B> urinates into [T]."
reagents.remove_any(rand(1,8))

else if(RC && (istype(RC,/obj/item/weapon/reagent_containers/food/drinks || istype(RC,/obj/item/weapon/reagent_containers/glass))))
if(RC.is_open_container())
//Inside a beaker, glass, drink, etc.
message = "<B>[src]</B> urinates into [RC]."
var/amount = rand(1,8)
RC.reagents.add_reagent("urine", amount)
if(reagents)
reagents.trans_to(RC, amount)

else if(w_uniform)//In your pants.
message = "<B>[src]</B> pisses \his pants."
adjust_hygiene(-25)
add_event("pissedself", /datum/happiness_event/hygiene/pee)

else//On the floor.
var/turf/TT = src.loc
var/obj/effect/decal/cleanable/urine/D = new/obj/effect/decal/cleanable/urine(src.loc)
if(reagents)
reagents.trans_to(D, rand(1,8))
message = "<B>[src]</B> pisses on the [TT.name]."
piss_left++//Global var for round end, not how much piss is left.

bladder -= 50
visible_message("[message]")

@@ -0,0 +1,179 @@
//////////////////////////////////////////////////////////////////////////
//This is the file where all the stats and skills procs are kept. //
//The system is kinda barebones now but I hope to rewrite it to //
//be betting in the near future. //
// //
//Stats are pretty generic, skills are kind of specific. //
//You should just be able to plop in the proc call wherever you want. //
//I tried to make it versitile. //
// - Matt //
//////////////////////////////////////////////////////////////////////////

//defines
#define CRIT_SUCCESS_NORM 5
#define CRIT_FAILURE_NORM 5
#define CRIT_SUCCESS 2
#define CRIT_FAILURE 3


//I am aware this is probably the worst possible way of doing it but I'm using this method till I get a better one. - Matt
/mob
var/str = 10 //strength - used for hitting and lifting.
var/dex = 10 //dexterity - used for dodging and parrying.
var/int = 10

//skills
var/melee_skill = 50
var/ranged_skill = 50
var/medical_skill = 20
var/engineering_skill = 50

//crit shit
var/crit_success_chance = CRIT_SUCCESS_NORM
var/crit_failure_chance = CRIT_FAILURE_NORM
var/crit_success_modifier = 0
var/crit_failure_modifier = 0
var/crit_mood_modifier = 0


/mob/proc/get_success_chance()
return crit_success_chance + crit_success_modifier + crit_mood_modifier

/mob/proc/get_failure_chance()
return crit_failure_chance + crit_failure_modifier + crit_mood_modifier




/mob/proc/skillcheck(var/skill, var/requirement, var/show_message, var/message = "I have failed to do this.")//1 - 100
if(skill >= requirement)//If we already surpass the skill requirements no need to roll.
if(prob(get_success_chance()))//Only thing we roll for is a crit success.
return CRIT_SUCCESS
return 1
else
if(prob(skill + src.mood_affect(0, 1)))//Otherwise we roll to see if we pass.
if(prob(get_success_chance()))//And again to see if we get a crit scucess.
return CRIT_SUCCESS
return 1
else
if(show_message)//If we don't pass then we return failure
to_chat(src, "<span class = 'warning'>[message]</span>")
if(prob(get_failure_chance()))//And roll for a crit failure.
return CRIT_FAILURE
return 0


/mob/proc/statscheck(var/stat, var/requirement, var/show_message, var/message = "I have failed to do this.")//Requirement needs to be 1 through 20
if(stat < requirement)
var/H = rand(1,20)// our "dice"
H += mood_affect(1)// our skill modifier
if(stat >= H)//Rolling that d20
//world << "Rolled and passed."
return 1
else
if(show_message)//If we fail then print this message and return 0.
to_chat(src, "<span class = 'warning'>[message]</span>")
return 0
else
//world << "Didn't roll and passed."
return 1

//having a bad mood fucks your shit up fam.
/mob/proc/mood_affect(var/stat = null, var/skill = null)
if(iscarbon(src))
var/mob/living/carbon/C = src
if(C.happiness <= MOOD_LEVEL_SAD3)
if(stat)
return 5
if(skill)
return -15


proc/strToDamageModifier(var/strength)
switch(strength)
if(1 to 5)
return 0.5

if(6 to 11)
return 1

if(12 to 15)
return 1.5

if(16 to INFINITY)
return 1.75

proc/strToSpeedModifier(var/strength, var/w_class)//Looks messy. Is messy. Is also only used once. But I don't give a fuuuuuuuuck.
switch(strength)
if(1 to 5)
if(w_class > ITEM_SIZE_NORMAL)
return 20

if(6 to 11)
if(w_class > ITEM_SIZE_NORMAL)
return 15

if(12 to 15)
if(w_class > ITEM_SIZE_NORMAL)
return 10

if(16 to INFINITY)
if(w_class > ITEM_SIZE_NORMAL)
return 5

//Stats helpers.
/mob/proc/add_stats(var/stre, var/dexe, var/inti)//To make adding stats quicker.
if(stre)
str = stre
if(dexe)
dex = dexe
if(inti)
int = inti


/mob/proc/adjustStrength(var/num)
str += num

/mob/proc/adjustDexterity(var/num)
dex += num

/mob/proc/adjustInteligence(var/num)
int += num



//Skill helpers.
/mob/proc/skillnumtodesc(var/skill)
switch(skill)
if(0 to 25)
return "<small><i>pathetic</i></small>"
if(25 to 45)
return "unskilled"
if(45 to 60)
return pick("alright", "ok", "not bad")
if(60 to 80)
return "skilled"
if(80 to INFINITY)
return "<b>GOD LIKE</b>"

/mob/proc/add_skills(var/melee, var/ranged, var/medical, var/engineering)//To make adding skills quicker.
if(melee)
melee_skill = melee
if(ranged)
ranged_skill = ranged
if(medical)
medical_skill = medical
if(engineering)
engineering_skill = engineering

/mob/living/carbon/human/verb/check_skills()//Debug tool for checking skills until I add the icon for it to the HUD.
set name = "Check Skills"
set category = "IC"

var/message = "<big><b>Skills:</b></big>\n"
message += "I am <b>[skillnumtodesc(melee_skill)]</b> at melee.\n"
message += "I am <b>[skillnumtodesc(ranged_skill)]</b> with guns.</b></i>\n"
message += "I am <b>[skillnumtodesc(medical_skill)]</b> with medicine.</b></i>\n"
message += "I am <b>[skillnumtodesc(engineering_skill)]</b> at engineering.</b></i>\n"

to_chat(src, message)