mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 16:07:40 +00:00
1150 lines
46 KiB
Plaintext
1150 lines
46 KiB
Plaintext
/mob/living/carbon/human
|
|
name = "Unknown"
|
|
real_name = "Unknown"
|
|
icon = 'icons/mob/human.dmi'
|
|
icon_state = "caucasian_m"
|
|
SET_APPEARANCE_FLAGS(KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE)
|
|
|
|
/mob/living/carbon/human/Initialize(mapload)
|
|
add_verb(src, /mob/living/proc/mob_sleep)
|
|
add_verb(src, /mob/living/proc/lay_down)
|
|
add_verb(src, /mob/living/carbon/human/verb/underwear_toggle)
|
|
add_verb(src, /mob/living/verb/subtle)
|
|
add_verb(src, /mob/living/verb/subtler)
|
|
//initialize limbs first
|
|
create_bodyparts()
|
|
|
|
setup_human_dna()
|
|
|
|
if(dna.species)
|
|
set_species(dna.species.type)
|
|
|
|
//initialise organs
|
|
create_internal_organs() //most of it is done in set_species now, this is only for parent call
|
|
physiology = new()
|
|
|
|
AddComponent(/datum/component/personal_crafting)
|
|
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_HUMAN, 1, 2)
|
|
. = ..()
|
|
|
|
if(CONFIG_GET(flag/disable_stambuffer))
|
|
enable_intentional_sprint_mode()
|
|
|
|
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, TYPE_PROC_REF(/atom, clean_blood))
|
|
GLOB.human_list += src
|
|
|
|
/mob/living/carbon/human/proc/setup_human_dna()
|
|
//initialize dna. for spawned humans; overwritten by other code
|
|
create_dna(src)
|
|
randomize_human(src)
|
|
dna.initialize_dna()
|
|
|
|
/mob/living/carbon/human/ComponentInitialize()
|
|
. = ..()
|
|
if(!CONFIG_GET(flag/disable_human_mood))
|
|
AddComponent(/datum/component/mood)
|
|
AddComponent(/datum/component/combat_mode)
|
|
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
|
|
AddElement(/datum/element/flavor_text/carbon/temporary, "", "Set Pose (Temporary Flavor Text)", "This should be used only for things pertaining to the current round!", _save_key = null)
|
|
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
|
|
AddElement(/datum/element/strippable, GLOB.strippable_human_items, TYPE_PROC_REF(/mob/living/carbon/human, should_strip))
|
|
|
|
/mob/living/carbon/human/Destroy()
|
|
QDEL_NULL(physiology)
|
|
QDEL_NULL_LIST(vore_organs) // CITADEL EDIT belly stuff
|
|
GLOB.human_list -= src
|
|
return ..()
|
|
|
|
/mob/living/carbon/human/prepare_data_huds()
|
|
//Update med hud images...
|
|
..()
|
|
//...sec hud images...
|
|
sec_hud_set_ID()
|
|
sec_hud_set_implants()
|
|
sec_hud_set_security_status()
|
|
//...and display them.
|
|
add_to_all_human_data_huds()
|
|
|
|
/mob/living/carbon/human/get_status_tab_items()
|
|
. = ..()
|
|
. += "Intent: [a_intent]"
|
|
. += "Move Mode: [m_intent]"
|
|
if(internal)
|
|
if(!internal.air_contents)
|
|
qdel(internal)
|
|
else
|
|
. += ""
|
|
. += "Internal Atmosphere Info: [internal.name]"
|
|
. += "Tank Pressure: [internal.air_contents.return_pressure()]"
|
|
. += "Distribution Pressure: [internal.distribute_pressure]"
|
|
if(mind)
|
|
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
|
|
if(changeling)
|
|
. += ""
|
|
. += "Chemical Storage: [changeling.chem_charges]/[changeling.chem_storage]"
|
|
. += "Absorbed DNA: [changeling.absorbedcount]"
|
|
|
|
//NINJACODE
|
|
if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) //Only display if actually a ninja.
|
|
var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit
|
|
. += "SpiderOS Status: [SN.s_initialized ? "Initialized" : "Disabled"]"
|
|
. += "Current Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]"
|
|
if(SN.s_initialized)
|
|
//Suit gear
|
|
. += "Energy Charge: [round(SN.cell.charge/100)]%"
|
|
//Ninja status
|
|
. += "Fingerprints: [md5(dna.uni_identity)]"
|
|
. += "Unique Identity: [dna.unique_enzymes]"
|
|
. += "Overall Status: [stat > 1 ? "dead" : "[health]% healthy"]"
|
|
. += "Nutrition Status: [nutrition]"
|
|
. += "Oxygen Loss: [getOxyLoss()]"
|
|
. += "Toxin Levels: [getToxLoss()]"
|
|
. += "Burn Severity: [getFireLoss()]"
|
|
. += "Brute Trauma: [getBruteLoss()]"
|
|
. += "Radiation Levels: [radiation] rad"
|
|
. += "Body Temperature: [bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)"
|
|
|
|
//Diseases
|
|
if(length(diseases))
|
|
. += "Viruses:"
|
|
for(var/thing in diseases)
|
|
var/datum/disease/D = thing
|
|
. += "* [D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]"
|
|
|
|
// called when something steps onto a human
|
|
// this could be made more general, but for now just handle mulebot
|
|
/mob/living/carbon/human/Crossed(atom/movable/AM)
|
|
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
|
|
var/mob/living/simple_animal/bot/mulebot/MB = AM
|
|
if(istype(MB))
|
|
MB.RunOver(src)
|
|
|
|
spreadFire(AM)
|
|
|
|
/mob/living/carbon/human/Topic(href, href_list)
|
|
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
|
if(href_list["embedded_object"])
|
|
var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
|
|
if(!L)
|
|
return
|
|
var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
|
|
if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
|
|
return
|
|
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
|
|
return
|
|
|
|
///////HUDs///////
|
|
if(href_list["hud"])
|
|
if(ishuman(usr))
|
|
var/mob/living/carbon/human/H = usr
|
|
var/perpname = get_face_name(get_id_name(""))
|
|
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud))
|
|
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general)
|
|
if(href_list["photo_front"] || href_list["photo_side"])
|
|
if(R)
|
|
if(!H.canUseHUD())
|
|
return
|
|
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/medical))
|
|
return
|
|
var/obj/item/photo/P = null
|
|
if(href_list["photo_front"])
|
|
P = R.fields["photo_front"]
|
|
else if(href_list["photo_side"])
|
|
P = R.fields["photo_side"]
|
|
if(P)
|
|
P.show(H)
|
|
|
|
if(href_list["hud"] == "m")
|
|
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/medical))
|
|
if(href_list["p_stat"])
|
|
var/health_status = input(usr, "Specify a new physical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel")
|
|
if(R)
|
|
if(!H.canUseHUD())
|
|
return
|
|
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/medical))
|
|
return
|
|
if(health_status && health_status != "Cancel")
|
|
R.fields["p_stat"] = health_status
|
|
return
|
|
if(href_list["m_stat"])
|
|
var/health_status = input(usr, "Specify a new mental status for this person.", "Medical HUD", R.fields["m_stat"]) in list("Stable", "*Watch*", "*Unstable*", "*Insane*", "Cancel")
|
|
if(R)
|
|
if(!H.canUseHUD())
|
|
return
|
|
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/medical))
|
|
return
|
|
if(health_status && health_status != "Cancel")
|
|
R.fields["m_stat"] = health_status
|
|
return
|
|
if(href_list["evaluation"])
|
|
if(!getBruteLoss() && !getFireLoss() && !getOxyLoss() && getToxLoss() < 20)
|
|
to_chat(usr, "<span class='notice'>No external injuries detected.</span><br>")
|
|
return
|
|
var/span = "notice"
|
|
var/status = ""
|
|
if(getBruteLoss())
|
|
to_chat(usr, "<b>Physical trauma analysis:</b>")
|
|
for(var/X in bodyparts)
|
|
var/obj/item/bodypart/BP = X
|
|
var/brutedamage = BP.brute_dam
|
|
if(brutedamage > 0)
|
|
status = "received minor physical injuries."
|
|
span = "notice"
|
|
if(brutedamage > 20)
|
|
status = "been seriously damaged."
|
|
span = "danger"
|
|
if(brutedamage > 40)
|
|
status = "sustained major trauma!"
|
|
span = "userdanger"
|
|
if(brutedamage)
|
|
to_chat(usr, "<span class='[span]'>[BP] appears to have [status]</span>")
|
|
if(getFireLoss())
|
|
to_chat(usr, "<b>Analysis of skin burns:</b>")
|
|
for(var/X in bodyparts)
|
|
var/obj/item/bodypart/BP = X
|
|
var/burndamage = BP.burn_dam
|
|
if(burndamage > 0)
|
|
status = "signs of minor burns."
|
|
span = "notice"
|
|
if(burndamage > 20)
|
|
status = "serious burns."
|
|
span = "danger"
|
|
if(burndamage > 40)
|
|
status = "major burns!"
|
|
span = "userdanger"
|
|
if(burndamage)
|
|
to_chat(usr, "<span class='[span]'>[BP] appears to have [status]</span>")
|
|
if(getOxyLoss())
|
|
to_chat(usr, "<span class='danger'>Patient has signs of suffocation, emergency treatment may be required!</span>")
|
|
if(getToxLoss() > 20)
|
|
to_chat(usr, "<span class='danger'>Gathered data is inconsistent with the analysis, possible cause: poisoning.</span>")
|
|
|
|
if(href_list["hud"] == "s")
|
|
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
|
if(usr.stat || usr == src) //|| !usr.canmove || usr.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
|
|
return //Non-fluff: This allows sec to set people to arrest as they get disarmed or beaten
|
|
// Checks the user has security clearence before allowing them to change arrest status via hud, comment out to enable all access
|
|
var/allowed_access = null
|
|
var/obj/item/clothing/glasses/G = H.glasses
|
|
if (!(G.obj_flags & EMAGGED))
|
|
if(H.wear_id)
|
|
var/list/access = H.wear_id.GetAccess()
|
|
if(ACCESS_SEC_DOORS in access)
|
|
allowed_access = H.get_authentification_name()
|
|
else
|
|
allowed_access = "@%&ERROR_%$*"
|
|
|
|
|
|
if(!allowed_access)
|
|
to_chat(H, "<span class='warning'>ERROR: Invalid Access</span>")
|
|
return
|
|
|
|
if(perpname)
|
|
R = find_record("name", perpname, GLOB.data_core.security)
|
|
if(R)
|
|
if(href_list["status"])
|
|
var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Paroled", "Discharged", "Cancel")
|
|
if(setcriminal != "Cancel")
|
|
if(R)
|
|
if(H.canUseHUD())
|
|
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
|
investigate_log("[key_name(src)] has been set from [R.fields["criminal"]] to [setcriminal] by [key_name(usr)].", INVESTIGATE_RECORDS)
|
|
R.fields["criminal"] = setcriminal
|
|
sec_hud_set_security_status()
|
|
return
|
|
|
|
if(href_list["view"])
|
|
if(R)
|
|
if(!H.canUseHUD())
|
|
return
|
|
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
|
return
|
|
to_chat(usr, "<b>Name:</b> [R.fields["name"]] <b>Criminal Status:</b> [R.fields["criminal"]]")
|
|
to_chat(usr, "<b>Minor Crimes:</b>")
|
|
for(var/datum/data/crime/c in R.fields["mi_crim"])
|
|
to_chat(usr, "<b>Crime:</b> [c.crimeName]")
|
|
to_chat(usr, "<b>Details:</b> [c.crimeDetails]")
|
|
to_chat(usr, "Added by [c.author] at [c.time]")
|
|
to_chat(usr, "----------")
|
|
to_chat(usr, "<b>Major Crimes:</b>")
|
|
for(var/datum/data/crime/c in R.fields["ma_crim"])
|
|
to_chat(usr, "<b>Crime:</b> [c.crimeName]")
|
|
to_chat(usr, "<b>Details:</b> [c.crimeDetails]")
|
|
to_chat(usr, "Added by [c.author] at [c.time]")
|
|
to_chat(usr, "----------")
|
|
to_chat(usr, "<b>Notes:</b> [R.fields["notes"]]")
|
|
return
|
|
|
|
if(href_list["add_crime"])
|
|
switch(alert("What crime would you like to add?","Security HUD","Minor Crime","Major Crime","Cancel"))
|
|
if("Minor Crime")
|
|
if(R)
|
|
var/t1 = stripped_input("Please input minor crime names:", "Security HUD", "", null)
|
|
var/t2 = stripped_multiline_input("Please input minor crime details:", "Security HUD", "", null)
|
|
if(R)
|
|
if (!t1 || !t2 || !allowed_access)
|
|
return
|
|
else if(!H.canUseHUD())
|
|
return
|
|
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
|
return
|
|
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss", world.time))
|
|
GLOB.data_core.addMinorCrime(R.fields["id"], crime)
|
|
investigate_log("New Minor Crime: <strong>[t1]</strong>: [t2] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
|
|
to_chat(usr, "<span class='notice'>Successfully added a minor crime.</span>")
|
|
return
|
|
if("Major Crime")
|
|
if(R)
|
|
var/t1 = stripped_input("Please input major crime names:", "Security HUD", "", null)
|
|
var/t2 = stripped_multiline_input("Please input major crime details:", "Security HUD", "", null)
|
|
if(R)
|
|
if (!t1 || !t2 || !allowed_access)
|
|
return
|
|
else if (!H.canUseHUD())
|
|
return
|
|
else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
|
return
|
|
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss", world.time))
|
|
GLOB.data_core.addMajorCrime(R.fields["id"], crime)
|
|
investigate_log("New Major Crime: <strong>[t1]</strong>: [t2] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
|
|
to_chat(usr, "<span class='notice'>Successfully added a major crime.</span>")
|
|
return
|
|
|
|
if(href_list["view_comment"])
|
|
if(R)
|
|
if(!H.canUseHUD())
|
|
return
|
|
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
|
return
|
|
to_chat(usr, "<b>Comments/Log:</b>")
|
|
var/counter = 1
|
|
while(R.fields[text("com_[]", counter)])
|
|
to_chat(usr, R.fields[text("com_[]", counter)])
|
|
to_chat(usr, "----------")
|
|
counter++
|
|
return
|
|
|
|
if(href_list["add_comment"])
|
|
if(R)
|
|
var/t1 = stripped_multiline_input("Add Comment:", "Secure. records", null, null)
|
|
if(R)
|
|
if (!t1 || !allowed_access)
|
|
return
|
|
else if(!H.canUseHUD())
|
|
return
|
|
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
|
return
|
|
var/counter = 1
|
|
while(R.fields[text("com_[]", counter)])
|
|
counter++
|
|
R.fields["com_[counter]"] = "Made by [allowed_access] on [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)] [time2text(world.realtime, "MMM DD")], [GLOB.year_integer]<BR>[t1]"
|
|
to_chat(usr, "<span class='notice'>Successfully added comment.</span>")
|
|
return
|
|
to_chat(usr, "<span class='warning'>Unable to locate a data core entry for this person.</span>")
|
|
|
|
/mob/living/carbon/human/proc/canUseHUD()
|
|
return CHECK_MOBILITY(src, MOBILITY_UI)
|
|
|
|
/mob/living/carbon/human/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE)
|
|
. = 1 // Default to returning true.
|
|
if(user && !target_zone)
|
|
target_zone = user.zone_selected
|
|
if(HAS_TRAIT(src, TRAIT_PIERCEIMMUNE) && !bypass_immunity)
|
|
. = 0
|
|
// If targeting the head, see if the head item is thin enough.
|
|
// If targeting anything else, see if the wear suit is thin enough.
|
|
if (!penetrate_thick)
|
|
if(above_neck(target_zone))
|
|
if(head && istype(head, /obj/item/clothing))
|
|
var/obj/item/clothing/CH = head
|
|
if (CH.clothing_flags & THICKMATERIAL)
|
|
. = 0
|
|
else
|
|
if(wear_suit && istype(wear_suit, /obj/item/clothing))
|
|
var/obj/item/clothing/CS = wear_suit
|
|
if (CS.clothing_flags & THICKMATERIAL)
|
|
. = 0
|
|
if(!. && error_msg && user)
|
|
// Might need re-wording.
|
|
to_chat(user, "<span class='alert'>There is no exposed flesh or thin material [above_neck(target_zone) ? "on [p_their()] head" : "on [p_their()] body"].</span>")
|
|
|
|
/mob/living/carbon/human/check_obscured_slots()
|
|
. = ..()
|
|
if(wear_suit)
|
|
if(wear_suit.flags_inv & HIDEGLOVES)
|
|
LAZYOR(., ITEM_SLOT_GLOVES)
|
|
if(wear_suit.flags_inv & HIDEJUMPSUIT)
|
|
LAZYOR(., ITEM_SLOT_ICLOTHING)
|
|
if(wear_suit.flags_inv & HIDESHOES)
|
|
LAZYOR(., ITEM_SLOT_FEET)
|
|
|
|
/mob/living/carbon/human/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
|
|
if(judgement_criteria & JUDGE_EMAGGED)
|
|
return 10 //Everyone is a criminal!
|
|
|
|
var/threatcount = 0
|
|
|
|
//Lasertag bullshit
|
|
if(lasercolor)
|
|
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
|
|
if(istype(wear_suit, /obj/item/clothing/suit/redtag))
|
|
threatcount += 4
|
|
if(is_holding_item_of_type(/obj/item/gun/energy/laser/redtag))
|
|
threatcount += 4
|
|
if(istype(belt, /obj/item/gun/energy/laser/redtag))
|
|
threatcount += 2
|
|
|
|
if(lasercolor == "r")
|
|
if(istype(wear_suit, /obj/item/clothing/suit/bluetag))
|
|
threatcount += 4
|
|
if(is_holding_item_of_type(/obj/item/gun/energy/laser/bluetag))
|
|
threatcount += 4
|
|
if(istype(belt, /obj/item/gun/energy/laser/bluetag))
|
|
threatcount += 2
|
|
|
|
return threatcount
|
|
|
|
//Check for ID
|
|
var/obj/item/card/id/idcard = get_idcard(FALSE)
|
|
if( (judgement_criteria & JUDGE_IDCHECK) && !idcard && name=="Unknown")
|
|
threatcount += 4
|
|
|
|
//Check for weapons
|
|
if( (judgement_criteria & JUDGE_WEAPONCHECK) && weaponcheck)
|
|
if(!idcard || !(ACCESS_WEAPONS in idcard.access))
|
|
for(var/obj/item/I in held_items) //if they're holding a gun
|
|
if(weaponcheck.Invoke(I))
|
|
threatcount += 4
|
|
if(weaponcheck.Invoke(belt) || weaponcheck.Invoke(back)) //if a weapon is present in the belt or back slot
|
|
threatcount += 2 //not enough to trigger look_for_perp() on it's own unless they also have criminal status.
|
|
|
|
//Check for arrest warrant
|
|
if(judgement_criteria & JUDGE_RECORDCHECK)
|
|
var/perpname = get_face_name(get_id_name())
|
|
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
|
|
if(R && R.fields["criminal"])
|
|
switch(R.fields["criminal"])
|
|
if("*Arrest*")
|
|
threatcount += 5
|
|
if("Incarcerated")
|
|
threatcount += 2
|
|
if("Paroled")
|
|
threatcount += 2
|
|
|
|
//Check for dresscode violations
|
|
if(istype(head, /obj/item/clothing/head/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/syndi) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi))
|
|
threatcount += 4 //fuk u antags <3 //no you
|
|
|
|
//mindshield implants imply trustworthyness
|
|
if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
|
|
threatcount -= 1
|
|
|
|
//Agent cards lower threatlevel.
|
|
if(istype(idcard, /obj/item/card/id/syndicate))
|
|
threatcount -= 2
|
|
|
|
return threatcount
|
|
|
|
|
|
//Used for new human mobs created by cloning/goleming/podding
|
|
/mob/living/carbon/human/proc/set_cloned_appearance()
|
|
if(dna.features["body_model"] == MALE)
|
|
facial_hair_style = "Full Beard"
|
|
else
|
|
facial_hair_style = "Shaved"
|
|
hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3")
|
|
underwear = "Nude"
|
|
undershirt = "Nude"
|
|
socks = "Nude"
|
|
update_body(TRUE)
|
|
update_hair()
|
|
|
|
/mob/living/carbon/human/singularity_pull(S, current_size)
|
|
..()
|
|
if(current_size >= STAGE_THREE)
|
|
for(var/obj/item/hand in held_items)
|
|
if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && dropItemToGround(hand))
|
|
step_towards(hand, src)
|
|
to_chat(src, "<span class='warning'>\The [S] pulls \the [hand] from your grip!</span>")
|
|
rad_act(current_size * 3)
|
|
if(mob_negates_gravity())
|
|
return
|
|
|
|
/mob/living/carbon/human/proc/do_cpr(mob/living/carbon/C)
|
|
CHECK_DNA_AND_SPECIES(C)
|
|
|
|
if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
|
to_chat(src, "<span class='warning'>[C.name] is dead!</span>")
|
|
return
|
|
if(is_mouth_covered())
|
|
to_chat(src, "<span class='warning'>Remove your mask first!</span>")
|
|
return FALSE
|
|
if(C.is_mouth_covered())
|
|
to_chat(src, "<span class='warning'>Remove [p_their()] mask first!</span>")
|
|
return FALSE
|
|
|
|
if(C.cpr_time < world.time + 30)
|
|
visible_message("<span class='notice'>[src] is trying to perform CPR on [C.name]!</span>", \
|
|
"<span class='notice'>You try to perform CPR on [C.name]... Hold still!</span>")
|
|
if(!do_mob(src, C))
|
|
to_chat(src, "<span class='warning'>You fail to perform CPR on [C]!</span>")
|
|
return FALSE
|
|
|
|
var/they_breathe = !HAS_TRAIT(C, TRAIT_NOBREATH)
|
|
var/they_lung = C.getorganslot(ORGAN_SLOT_LUNGS)
|
|
|
|
if(C.health > C.crit_threshold)
|
|
return
|
|
|
|
src.visible_message("[src] performs CPR on [C.name]!", "<span class='notice'>You perform CPR on [C.name].</span>")
|
|
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "perform_cpr", /datum/mood_event/perform_cpr)
|
|
C.cpr_time = world.time
|
|
log_combat(src, C, "CPRed")
|
|
|
|
if(they_breathe && they_lung)
|
|
var/suff = min(C.getOxyLoss(), 7)
|
|
C.adjustOxyLoss(-suff)
|
|
C.updatehealth()
|
|
to_chat(C, "<span class='unconscious'>You feel a breath of fresh air enter your lungs... It feels good...</span>")
|
|
else if(they_breathe && !they_lung)
|
|
to_chat(C, "<span class='unconscious'>You feel a breath of fresh air... but you don't feel any better...</span>")
|
|
else
|
|
to_chat(C, "<span class='unconscious'>You feel a breath of fresh air... which is a sensation you don't recognise...</span>")
|
|
|
|
/mob/living/carbon/human/cuff_resist(obj/item/I)
|
|
if(dna && dna.check_mutation(HULK))
|
|
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk")
|
|
if(..(I, cuff_break = FAST_CUFFBREAK))
|
|
dropItemToGround(I)
|
|
else
|
|
if(..())
|
|
dropItemToGround(I)
|
|
|
|
/mob/living/carbon/human/clean_blood()
|
|
var/mob/living/carbon/human/H = src
|
|
if(H.gloves)
|
|
if(H.gloves.clean_blood())
|
|
H.update_inv_gloves()
|
|
else
|
|
..() // Clear the Blood_DNA list
|
|
if(H.bloody_hands)
|
|
H.bloody_hands = 0
|
|
H.update_inv_gloves()
|
|
update_icons() //apply the now updated overlays to the mob
|
|
|
|
/mob/living/carbon/human/wash_cream()
|
|
if(creamed) //clean both to prevent a rare bug
|
|
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_snout"))
|
|
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_human"))
|
|
creamed = FALSE
|
|
|
|
//Turns a mob black, flashes a skeleton overlay
|
|
//Just like a cartoon!
|
|
/mob/living/carbon/human/proc/electrocution_animation(anim_duration)
|
|
//Handle mutant parts if possible
|
|
if(dna && dna.species)
|
|
add_atom_colour("#000000", TEMPORARY_COLOUR_PRIORITY)
|
|
var/static/mutable_appearance/electrocution_skeleton_anim
|
|
if(!electrocution_skeleton_anim)
|
|
electrocution_skeleton_anim = mutable_appearance(icon, "electrocuted_base")
|
|
electrocution_skeleton_anim.appearance_flags |= RESET_COLOR|KEEP_APART
|
|
add_overlay(electrocution_skeleton_anim)
|
|
addtimer(CALLBACK(src, PROC_REF(end_electrocution_animation), electrocution_skeleton_anim), anim_duration)
|
|
|
|
else //or just do a generic animation
|
|
flick_overlay_view(image(icon,src,"electrocuted_generic",ABOVE_MOB_LAYER), src, anim_duration)
|
|
|
|
/mob/living/carbon/human/proc/end_electrocution_animation(mutable_appearance/MA)
|
|
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000")
|
|
cut_overlay(MA)
|
|
|
|
/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting = TRUE)
|
|
if(incapacitated() || (check_resting && !CHECK_MOBILITY(src, MOBILITY_STAND)))
|
|
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
|
return FALSE
|
|
if(!Adjacent(M) && (M.loc != src))
|
|
if((be_close == 0) || (!no_tk && (dna.check_mutation(TK) && tkMaxRangeCheck(src, M))))
|
|
return TRUE
|
|
to_chat(src, "<span class='warning'>You are too far away!</span>")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/mob/living/carbon/human/resist_restraints()
|
|
if(wear_suit && wear_suit.breakouttime)
|
|
MarkResistTime()
|
|
cuff_resist(wear_suit)
|
|
else
|
|
..()
|
|
|
|
/mob/living/carbon/human/replace_records_name(oldname,newname) // Only humans have records right now, move this up if changed.
|
|
for(var/list/L in list(GLOB.data_core.general,GLOB.data_core.medical,GLOB.data_core.security,GLOB.data_core.locked))
|
|
var/datum/data/record/R = find_record("name", oldname, L)
|
|
if(R)
|
|
R.fields["name"] = newname
|
|
|
|
/mob/living/carbon/human/get_total_tint()
|
|
. = ..()
|
|
if(glasses)
|
|
. += glasses.tint
|
|
|
|
/mob/living/carbon/human/update_health_hud()
|
|
if(!client || !hud_used)
|
|
return
|
|
if(dna.species.update_health_hud())
|
|
return
|
|
else
|
|
if(hud_used.healths)
|
|
var/health_amount = min(health, maxHealth - clamp(getStaminaLoss()-50, 0, 80))//CIT CHANGE - makes staminaloss have less of an impact on the health hud
|
|
if(..(health_amount)) //not dead
|
|
switch(hal_screwyhud)
|
|
if(SCREWYHUD_CRIT)
|
|
hud_used.healths.icon_state = "health6"
|
|
if(SCREWYHUD_DEAD)
|
|
hud_used.healths.icon_state = "health7"
|
|
if(SCREWYHUD_HEALTHY)
|
|
hud_used.healths.icon_state = "health0"
|
|
if(hud_used.healthdoll)
|
|
hud_used.healthdoll.cut_overlays()
|
|
if(stat != DEAD)
|
|
hud_used.healthdoll.icon_state = "healthdoll_OVERLAY"
|
|
for(var/X in bodyparts)
|
|
var/obj/item/bodypart/BP = X
|
|
var/damage = BP.burn_dam + BP.brute_dam
|
|
var/comparison = (BP.max_damage/5)
|
|
var/icon_num = 0
|
|
if(damage)
|
|
icon_num = 1
|
|
if(damage > (comparison))
|
|
icon_num = 2
|
|
if(damage > (comparison*2))
|
|
icon_num = 3
|
|
if(damage > (comparison*3))
|
|
icon_num = 4
|
|
if(damage > (comparison*4))
|
|
icon_num = 5
|
|
if(hal_screwyhud == SCREWYHUD_HEALTHY)
|
|
icon_num = 0
|
|
if(icon_num)
|
|
hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[BP.body_zone][icon_num]"))
|
|
for(var/t in get_missing_limbs()) //Missing limbs
|
|
hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[t]6"))
|
|
for(var/t in get_disabled_limbs()) //Disabled limbs
|
|
hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[t]7"))
|
|
else
|
|
hud_used.healthdoll.icon_state = "healthdoll_DEAD"
|
|
|
|
hud_used.staminas?.update_icon_state()
|
|
hud_used.staminabuffer?.mark_dirty()
|
|
|
|
/mob/living/carbon/human/fully_heal(admin_revive = FALSE)
|
|
if(admin_revive)
|
|
regenerate_limbs()
|
|
regenerate_organs()
|
|
remove_all_embedded_objects()
|
|
set_heartattack(FALSE)
|
|
drunkenness = 0
|
|
for(var/datum/mutation/human/HM in dna.mutations)
|
|
if(HM.quality != POSITIVE)
|
|
dna.remove_mutation(HM.name)
|
|
if(blood_volume < (BLOOD_VOLUME_NORMAL*blood_ratio))
|
|
blood_volume = (BLOOD_VOLUME_NORMAL*blood_ratio)
|
|
integrating_blood = 0
|
|
..()
|
|
|
|
/mob/living/carbon/human/check_weakness(obj/item/weapon, mob/living/attacker)
|
|
. = ..()
|
|
if (dna && dna.species)
|
|
. += dna.species.check_weakness(weapon, attacker)
|
|
|
|
/mob/living/carbon/human/is_literate()
|
|
return TRUE
|
|
|
|
/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
|
|
if(dna && dna.species) //prevents a runtime while a human is being monkeyfied
|
|
override = dna.species.override_float
|
|
..()
|
|
|
|
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
|
|
if(blood && dna?.species && (NOBLOOD in dna.species.species_traits))
|
|
if(message)
|
|
visible_message("<span class='warning'>[src] dry heaves!</span>", \
|
|
"<span class='userdanger'>You try to throw up, but there's nothing in your stomach!</span>")
|
|
if(stun)
|
|
DefaultCombatKnockdown(200)
|
|
return TRUE
|
|
..()
|
|
|
|
/mob/living/carbon/human/vv_get_dropdown()
|
|
. = ..()
|
|
VV_DROPDOWN_OPTION("", "---------")
|
|
VV_DROPDOWN_OPTION(VV_HK_COPY_OUTFIT, "Copy Outfit")
|
|
VV_DROPDOWN_OPTION(VV_HK_MOD_QUIRKS, "Add/Remove Quirks")
|
|
VV_DROPDOWN_OPTION(VV_HK_MAKE_MONKEY, "Make Monkey")
|
|
VV_DROPDOWN_OPTION(VV_HK_MAKE_CYBORG, "Make Cyborg")
|
|
VV_DROPDOWN_OPTION(VV_HK_MAKE_SLIME, "Make Slime")
|
|
VV_DROPDOWN_OPTION(VV_HK_MAKE_ALIEN, "Make Alien")
|
|
VV_DROPDOWN_OPTION(VV_HK_SET_SPECIES, "Set Species")
|
|
VV_DROPDOWN_OPTION(VV_HK_PURRBATION, "Toggle Purrbation")
|
|
VV_DROPDOWN_OPTION(VV_HK_APPLY_PREFS, "Apply preferences")
|
|
|
|
/mob/living/carbon/human/vv_do_topic(list/href_list)
|
|
. = ..()
|
|
if(href_list[VV_HK_COPY_OUTFIT])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
copy_outfit()
|
|
if(href_list[VV_HK_MOD_QUIRKS])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
|
|
var/list/options = list("Clear"="Clear")
|
|
for(var/x in subtypesof(/datum/quirk))
|
|
var/datum/quirk/T = x
|
|
var/qname = initial(T.name)
|
|
options[has_quirk(T) ? "[qname] (Remove)" : "[qname] (Add)"] = T
|
|
|
|
var/result = input(usr, "Choose quirk to add/remove","Quirk Mod") as null|anything in options
|
|
if(result)
|
|
if(result == "Clear")
|
|
for(var/datum/quirk/q in roundstart_quirks)
|
|
remove_quirk(q.type)
|
|
else
|
|
var/T = options[result]
|
|
if(has_quirk(T))
|
|
remove_quirk(T)
|
|
else
|
|
add_quirk(T,TRUE)
|
|
if(href_list[VV_HK_MAKE_MONKEY])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
|
return
|
|
usr.client.holder.Topic("vv_override", list("monkeyone"=href_list[VV_HK_TARGET]))
|
|
if(href_list[VV_HK_MAKE_CYBORG])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
|
return
|
|
usr.client.holder.Topic("vv_override", list("makerobot"=href_list[VV_HK_TARGET]))
|
|
if(href_list[VV_HK_MAKE_ALIEN])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
|
return
|
|
usr.client.holder.Topic("vv_override", list("makealien"=href_list[VV_HK_TARGET]))
|
|
if(href_list[VV_HK_MAKE_SLIME])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
|
|
return
|
|
usr.client.holder.Topic("vv_override", list("makeslime"=href_list[VV_HK_TARGET]))
|
|
if(href_list[VV_HK_SET_SPECIES])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
var/result = input(usr, "Please choose a new species","Species") as null|anything in GLOB.species_list
|
|
if(result)
|
|
var/newtype = GLOB.species_list[result]
|
|
admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [src] to [result]")
|
|
set_species(newtype)
|
|
if(href_list[VV_HK_PURRBATION])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
if(!ishumanbasic(src))
|
|
to_chat(usr, "This can only be done to the basic human species at the moment.")
|
|
return
|
|
var/success = purrbation_toggle(src)
|
|
if(success)
|
|
to_chat(usr, "Put [src] on purrbation.")
|
|
log_admin("[key_name(usr)] has put [key_name(src)] on purrbation.")
|
|
var/msg = "<span class='notice'>[key_name_admin(usr)] has put [key_name(src)] on purrbation.</span>"
|
|
message_admins(msg)
|
|
admin_ticket_log(src, msg)
|
|
|
|
else
|
|
to_chat(usr, "Removed [src] from purrbation.")
|
|
log_admin("[key_name(usr)] has removed [key_name(src)] from purrbation.")
|
|
var/msg = "<span class='notice'>[key_name_admin(usr)] has removed [key_name(src)] from purrbation.</span>"
|
|
message_admins(msg)
|
|
admin_ticket_log(src, msg)
|
|
if(href_list[VV_HK_APPLY_PREFS])
|
|
if(!check_rights(R_SPAWN))
|
|
return
|
|
if(!client)
|
|
var/bigtext = {"This action requires a client, if you need to do anything special, follow this short guide:
|
|
<blockquote class="info">
|
|
Mark this mob, then navigate to the preferences of the client you desire and call copy_to() with one argument, when it asks for the argument, browse to the bottom of the list and select marked datum, if you've followed this guide correctly, the mob will be turned into the character from the preferences you used.
|
|
</blockquote>
|
|
"}
|
|
to_chat(usr, bigtext)
|
|
return
|
|
|
|
var/datum/preferences/copying_this_one = client.prefs // turns out that prefs always exist if the client leaves, i'm not checking for client again
|
|
var/is_this_guy_trolling_the_admin = copying_this_one.default_slot
|
|
|
|
if(alert(usr, "Confirm reapply preferences?", "", "I'm sure", "Cancel") != "I'm sure")
|
|
return
|
|
|
|
if(is_this_guy_trolling_the_admin != copying_this_one.default_slot) // why would you do this, broooo
|
|
if(alert(usr, "The user changed their character slot while you were deciding, are you sure you want to do this? They might change their mind again and i will not protect again this time", "Uh oh", "I'm sure", "They did what?") != "I'm sure")
|
|
return
|
|
|
|
copying_this_one.copy_to(src)
|
|
var/change_text = "reapplied [key_name(src, TRUE)]'s preferences, [(is_this_guy_trolling_the_admin != copying_this_one.default_slot) ? "changing their character" : "resetting their character"]."
|
|
to_chat(usr, capitalize(change_text))
|
|
log_admin("[key_name(usr)] has [change_text]")
|
|
message_admins(span_notice("[key_name_admin(usr)] has [change_text]"))
|
|
admin_ticket_log(src, span_notice("[key_name_admin(usr, FALSE)] has [change_text]")) // In case they complained in an ahelp, we'll let them know anything happened
|
|
|
|
/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
|
|
var/GS_needed = istype(target, /mob/living/silicon/pai)? GRAB_PASSIVE : GRAB_AGGRESSIVE
|
|
if(pulling == target && grab_state >= GS_needed && stat == CONSCIOUS)
|
|
//If they dragged themselves and we're currently aggressively grabbing them try to piggyback
|
|
if(user == target && can_piggyback(target))
|
|
piggyback(target)
|
|
return
|
|
//If you dragged them to you and you're aggressively grabbing try to fireman carry them
|
|
else if(user == src)
|
|
if(user.a_intent == INTENT_GRAB)
|
|
fireman_carry(target)
|
|
return
|
|
. = ..()
|
|
|
|
//src is the user that will be carrying, target is the mob to be carried
|
|
/mob/living/carbon/human/proc/can_piggyback(mob/living/target)
|
|
return (iscarbon(target) || ispAI(target)) && target.stat == CONSCIOUS && CHECK_MOBILITY(src, MOBILITY_STAND)
|
|
|
|
/mob/living/carbon/human/proc/can_be_firemanned(mob/living/carbon/target)
|
|
return (ishuman(target) && !CHECK_MOBILITY(target, MOBILITY_STAND)) || ispAI(target)
|
|
|
|
/mob/living/carbon/human/proc/fireman_carry(mob/living/carbon/target)
|
|
var/carrydelay = 50 //if you have latex you are faster at grabbing
|
|
var/skills_space = "" //cobby told me to do this
|
|
if(HAS_TRAIT(src, TRAIT_QUICKER_CARRY))
|
|
carrydelay = 30
|
|
skills_space = "expertly "
|
|
else if(HAS_TRAIT(src, TRAIT_QUICK_CARRY))
|
|
carrydelay = 40
|
|
skills_space = "quickly "
|
|
if(can_be_firemanned(target) && !incapacitated(FALSE, TRUE))
|
|
visible_message("<span class='notice'>[src] starts [skills_space]lifting [target] onto their back..</span>",
|
|
//Joe Medic starts quickly/expertly lifting Grey Tider onto their back..
|
|
"<span class='notice'>[carrydelay < 35 ? "Using your gloves' nanochips, you" : "You"] [skills_space]start to lift [target] onto your back[carrydelay == 40 ? ", while assisted by the nanochips in your gloves.." : "..."]</span>")
|
|
//(Using your gloves' nanochips, you/You) ( /quickly/expertly) start to lift Grey Tider onto your back(, while assisted by the nanochips in your gloves../...)
|
|
if(do_after(src, carrydelay, target, extra_checks = CALLBACK(src, PROC_REF(can_be_firemanned), target)))
|
|
//Second check to make sure they're still valid to be carried
|
|
if(can_be_firemanned(target) && !incapacitated(FALSE, TRUE))
|
|
buckle_mob(target, TRUE, TRUE, 90, 1, 0, TRUE)
|
|
return
|
|
visible_message("<span class='warning'>[src] fails to fireman carry [target]!")
|
|
else
|
|
if (ishuman(target))
|
|
to_chat(src, "<span class='notice'>You can't fireman carry [target] while they're standing!</span>")
|
|
else
|
|
to_chat(src, "<span class='notice'>You can't seem to fireman carry that kind of species.</span>")
|
|
|
|
/mob/living/carbon/human/proc/piggyback(mob/living/carbon/target)
|
|
if(can_piggyback(target))
|
|
visible_message("<span class='notice'>[target] starts to climb onto [src]...</span>")
|
|
if(do_after(target, 1.5 SECONDS, src, IGNORE_INCAPACITATED, extra_checks = CALLBACK(src, PROC_REF(can_piggyback), target)))
|
|
if(can_piggyback(target))
|
|
if(target.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
|
|
target.visible_message("<span class='warning'>[target] can't hang onto [src]!</span>")
|
|
return
|
|
buckle_mob(target, TRUE, TRUE, 0, 1, 2, FALSE)
|
|
else
|
|
visible_message("<span class='warning'>[target] fails to climb onto [src]!</span>")
|
|
else
|
|
to_chat(target, "<span class='warning'>You can't piggyback ride [src] right now!</span>")
|
|
|
|
/mob/living/carbon/human/buckle_mob(mob/living/target, force = FALSE, check_loc = TRUE, lying_buckle = 0, hands_needed = 0, target_hands_needed = 0, fireman = FALSE)
|
|
if(!force)//humans are only meant to be ridden through piggybacking and special cases
|
|
return
|
|
if(!is_type_in_typecache(target, can_ride_typecache))
|
|
target.visible_message("<span class='warning'>[target] really can't seem to mount [src]...</span>")
|
|
return
|
|
buckle_lying = lying_buckle
|
|
var/datum/component/riding/human/riding_datum = LoadComponent(/datum/component/riding/human)
|
|
if(target_hands_needed)
|
|
riding_datum.ride_check_rider_restrained = TRUE
|
|
if(buckled_mobs && ((target in buckled_mobs) || (buckled_mobs.len >= max_buckled_mobs)) || buckled)
|
|
return
|
|
if(istype(target, /mob/living/silicon/pai))
|
|
hands_needed = 1
|
|
target_hands_needed = 0
|
|
var/equipped_hands_self
|
|
var/equipped_hands_target
|
|
if(hands_needed)
|
|
equipped_hands_self = riding_datum.equip_buckle_inhands(src, hands_needed, target)
|
|
if(target_hands_needed)
|
|
equipped_hands_target = riding_datum.equip_buckle_inhands(target, target_hands_needed)
|
|
|
|
if(hands_needed || target_hands_needed)
|
|
if(hands_needed && !equipped_hands_self)
|
|
src.visible_message("<span class='warning'>[src] can't get a grip on [target] because their hands are full!</span>",
|
|
"<span class='warning'>You can't get a grip on [target] because your hands are full!</span>")
|
|
return
|
|
else if(target_hands_needed && !equipped_hands_target)
|
|
target.visible_message("<span class='warning'>[target] can't get a grip on [src] because their hands are full!</span>",
|
|
"<span class='warning'>You can't get a grip on [src] because your hands are full!</span>")
|
|
return
|
|
|
|
stop_pulling()
|
|
riding_datum.handle_vehicle_layer(dir)
|
|
riding_datum.fireman_carrying = fireman
|
|
. = ..(target, force, check_loc)
|
|
|
|
/mob/living/carbon/human/proc/is_shove_knockdown_blocked() //If you want to add more things that block shove knockdown, extend this
|
|
for(var/obj/item/clothing/C in get_equipped_items()) //doesn't include pockets
|
|
if(C.blocks_shove_knockdown)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/mob/living/carbon/human/updatehealth()
|
|
. = ..()
|
|
dna?.species.spec_updatehealth(src)
|
|
if(HAS_TRAIT(src, TRAIT_IGNORESLOWDOWN)) //if we want to ignore slowdown from damage and equipment
|
|
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
|
|
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
|
|
return
|
|
if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) //if we want to ignore slowdown from damage, but not from equipment
|
|
var/scaling = maxHealth / 100
|
|
var/health_deficiency = max(((maxHealth / scaling) - (health / scaling)), max(0, getStaminaLoss() - 39))
|
|
if(health_deficiency >= 40)
|
|
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, health_deficiency / 75)
|
|
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, health_deficiency / 25)
|
|
else
|
|
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
|
|
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
|
|
else
|
|
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
|
|
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
|
|
|
|
/mob/living/carbon/human/is_bleeding()
|
|
if(NOBLOOD in dna.species.species_traits || bleedsuppress)
|
|
return FALSE
|
|
return ..()
|
|
|
|
/mob/living/carbon/human/get_total_bleed_rate()
|
|
if(NOBLOOD in dna.species.species_traits)
|
|
return FALSE
|
|
return ..()
|
|
|
|
/mob/living/carbon/human/species
|
|
var/race = null
|
|
|
|
/mob/living/carbon/human/species/Initialize(mapload)
|
|
. = ..()
|
|
set_species(race)
|
|
|
|
/**
|
|
* # `spec_trait_examine_font()`
|
|
*
|
|
* This gets a humanoid's special examine font, which is used to color their species name during examine / health analyzing.
|
|
* The first of these that applies is returned.
|
|
* Returns:
|
|
* * Metallic font if robotic
|
|
* * Cyan if a toxinlover
|
|
* * Purple if plasmaperson
|
|
* * Rock / Brownish if a golem
|
|
* * Green if none of the others apply (aka, generic organic)
|
|
*/
|
|
/mob/living/carbon/human/proc/spec_trait_examine_font()
|
|
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
|
|
return "<font color='#aaa9ad'>"
|
|
if(HAS_TRAIT(src, TRAIT_TOXINLOVER))
|
|
return "<font color='#00ffff'>"
|
|
if(isplasmaman(src))
|
|
return "<font color='#800080'>"
|
|
if(isgolem(src))
|
|
return "<font color='#8b4513'>"
|
|
return "<font color='#18d855'>"
|
|
|
|
|
|
/mob/living/carbon/human/get_tooltip_data()
|
|
var/t_He = p_they(TRUE)
|
|
var/t_is = p_are()
|
|
. = list()
|
|
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
|
if(skipface || get_visible_name() == "Unknown")
|
|
. += "You can't make out what species they are."
|
|
else
|
|
. += "[t_He] [t_is] a [spec_trait_examine_font()][dna.custom_species ? dna.custom_species : dna.species.name]</font>"
|
|
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, usr, .)
|
|
|
|
/mob/living/carbon/human/chestonly
|
|
bodyparts = list(/obj/item/bodypart/chest)
|
|
|
|
/mob/living/carbon/human/species/abductor
|
|
race = /datum/species/abductor
|
|
|
|
/mob/living/carbon/human/species/android
|
|
race = /datum/species/android
|
|
|
|
/mob/living/carbon/human/species/corporate
|
|
race = /datum/species/corporate
|
|
|
|
/mob/living/carbon/human/species/felinid
|
|
race = /datum/species/human/felinid
|
|
|
|
/mob/living/carbon/human/species/fly
|
|
race = /datum/species/fly
|
|
|
|
/mob/living/carbon/human/species/golem
|
|
race = /datum/species/golem
|
|
|
|
/mob/living/carbon/human/species/golem/random
|
|
race = /datum/species/golem/random
|
|
|
|
/mob/living/carbon/human/species/golem/adamantine
|
|
race = /datum/species/golem/adamantine
|
|
|
|
/mob/living/carbon/human/species/golem/plasma
|
|
race = /datum/species/golem/plasma
|
|
|
|
/mob/living/carbon/human/species/golem/diamond
|
|
race = /datum/species/golem/diamond
|
|
|
|
/mob/living/carbon/human/species/golem/gold
|
|
race = /datum/species/golem/gold
|
|
|
|
/mob/living/carbon/human/species/golem/silver
|
|
race = /datum/species/golem/silver
|
|
|
|
/mob/living/carbon/human/species/golem/plasteel
|
|
race = /datum/species/golem/plasteel
|
|
|
|
/mob/living/carbon/human/species/golem/titanium
|
|
race = /datum/species/golem/titanium
|
|
|
|
/mob/living/carbon/human/species/golem/plastitanium
|
|
race = /datum/species/golem/plastitanium
|
|
|
|
/mob/living/carbon/human/species/golem/alien_alloy
|
|
race = /datum/species/golem/alloy
|
|
|
|
/mob/living/carbon/human/species/golem/wood
|
|
race = /datum/species/golem/wood
|
|
|
|
/mob/living/carbon/human/species/golem/uranium
|
|
race = /datum/species/golem/uranium
|
|
|
|
/mob/living/carbon/human/species/golem/sand
|
|
race = /datum/species/golem/sand
|
|
|
|
/mob/living/carbon/human/species/golem/glass
|
|
race = /datum/species/golem/glass
|
|
|
|
/mob/living/carbon/human/species/golem/bluespace
|
|
race = /datum/species/golem/bluespace
|
|
|
|
/mob/living/carbon/human/species/golem/bananium
|
|
race = /datum/species/golem/bananium
|
|
|
|
/mob/living/carbon/human/species/golem/blood_cult
|
|
race = /datum/species/golem/runic
|
|
|
|
/mob/living/carbon/human/species/golem/cloth
|
|
race = /datum/species/golem/cloth
|
|
|
|
/mob/living/carbon/human/species/golem/plastic
|
|
race = /datum/species/golem/plastic
|
|
|
|
/mob/living/carbon/human/species/golem/bronze
|
|
race = /datum/species/golem/bronze
|
|
|
|
/mob/living/carbon/human/species/golem/cardboard
|
|
race = /datum/species/golem/cardboard
|
|
|
|
/mob/living/carbon/human/species/golem/leather
|
|
race = /datum/species/golem/leather
|
|
|
|
/mob/living/carbon/human/species/golem/bone
|
|
race = /datum/species/golem/bone
|
|
|
|
/mob/living/carbon/human/species/golem/durathread
|
|
race = /datum/species/golem/durathread
|
|
|
|
/mob/living/carbon/human/species/golem/clockwork
|
|
race = /datum/species/golem/clockwork
|
|
|
|
/mob/living/carbon/human/species/golem/clockwork/no_scrap
|
|
race = /datum/species/golem/clockwork/no_scrap
|
|
|
|
/mob/living/carbon/human/species/jelly
|
|
race = /datum/species/jelly
|
|
|
|
/mob/living/carbon/human/species/jelly/slime
|
|
race = /datum/species/jelly/slime
|
|
|
|
/mob/living/carbon/human/species/jelly/stargazer
|
|
race = /datum/species/jelly/stargazer
|
|
|
|
/mob/living/carbon/human/species/jelly/luminescent
|
|
race = /datum/species/jelly/luminescent
|
|
|
|
/mob/living/carbon/human/species/lizard
|
|
race = /datum/species/lizard
|
|
|
|
/mob/living/carbon/human/species/ethereal
|
|
race = /datum/species/ethereal
|
|
|
|
/mob/living/carbon/human/species/lizard/ashwalker
|
|
race = /datum/species/lizard/ashwalker
|
|
|
|
/mob/living/carbon/human/species/insect
|
|
race = /datum/species/insect
|
|
|
|
/mob/living/carbon/human/species/mush
|
|
race = /datum/species/mush
|
|
|
|
/mob/living/carbon/human/species/plasma
|
|
race = /datum/species/plasmaman
|
|
|
|
/mob/living/carbon/human/species/pod
|
|
race = /datum/species/pod
|
|
|
|
/mob/living/carbon/human/species/shadow
|
|
race = /datum/species/shadow
|
|
|
|
/mob/living/carbon/human/species/shadow/nightmare
|
|
race = /datum/species/shadow/nightmare
|
|
|
|
/mob/living/carbon/human/species/skeleton
|
|
race = /datum/species/skeleton
|
|
|
|
/mob/living/carbon/human/species/synth
|
|
race = /datum/species/synth
|
|
|
|
/mob/living/carbon/human/species/synth/military
|
|
race = /datum/species/synth/military
|
|
|
|
/mob/living/carbon/human/species/vampire
|
|
race = /datum/species/vampire
|
|
|
|
/mob/living/carbon/human/species/zombie
|
|
race = /datum/species/zombie
|
|
|
|
/mob/living/carbon/human/species/zombie/infectious
|
|
race = /datum/species/zombie/infectious
|
|
|
|
/mob/living/carbon/human/species/zombie/krokodil_addict
|
|
race = /datum/species/krokodil_addict
|
|
|
|
/mob/living/carbon/human/species/mammal
|
|
race = /datum/species/mammal
|
|
|
|
/mob/living/carbon/human/species/insect
|
|
race = /datum/species/insect
|
|
|
|
/mob/living/carbon/human/species/xeno
|
|
race = /datum/species/xeno
|
|
|
|
/mob/living/carbon/human/species/ipc
|
|
race = /datum/species/ipc
|
|
|
|
/mob/living/carbon/human/species/roundstartslime
|
|
race = /datum/species/jelly/roundstartslime
|
|
|
|
/mob/living/carbon/human/species/arachnid
|
|
race = /datum/species/arachnid
|