Further work on properly integrating, updating and fixing prosthetic options.

WIP
Allowed heads/bodies to be prosthetic. Removed IPC. Refactored some flags.
This commit is contained in:
Zuhayr
2015-12-18 18:23:58 +10:30
parent c886810238
commit d71573e749
102 changed files with 925 additions and 722 deletions

View File

@@ -880,12 +880,15 @@ var/list/admin_verbs_mentor = list(
if(new_fstyle)
M.f_style = new_fstyle
var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female")
var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female", "Neuter")
if (new_gender)
if(new_gender == "Male")
M.gender = MALE
else
else if (new_gender == "Female")
M.gender = FEMALE
else
M.gender = NEUTER
M.update_hair()
M.update_body()
M.check_dna(M)

View File

@@ -1,7 +1,7 @@
/datum/category_item/player_setup_item/general/basic
name = "Basic"
sort_order = 1
var/list/valid_player_genders = list(MALE, FEMALE)
var/list/valid_player_genders = list(MALE, FEMALE, NEUTER, PLURAL)
/datum/category_item/player_setup_item/general/basic/load_character(var/savefile/S)
S["real_name"] >> pref.real_name

View File

@@ -75,8 +75,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
/datum/category_item/player_setup_item/general/body/content(var/mob/user)
pref.update_preview_icon()
if(pref.preview_icon_front && pref.preview_icon_side)
user << browse_rsc(pref.preview_icon_front, "previewicon.png")
user << browse_rsc(pref.preview_icon_side, "previewicon2.png")
user << browse_rsc(pref.preview_icon_front, "preview_icon.png")
user << browse_rsc(pref.preview_icon_side, "preview_icon2.png")
var/mob_species = all_species[pref.species]
. += "<table><tr style='vertical-align:top'><td><b>Body</b> "
@@ -87,7 +87,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(has_flag(mob_species, HAS_SKIN_TONE))
. += "Skin Tone: <a href='?src=\ref[src];skin_tone=1'>[-pref.s_tone + 35]/220</a><br>"
. += "Needs Glasses: <a href='?src=\ref[src];disabilities=[NEARSIGHTED]'><b>[pref.disabilities & NEARSIGHTED ? "Yes" : "No"]</b></a><br>"
. += "Limbs: <a href='?src=\ref[src];limbs=1'>Adjust</a><br>"
. += "Limbs: <a href='?src=\ref[src];limbs=1'>Adjust</a> <a href='?src=\ref[src];reset_limbs=1'>Reset</a><br>"
. += "Internal Organs: <a href='?src=\ref[src];organs=1'>Adjust</a><br>"
//display limbs below
@@ -96,6 +96,13 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/status = pref.organ_data[name]
var/organ_name = null
switch(name)
if("torso")
organ_name = "torso"
if("groin")
organ_name = "groin"
if("head")
organ_name = "head"
if("l_arm")
organ_name = "left arm"
if("r_arm")
@@ -116,6 +123,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
organ_name = "heart"
if("eyes")
organ_name = "eyes"
if("brain")
organ_name = "brain"
if(status == "cyborg")
++ind
@@ -136,7 +145,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
++ind
if(ind > 1)
. += ", "
. += "\tMechanical [organ_name]"
. += "\tSynthetic [organ_name]"
else if(status == "assisted")
++ind
if(ind > 1)
@@ -148,6 +157,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
. += "\tSurgically altered [organ_name]"
if("eyes")
. += "\tRetinal overlayed [organ_name]"
if("brain")
. += "\tAssisted-interface [organ_name]"
else
. += "\tMechanically assisted [organ_name]"
if(!ind)
@@ -155,7 +166,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
else
. += "<br><br>"
. += "</td><td><b>Preview</b><br><img src=previewicon.png height=64 width=64><img src=previewicon2.png height=64 width=64>"
. += "</td><td><b>Preview</b><br><img src=preview_icon.png height=64 width=64><img src=preview_icon2.png height=64 width=64>"
. += "</td></tr></table>"
. += "<b>Hair</b><br>"
@@ -252,6 +263,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.b_hair = 0//hex2num(copytext(new_hair, 6, 8))
pref.s_tone = 0
reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case.
return TOPIC_REFRESH
else if(href_list["hair_color"])
@@ -334,8 +346,12 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.f_style = new_f_style
return TOPIC_REFRESH
else if(href_list["reset_limbs"])
reset_limbs()
return TOPIC_REFRESH
else if(href_list["limbs"])
var/limb_name = input(user, "Which limb do you want to change?") as null|anything in list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand")
var/limb_name = input(user, "Which limb do you want to change?") as null|anything in list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand","Full Body")
if(!limb_name && !CanUseTopic(user)) return TOPIC_NOACTION
var/limb = null
@@ -366,6 +382,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if("Right Hand")
limb = "r_hand"
third_limb = "r_arm"
if("Full Body")
limb = "torso"
var/new_state = input(user, "What state do you wish the limb to be in?") as null|anything in list("Normal","Amputated","Prothesis")
if(!new_state && !CanUseTopic(user)) return TOPIC_NOACTION
@@ -378,6 +397,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.organ_data[third_limb] = null
pref.rlimb_data[third_limb] = null
if("Amputated")
if(limb == "torso")
return
pref.organ_data[limb] = "amputated"
pref.rlimb_data[limb] = null
if(second_limb)
@@ -397,17 +420,31 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/choice = input(user, "Which manufacturer do you wish to use for this limb?") as null|anything in usable_manufacturers
if(!choice)
return
pref.rlimb_data[limb] = choice
pref.organ_data[limb] = "cyborg"
if(second_limb)
pref.rlimb_data[second_limb] = choice
pref.organ_data[second_limb] = "cyborg"
if(third_limb && pref.organ_data[third_limb] == "amputated")
pref.organ_data[third_limb] = null
if(limb == "torso")
for(var/other_limb in list("l_foot","r_foot","l_hand","r_hand","l_leg","r_leg","l_arm","r_arm","groin","head"))
if(pref.organ_data[other_limb])
continue
pref.organ_data[other_limb] = "cyborg"
pref.rlimb_data[other_limb] = choice
if(!pref.organ_data["brain"])
pref.organ_data["brain"] = "assisted"
for(var/internal_organ in list("heart","eyes"))
pref.organ_data[internal_organ] = "mechanical"
return TOPIC_REFRESH
else if(href_list["organs"])
var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes")
var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes", "Brain")
if(!organ_name) return
var/organ = null
@@ -416,12 +453,20 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
organ = "heart"
if("Eyes")
organ = "eyes"
if("Brain")
if(pref.organ_data["head"] != "cyborg")
user << "<span class='warning'>You may only select an assisted or synthetic brain if you have a full prosthetic body.</span>"
return
organ = "brain"
var/new_state = input(user, "What state do you wish the organ to be in?") as null|anything in list("Normal","Assisted","Mechanical")
if(!new_state) return
switch(new_state)
if("Normal")
if(pref.organ_data["torso"] == "cyborg")
user << "<span class='warning'>A character with a synthetic body may only use synthetic organs.</span>"
return
pref.organ_data[organ] = null
if("Assisted")
pref.organ_data[organ] = "assisted"
@@ -436,6 +481,18 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
return ..()
/datum/category_item/player_setup_item/general/body/proc/reset_limbs()
for(var/organ in pref.organ_data)
pref.organ_data[organ] = null
while(null in pref.organ_data)
pref.organ_data -= null
for(var/organ in pref.rlimb_data)
pref.rlimb_data[organ] = null
while(null in pref.rlimb_data)
pref.rlimb_data -= null
/datum/category_item/player_setup_item/general/body/proc/SetSpecies(mob/user)
if(!pref.species_preview || !(pref.species_preview in all_species))
pref.species_preview = "Human"
@@ -455,10 +512,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
dat += "</br><b>Often present on human stations.</b>"
if(current_species.spawn_flags & IS_WHITELISTED)
dat += "</br><b>Whitelist restricted.</b>"
if(current_species.flags & NO_BLOOD)
dat += "</br><b>Does not have blood.</b>"
if(current_species.flags & NO_BREATHE)
dat += "</br><b>Does not breathe.</b>"
if(!current_species.has_organ["heart"])
dat += "</br><b>Does not have a circulatory system.</b>"
if(!current_species.has_organ["lungs"])
dat += "</br><b>Does not have a respiratory system.</b>"
if(current_species.flags & NO_SCAN)
dat += "</br><b>Does not have DNA.</b>"
if(current_species.flags & NO_PAIN)

View File

@@ -310,6 +310,8 @@ datum/preferences
var/status = organ_data[name]
var/obj/item/organ/external/O = character.organs_by_name[name]
if(name == "torso" && !O)
O = character.organs_by_name["chest"]
if(O)
O.status = 0
if(status == "amputated")
@@ -334,20 +336,14 @@ datum/preferences
I.robotize()
character.underwear = underwear
character.undershirt = undershirt
character.socks = socks
if(backbag > 4 || backbag < 1)
backbag = 1 //Same as above
character.backbag = backbag
//Debugging report to track down a bug, which randomly assigned the plural gender to people.
if(character.gender in list(PLURAL, NEUTER))
if(isliving(src)) //Ghosts get neuter by default
message_admins("[character] ([character.ckey]) has spawned with their gender as plural or neuter. Please notify coders.")
character.gender = MALE
character.update_body()
/datum/preferences/proc/open_load_dialog(mob/user)
var/dat = "<body>"

View File

@@ -99,10 +99,9 @@
var/sound = "heartbeat"
var/sound_strength = "cannot hear"
var/heartbeat = 0
if(M.species && M.species.has_organ["heart"])
var/obj/item/organ/heart/heart = M.internal_organs_by_name["heart"]
if(heart && !heart.robotic)
heartbeat = 1
var/obj/item/organ/heart/heart = M.internal_organs_by_name["heart"]
if(heart && !(heart.status & ORGAN_ROBOT))
heartbeat = 1
if(M.stat == DEAD || (M.status_flags&FAKEDEATH))
sound_strength = "cannot hear"
sound = "anything"
@@ -112,7 +111,6 @@
sound_strength = "hear"
sound = "no heartbeat"
if(heartbeat)
var/obj/item/organ/heart/heart = M.internal_organs_by_name["heart"]
if(heart.is_bruised() || M.getOxyLoss() > 50)
sound = "[pick("odd noises in","weak")] heartbeat"
else

View File

@@ -96,13 +96,13 @@
/datum/language/machine
name = "Encoded Audio Language"
desc = "A language of encoded tones that allow for IPCs to communicate auditorily between each other in a manner that allows for easier transfer of information."
speech_verb = "beeps"
ask_verb = "beeps"
exclaim_verb = "loudly beeps"
desc = "A efficient language of encoded tones developed by synthetics and cyborgs."
speech_verb = "whistles"
ask_verb = "chirps"
exclaim_verb = "whistles loudly"
colour = "changeling"
key = "6"
flags = RESTRICTED | NO_STUTTER
flags = NO_STUTTER
syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz")
space_chance = 10

View File

@@ -60,7 +60,7 @@
brainobj = O
brainobj.loc = src
name = "Man-Machine Interface: [brainmob.real_name]"
name = "man-machine interface ([brainmob.real_name])"
icon_state = "mmi_full"
locked = 1

View File

@@ -15,6 +15,25 @@
attack_verb = list("attacked", "slapped", "whacked")
var/mob/living/carbon/brain/brainmob = null
/obj/item/organ/brain/robotize()
replace_self_with(/obj/item/organ/mmi_holder/posibrain)
/obj/item/organ/brain/mechassist()
replace_self_with(/obj/item/organ/mmi_holder)
/obj/item/organ/brain/proc/replace_self_with(replace_path)
if(!owner)
new replace_path(src.loc)
qdel(src)
return
owner.internal_organs_by_name[organ_tag] = new replace_path(owner, 1)
owner.internal_organs -= src
while(null in owner.internal_organs_by_name)
owner.internal_organs_by_name -= null
while(null in owner.internal_organs)
owner.internal_organs -= null
/obj/item/organ/pariah_brain
name = "brain remnants"
desc = "Did someone tread on this? It looks useless for cloning or cyborgification."
@@ -93,13 +112,11 @@
/obj/item/organ/brain/slime
name = "slime core"
desc = "A complex, organic knot of jelly and crystalline particles."
robotic = 2
icon = 'icons/mob/slimes.dmi'
icon_state = "green slime extract"
/obj/item/organ/brain/golem
name = "chem"
desc = "A tightly furled roll of paper, covered with indecipherable runes."
robotic = 2
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll"

View File

@@ -7,7 +7,7 @@
/mob/living/carbon/proc/breathe()
//if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return
if(species && (species.flags & NO_BREATHE) || does_not_breathe) return
if(!should_have_organ("lungs") || does_not_breathe) return
var/datum/gas_mixture/breath = null

View File

@@ -472,3 +472,11 @@
if(!species)
return null
return species.default_language ? all_languages[species.default_language] : null
/mob/living/carbon/proc/should_have_organ(var/organ_check)
return 0
/mob/living/carbon/proc/can_feel_pain(var/check_organ)
if(isSynthetic())
return 0
return !(species.flags & NO_PAIN)

View File

@@ -8,7 +8,7 @@
var/mob/living/simple_animal/borer/B = has_brain_worms()
if(B && B.host_brain)
src << "\red <B>You withdraw your probosci, releasing control of [B.host_brain]</B>"
src << "<span class='danger'>You withdraw your probosci, releasing control of [B.host_brain]</span>"
B.detatch()
@@ -17,7 +17,7 @@
verbs -= /mob/living/carbon/proc/spawn_larvae
else
src << "\red <B>ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !</B>"
src << "<span class='danger'>ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !</span>"
//Brain slug proc for tormenting the host.
/mob/living/carbon/proc/punish_host()
@@ -31,13 +31,12 @@
return
if(B.host_brain.ckey)
src << "\red <B>You send a punishing spike of psychic agony lancing into your host's brain.</B>"
if (species && (species.flags & NO_PAIN))
B.host_brain << "\red You feel a strange sensation as a foreign influence prods your mind."
src << "\red <B>It doesn't seem to be as effective as you hoped.</B>"
src << "<span class='danger'>You send a punishing spike of psychic agony lancing into your host's brain.</span>"
if (!can_feel_pain())
B.host_brain << "<span class='warning'>You feel a strange sensation as a foreign influence prods your mind.</span>"
src << "<span class='danger'>It doesn't seem to be as effective as you hoped.</span>"
else
B.host_brain << "\red <B><FONT size=3>Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!</FONT></B>"
B.host_brain << "<span class='danger'><FONT size=3>Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!</FONT></span>"
/mob/living/carbon/proc/spawn_larvae()
set category = "Abilities"
@@ -50,15 +49,14 @@
return
if(B.chemicals >= 100)
src << "\red <B>Your host twitches and quivers as you rapidly excrete a larva from your sluglike body.</B>"
visible_message("\red <B>[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!</B>")
src << "<span class='danger'>Your host twitches and quivers as you rapidly excrete a larva from your sluglike body.</span>"
visible_message("<span class='danger'>\The [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!</span>")
B.chemicals -= 100
B.has_reproduced = 1
new /obj/effect/decal/cleanable/vomit(get_turf(src))
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
vomit(1)
new /mob/living/simple_animal/borer(get_turf(src))
else
src << "You do not have enough chemicals stored to reproduce."
src << "<span class='warning'>You do not have enough chemicals stored to reproduce.</span>"
return

View File

@@ -157,30 +157,44 @@
return valid_species
/mob/living/carbon/human/proc/generate_valid_hairstyles(var/check_gender = 1)
var/use_species = species.get_bodytype()
var/obj/item/organ/external/head/H = get_organ("head")
if(H) use_species = H.species.get_bodytype()
var/list/valid_hairstyles = new()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
if(check_gender && gender == MALE && S.gender == FEMALE)
continue
if(check_gender && gender == FEMALE && S.gender == MALE)
continue
if(!(species.get_bodytype() in S.species_allowed))
if(check_gender && gender != NEUTER)
if(gender == MALE && S.gender == FEMALE)
continue
else if(gender == FEMALE && S.gender == MALE)
continue
if(!(use_species in S.species_allowed))
continue
valid_hairstyles += hairstyle
return valid_hairstyles
/mob/living/carbon/human/proc/generate_valid_facial_hairstyles()
var/use_species = species.get_bodytype()
var/obj/item/organ/external/head/H = get_organ("head")
if(H) use_species = H.species.get_bodytype()
var/list/valid_facial_hairstyles = new()
for(var/facialhairstyle in facial_hair_styles_list)
var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle]
if(gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
continue
if(!(species.get_bodytype() in S.species_allowed))
if(gender != NEUTER)
if(gender == MALE && S.gender == FEMALE)
continue
else if(gender == FEMALE && S.gender == MALE)
continue
if(!(use_species in S.species_allowed))
continue
valid_facial_hairstyles += facialhairstyle

View File

@@ -15,7 +15,7 @@
I.throw_at(get_edge_target_turf(src,pick(alldirs)), rand(1,3), round(30/I.w_class))
..(species.gibbed_anim)
gibs(loc, viruses, dna, null, species.flesh_color, species.blood_color)
gibs(loc, viruses, dna, null, species.get_flesh_colour(src), species.get_blood_colour(src))
/mob/living/carbon/human/dust()
if(species)
@@ -68,7 +68,7 @@
if(wearing_rig)
wearing_rig.notify_ai("<span class='danger'>Warning: user death event. Mobility control passed to integrated intelligence system.</span>")
return ..(gibbed,species.death_message)
return ..(gibbed,species.get_death_message(src))
/mob/living/carbon/human/proc/ChangeToHusk()
if(HUSK in mutations) return

View File

@@ -207,7 +207,7 @@
m_type = 2
if ("deathgasp")
message = "[species.death_message]"
message = "[species.get_death_message()]"
m_type = 1
if ("giggle")

View File

@@ -38,9 +38,21 @@
CRASH("Gender datum was null; key was '[(skipjumpsuit && skipface) ? PLURAL : gender]'")
msg += "<EM>[src.name]</EM>"
if(species.name != "Human")
msg += ", a <b><font color='[species.flesh_color]'>[species.name]</font></b>"
msg += "!\n"
var/is_synth = isSynthetic()
if(is_synth)
var/use_gender = "a synthetic"
if(gender == MALE)
use_gender = "an android"
else if(gender == FEMALE)
use_gender = "a gynoid"
msg += ", <font color='#555555'>[use_gender]!</font></b>"
else if(species.name != "Human")
msg += ", <b><font color='[species.get_flesh_colour(src)]'>\a [species.name]!</font></b>"
msg += "<br>"
//uniform
if(w_uniform && !skipjumpsuit)
@@ -230,11 +242,12 @@
if(getBrainLoss() >= 60)
msg += "[T.He] [T.has] a stupid expression on [T.his] face.\n"
if(species.show_ssd && (!species.has_organ["brain"] || has_brain()) && stat != DEAD)
var/ssd_msg = species.get_ssd(src)
if(ssd_msg && (!should_have_organ("brain") || has_brain()) && stat != DEAD)
if(!key)
msg += "<span class='deadsay'>[T.He] [T.is] [species.show_ssd]. It doesn't look like [T.he] [T.is] waking up anytime soon.</span>\n"
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] [species.show_ssd].</span>\n"
msg += "<span class='deadsay'>[T.He] [T.is] [ssd_msg].</span>\n"
var/list/wound_flavor_text = list()
var/list/is_destroyed = list()
@@ -261,12 +274,12 @@
is_destroyed["[temp.name]"] = 1
wound_flavor_text["[temp.name]"] = "<span class='warning'><b>[T.He] [T.is] missing [T.his] [temp.name].</b></span>\n"
continue
if(temp.status & ORGAN_ROBOT)
if(!is_synth && temp.status & ORGAN_ROBOT)
if(!(temp.brute_dam + temp.burn_dam))
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a robot [temp.name]!</span>\n"
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a [temp.name]!</span>\n"
continue
else
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a robot [temp.name]. It has[temp.get_wounds_desc()]!</span>\n"
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a [temp.name]. It has[temp.get_wounds_desc()]!</span>\n"
else if(temp.wounds.len > 0 || temp.open)
if(temp.is_stump() && temp.parent_organ && organs_by_name[temp.parent_organ])
var/obj/item/organ/external/parent = organs_by_name[temp.parent_organ]

View File

@@ -654,18 +654,12 @@
///eyecheck()
///Returns a number between -1 to 2
/mob/living/carbon/human/eyecheck()
var/obj/item/organ/I = internal_organs_by_name["eyes"]
if(!I || I.status & (ORGAN_CUT_AWAY|ORGAN_DESTROYED))
return 2
var/number = 0
if(!species.has_organ["eyes"]) //No eyes, can't hurt them.
return 2
if(internal_organs_by_name["eyes"]) // Eyes are fucked, not a 'weak point'.
var/obj/item/organ/I = internal_organs_by_name["eyes"]
if(I.status & ORGAN_CUT_AWAY)
return 2
else
return 2
if(istype(src.head, /obj/item/clothing/head/welding))
if(!src.head:up)
number += 2
@@ -690,8 +684,6 @@
//Used by various things that knock people out by applying blunt trauma to the head.
//Checks that the species has a "head" (brain containing organ) and that hit_zone refers to it.
/mob/living/carbon/human/proc/headcheck(var/target_zone, var/brain_tag = "brain")
if(!species.has_organ[brain_tag])
return 0
var/obj/item/organ/affecting = internal_organs_by_name[brain_tag]
@@ -745,38 +737,16 @@
xylophone=0
return
/mob/living/carbon/human/proc/check_has_mouth()
/mob/living/proc/check_has_mouth()
return 1
/mob/living/carbon/human/check_has_mouth()
// Todo, check stomach organ when implemented.
var/obj/item/organ/external/head/H = get_organ("head")
if(!H || !H.can_intake_reagents)
return 0
return 1
/mob/living/carbon/human/proc/vomit()
if(!check_has_mouth())
return
if(!lastpuke)
lastpuke = 1
src << "<span class='warning'>You feel nauseous...</span>"
spawn(150) //15 seconds until second warning
src << "<span class='warning'>You feel like you are about to throw up!</span>"
spawn(100) //and you have 10 more for mad dash to the bucket
Stun(5)
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)
var/turf/location = loc
if (istype(location, /turf/simulated))
location.add_vomit_floor(src, 1)
nutrition -= 40
adjustToxLoss(-3)
spawn(350) //wait 35 seconds before next volley
lastpuke = 0
/mob/living/carbon/human/proc/morph()
set name = "Morph"
set category = "Superpower"
@@ -846,12 +816,14 @@
if(new_style)
f_style = new_style
var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female")
var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female", "Neutral")
if (new_gender)
if(new_gender == "Male")
gender = MALE
else
else if(new_gender == "Female")
gender = FEMALE
else
gender = NEUTER
regenerate_icons()
check_dna()
@@ -936,13 +908,12 @@
/mob/living/carbon/human/revive()
if(species && !(species.flags & NO_BLOOD))
if(should_have_organ("heart"))
vessel.add_reagent("blood",560-vessel.total_volume)
fixblood()
// Fix up all organs.
// This will ignore any prosthetics in the prefs currently.
species.create_organs(src)
species.create_organs(src) // Reset our organs/limbs.
restore_all_organs() // Reapply robotics/amputated status from preferences.
if(!client || !key) //Don't boot out anyone already in the mob.
for (var/obj/item/organ/brain/H in world)
@@ -1057,7 +1028,7 @@
for(var/obj/item/O in organ.implants)
if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad.
// All kinds of embedded objects cause bleeding.
if(species.flags & NO_PAIN)
if(!can_feel_pain(organ.limb_name))
src << "<span class='warning'>You feel [O] moving inside your [organ.name].</span>"
else
var/msg = pick( \
@@ -1067,7 +1038,7 @@
src << msg
organ.take_damage(rand(1,3), 0, 0)
if(!(organ.status & ORGAN_ROBOT) && !(species.flags & NO_BLOOD)) //There is no blood in protheses.
if(!(organ.status & ORGAN_ROBOT) && !should_have_organ("heart")) //There is no blood in protheses.
organ.status |= ORGAN_BLEEDING
src.adjustToxLoss(rand(1,3))
@@ -1302,11 +1273,15 @@
/mob/living/carbon/human/getDNA()
if(species.flags & NO_SCAN)
return null
if(isSynthetic())
return
..()
/mob/living/carbon/human/setDNA()
if(species.flags & NO_SCAN)
return
if(isSynthetic())
return
..()
/mob/living/carbon/human/has_brain()
@@ -1423,3 +1398,24 @@
pulling_punches = !pulling_punches
src << "<span class='notice'>You are now [pulling_punches ? "pulling your punches" : "not pulling your punches"].</span>"
return
/mob/living/carbon/human/should_have_organ(var/organ_check)
var/obj/item/organ/external/affecting
if(organ_check in list("heart","lungs"))
affecting = organs_by_name["chest"]
else if(organ_check in list("liver","kidneys"))
affecting = organs_by_name["groin"]
if(affecting && (affecting.status & ORGAN_ROBOT))
return 0
return (species && species.has_organ[organ_check])
/mob/living/carbon/human/can_feel_pain(var/obj/item/organ/check_organ)
if(isSynthetic())
return 0
if(check_organ)
if(!istype(check_organ))
return 0
return check_organ.can_feel_pain()
return !(species.flags & NO_PAIN)

View File

@@ -13,7 +13,7 @@
total_brute += O.brute_dam
total_burn += O.burn_dam
var/oxy_l = ((species.flags & NO_BREATHE) ? 0 : getOxyLoss())
var/oxy_l = getOxyLoss()
var/tox_l = ((species.flags & NO_POISON) ? 0 : getToxLoss())
var/clone_l = getCloneLoss()
@@ -28,7 +28,7 @@
if(status_flags & GODMODE) return 0 //godmode
if(species && species.has_organ["brain"])
if(should_have_organ("brain"))
var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"]
if(sponge)
sponge.take_damage(amount)
@@ -42,7 +42,7 @@
if(status_flags & GODMODE) return 0 //godmode
if(species && species.has_organ["brain"])
if(should_have_organ("brain"))
var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"]
if(sponge)
sponge.damage = min(max(amount, 0),(maxHealth*2))
@@ -56,7 +56,7 @@
if(status_flags & GODMODE) return 0 //godmode
if(species && species.has_organ["brain"])
if(should_have_organ("brain"))
var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"]
if(sponge)
brainloss = min(sponge.damage,maxHealth*2)
@@ -142,12 +142,12 @@
..()
/mob/living/carbon/human/getCloneLoss()
if(species.flags & (NO_SCAN))
if((species.flags & NO_SCAN) || isSynthetic())
cloneloss = 0
return ..()
/mob/living/carbon/human/setCloneLoss(var/amount)
if(species.flags & (NO_SCAN))
if((species.flags & NO_SCAN) || isSynthetic())
cloneloss = 0
else
..()
@@ -155,7 +155,7 @@
/mob/living/carbon/human/adjustCloneLoss(var/amount)
..()
if(species.flags & (NO_SCAN))
if((species.flags & NO_SCAN) || isSynthetic())
cloneloss = 0
return
@@ -189,37 +189,37 @@
// Defined here solely to take species flags into account without having to recast at mob/living level.
/mob/living/carbon/human/getOxyLoss()
if(species.flags & NO_BREATHE)
if(!should_have_organ("lungs"))
oxyloss = 0
return ..()
/mob/living/carbon/human/adjustOxyLoss(var/amount)
if(species.flags & NO_BREATHE)
if(!should_have_organ("lungs"))
oxyloss = 0
else
amount = amount*species.oxy_mod
..(amount)
/mob/living/carbon/human/setOxyLoss(var/amount)
if(species.flags & NO_BREATHE)
if(!should_have_organ("lungs"))
oxyloss = 0
else
..()
/mob/living/carbon/human/getToxLoss()
if(species.flags & NO_POISON)
if((species.flags & NO_POISON) || isSynthetic())
toxloss = 0
return ..()
/mob/living/carbon/human/adjustToxLoss(var/amount)
if(species.flags & NO_POISON)
if((species.flags & NO_POISON) || isSynthetic())
toxloss = 0
else
amount = amount*species.toxins_mod
..(amount)
/mob/living/carbon/human/setToxLoss(var/amount)
if(species.flags & NO_POISON)
if((species.flags & NO_POISON) || isSynthetic())
toxloss = 0
else
..()
@@ -321,7 +321,7 @@ In most cases it makes more sense to use apply_damage() instead! And make sure t
This function restores the subjects blood to max.
*/
/mob/living/carbon/human/proc/restore_blood()
if(!(species.flags & NO_BLOOD))
if(should_have_organ("heart"))
var/blood_volume = vessel.get_reagent_amount("blood")
vessel.add_reagent("blood",560.0-blood_volume)
@@ -329,9 +329,9 @@ This function restores the subjects blood to max.
/*
This function restores all organs.
*/
/mob/living/carbon/human/restore_all_organs()
/mob/living/carbon/human/restore_all_organs(var/ignore_prosthetic_prefs)
for(var/obj/item/organ/external/current_organ in organs)
current_organ.rejuvenate()
current_organ.rejuvenate(ignore_prosthetic_prefs)
/mob/living/carbon/human/proc/HealDamage(zone, brute, burn)
var/obj/item/organ/external/E = get_organ(zone)
@@ -354,14 +354,19 @@ This function restores all organs.
if(Debug2)
world.log << "## DEBUG: human/apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked]."
//visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]")
var/obj/item/organ/external/organ = null
if(isorgan(def_zone))
organ = def_zone
else
if(!def_zone) def_zone = ran_zone(def_zone)
organ = get_organ(check_zone(def_zone))
//Handle other types of damage
if((damagetype != BRUTE) && (damagetype != BURN))
if(damagetype == HALLOSS && !(species && (species.flags & NO_PAIN)))
if ((damage > 25 && prob(20)) || (damage > 50 && prob(60)))
emote("scream")
if(damagetype == HALLOSS)
if((damage > 25 && prob(20)) || (damage > 50 && prob(60)))
if(organ && organ.can_feel_pain())
emote("scream")
..(damage, damagetype, def_zone, blocked)
return 1
@@ -371,12 +376,7 @@ This function restores all organs.
if(blocked >= 100)
return 0
var/obj/item/organ/external/organ = null
if(isorgan(def_zone))
organ = def_zone
else
if(!def_zone) def_zone = ran_zone(def_zone)
organ = get_organ(check_zone(def_zone))
if(!organ) return 0
if(blocked)

View File

@@ -61,7 +61,7 @@ emp_act
emote("me", 1, "drops what they were holding, their [affected.name] malfunctioning!")
else
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
emote("me", 1, "[(species && species.flags & NO_PAIN) ? "" : emote_scream ]drops what they were holding in their [affected.name]!")
emote("me", 1, "[affected.can_feel_pain() ? "" : emote_scream]drops what they were holding in their [affected.name]!")
..(stun_amount, agony_amount, def_zone)
@@ -223,7 +223,7 @@ emp_act
//Harder to score a stun but if you do it lasts a bit longer
if(prob(effective_force))
apply_effect(20, PARALYZE, armor)
visible_message("<span class='danger'>[src] [species.knockout_message]</span>")
visible_message("<span class='danger'>[src] [species.get_knockout_message(src)]</span>")
else
//Easier to score a stun but lasts less time
if(prob(effective_force + 10))

View File

@@ -83,6 +83,7 @@
var/list/flavor_texts = list()
var/gunshot_residue
var/pulling_punches // Are you trying not to hurt your opponent?
var/full_prosthetic // We are a robutt.
mob_bump_flag = HUMAN
mob_push_flags = ~HEAVY

View File

@@ -16,7 +16,7 @@
var/health_deficiency = (100 - health)
if(health_deficiency >= 40) tally += (health_deficiency / 25)
if (!(species && (species.flags & NO_PAIN)))
if(can_feel_pain())
if(halloss >= 10) tally += (halloss / 10) //halloss shouldn't slow you down if you can't even feel it
var/hungry = (500 - nutrition)/5 // So overeat would be 100 and default level would be 80
@@ -42,7 +42,7 @@
var/obj/item/organ/external/E = get_organ(organ_name)
if(!E || (E.status & ORGAN_DESTROYED))
tally += 4
if(E.status & ORGAN_SPLINTED)
else if(E.status & ORGAN_SPLINTED)
tally += 0.5
else if(E.status & ORGAN_BROKEN)
tally += 1.5

View File

@@ -68,6 +68,7 @@
if (istype(buckled, /obj/structure/bed))
return
var/limb_pain
for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot"))
var/obj/item/organ/external/E = organs_by_name[limb_tag]
if(!E || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD)))
@@ -88,6 +89,8 @@
else if (E.is_dislocated())
stance_damage += 0.5
if(E) limb_pain = E.can_feel_pain()
// Canes and crutches help you stand (if the latter is ever added)
// One cane mitigates a broken leg+foot, or a missing foot.
// Two canes are needed for a lost leg. If you are missing both legs, canes aren't gonna help you.
@@ -99,7 +102,7 @@
// standing is poor
if(stance_damage >= 4 || (stance_damage >= 2 && prob(5)))
if(!(lying || resting))
if(species && !(species.flags & NO_PAIN))
if(limb_pain)
emote("scream")
custom_emote(1, "collapses!")
Weaken(5) //can't emote while weakened, apparently.
@@ -145,7 +148,7 @@
drop_from_inventory(r_hand)
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
emote("me", 1, "[(species.flags & NO_PAIN) ? "" : emote_scream ]drops what they were holding in their [E.name]!")
emote("me", 1, "[(E.can_feel_pain()) ? "" : emote_scream ]drops what they were holding in their [E.name]!")
else if(E.is_malfunctioning())
switch(E.body_part)

View File

@@ -40,7 +40,6 @@ This saves us from having to call add_fingerprint() any time something is put in
/mob/living/carbon/human/proc/has_organ(name)
var/obj/item/organ/external/O = organs_by_name[name]
return (O && !(O.status & ORGAN_DESTROYED) && !O.is_stump())
/mob/living/carbon/human/proc/has_organ_for_slot(slot)

View File

@@ -254,6 +254,12 @@
radiation = Clamp(radiation,0,100)
if (radiation)
// TODO.
if(isSynthetic())
radiation = 0
return
var/obj/item/organ/diona/nutrients/rad_organ = locate() in internal_organs
if(rad_organ && !rad_organ.is_broken())
var/rads = radiation/25
@@ -365,7 +371,7 @@
var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa
// Lung damage increases the minimum safe pressure.
if(species.has_organ["lungs"])
if(should_have_organ("lungs"))
var/obj/item/organ/lungs/L = internal_organs_by_name["lungs"]
if(isnull(L))
safe_pressure_min = INFINITY //No lungs, how are you breathing?
@@ -831,6 +837,7 @@
return min(1,thermal_protection)
/mob/living/carbon/human/handle_chemicals_in_body()
if(in_stasis)
return
@@ -838,43 +845,48 @@
chem_effects.Cut()
analgesic = 0
if(touching) touching.metabolize()
if(ingested) ingested.metabolize()
if(bloodstr) bloodstr.metabolize()
if(!isSynthetic())
if(CE_PAINKILLER in chem_effects)
analgesic = chem_effects[CE_PAINKILLER]
if(touching) touching.metabolize()
if(ingested) ingested.metabolize()
if(bloodstr) bloodstr.metabolize()
var/total_phoronloss = 0
for(var/obj/item/I in src)
if(I.contaminated)
total_phoronloss += vsc.plc.CONTAMINATION_LOSS
if(!(status_flags & GODMODE)) adjustToxLoss(total_phoronloss)
if(CE_PAINKILLER in chem_effects)
analgesic = chem_effects[CE_PAINKILLER]
var/total_phoronloss = 0
for(var/obj/item/I in src)
if(I.contaminated)
total_phoronloss += vsc.plc.CONTAMINATION_LOSS
if(!(status_flags & GODMODE)) adjustToxLoss(total_phoronloss)
if(status_flags & GODMODE) return 0 //godmode
var/obj/item/organ/diona/node/light_organ = locate() in internal_organs
if(light_organ && !light_organ.is_broken())
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(loc)) //else, there's considered to be no light
var/turf/T = loc
var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T
if(L)
light_amount = min(10,L.lum_r + L.lum_g + L.lum_b) - 5 //hardcapped so it's not abused by having a ton of flashlights
else
light_amount = 5
nutrition += light_amount
traumatic_shock -= light_amount
if(species.flags & IS_PLANT)
if(nutrition > 450)
nutrition = 450
if(light_amount >= 3) //if there's enough light, heal
adjustBruteLoss(-(round(light_amount/2)))
adjustFireLoss(-(round(light_amount/2)))
adjustToxLoss(-(light_amount))
adjustOxyLoss(-(light_amount))
//TODO: heal wounds, heal broken limbs.
if(!isSynthetic())
if(light_organ && !light_organ.is_broken())
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(loc)) //else, there's considered to be no light
var/turf/T = loc
var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T
if(L)
light_amount = min(10,L.lum_r + L.lum_g + L.lum_b) - 5 //hardcapped so it's not abused by having a ton of flashlights
else
light_amount = 5
nutrition += light_amount
traumatic_shock -= light_amount
if(species.flags & IS_PLANT)
if(nutrition > 450)
nutrition = 450
if(light_amount >= 3) //if there's enough light, heal
adjustBruteLoss(-(round(light_amount/2)))
adjustFireLoss(-(round(light_amount/2)))
adjustToxLoss(-(light_amount))
adjustOxyLoss(-(light_amount))
//TODO: heal wounds, heal broken limbs.
if(species.light_dam)
var/light_amount = 0
@@ -901,13 +913,14 @@
if(overeatduration > 1)
overeatduration -= 2 //doubled the unfat rate
if(species.flags & IS_PLANT && (!light_organ || light_organ.is_broken()))
if(!isSynthetic() && (species.flags & IS_PLANT) && (!light_organ || light_organ.is_broken()))
if(nutrition < 200)
take_overall_damage(2,0)
traumatic_shock++
// TODO: stomach and bloodstream organ.
handle_trace_chems()
if(!isSynthetic())
handle_trace_chems()
updatehealth()
@@ -920,7 +933,7 @@
if(status_flags & GODMODE) return 0
//SSD check, if a logged player is awake put them back to sleep!
if(species.show_ssd && !client && !teleop)
if(species.get_ssd(src) && !client && !teleop)
Sleeping(2)
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
blinded = 1
@@ -928,7 +941,7 @@
else //ALIVE. LIGHTS ARE ON
updatehealth() //TODO
if(health <= config.health_threshold_dead || (species.has_organ["brain"] && !has_brain()))
if(health <= config.health_threshold_dead || (should_have_organ("brain") && !has_brain()))
death()
blinded = 1
silent = 0
@@ -1248,7 +1261,7 @@
if(2) healths.icon_state = "health7"
else
//switch(health - halloss)
switch(100 - ((species.flags & NO_PAIN) ? 0 : traumatic_shock))
switch(100 - (!can_feel_pain() ? 0 : traumatic_shock))
if(100 to INFINITY) healths.icon_state = "health0"
if(80 to 100) healths.icon_state = "health1"
if(60 to 80) healths.icon_state = "health2"
@@ -1410,7 +1423,7 @@
// Puke if toxloss is too high
if(!stat)
if (getToxLoss() >= 45 && nutrition > 20)
vomit()
spawn vomit()
//0.1% chance of playing a scary sound to someone who's in complete darkness
if(isturf(loc) && rand(1,1000) == 1)
@@ -1484,7 +1497,7 @@
/mob/living/carbon/human/handle_shock()
..()
if(status_flags & GODMODE) return 0 //godmode
if(species && species.flags & NO_PAIN) return
if(!can_feel_pain()) return
if(health < config.health_threshold_softcrit)// health 0 makes you immediately collapse
shock_stage = max(shock_stage, 61)
@@ -1535,7 +1548,7 @@
/mob/living/carbon/human/proc/handle_pulse()
if(life_tick % 5) return pulse //update pulse every 5 life ticks (~1 tick/sec, depending on server load)
if(species && species.flags & NO_BLOOD)
if(!internal_organs_by_name["heart"])
return PULSE_NONE //No blood, no pulse.
if(stat == DEAD)
@@ -1566,12 +1579,12 @@
return temp
/mob/living/carbon/human/proc/handle_heartbeat()
if(pulse == PULSE_NONE || !species.has_organ["heart"])
if(pulse == PULSE_NONE)
return
var/obj/item/organ/heart/H = internal_organs_by_name["heart"]
if(!H || H.robotic >=2 )
if(!H || (H.status & ORGAN_ROBOT))
return
if(pulse >= PULSE_2FAST || shock_stage >= 10 || istype(get_turf(src), /turf/space))
@@ -1734,7 +1747,7 @@
return slurring
/mob/living/carbon/human/handle_stunned()
if(species.flags & NO_PAIN)
if(!can_feel_pain())
stunned = 0
return 0
if(..())

View File

@@ -18,7 +18,7 @@
remains_type = /obj/effect/decal/cleanable/ash
death_message = "dissolves into ash..."
flags = NO_BLOOD | NO_SCAN | NO_SLIP | NO_POISON | NO_MINOR_CUT
flags = NO_SCAN | NO_SLIP | NO_POISON | NO_MINOR_CUT
spawn_flags = IS_RESTRICTED
/datum/species/shadow/handle_death(var/mob/living/carbon/human/H)

View File

@@ -25,7 +25,6 @@
cold_level_2 = 50
cold_level_3 = 0
eyes = "vox_eyes_s"
gluttonous = 2
breath_type = "nitrogen"
@@ -45,6 +44,21 @@
/mob/living/carbon/human/proc/leap
)
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest),
"groin" = list("path" = /obj/item/organ/external/groin),
"head" = list("path" = /obj/item/organ/external/head/vox),
"l_arm" = list("path" = /obj/item/organ/external/arm),
"r_arm" = list("path" = /obj/item/organ/external/arm/right),
"l_leg" = list("path" = /obj/item/organ/external/leg),
"r_leg" = list("path" = /obj/item/organ/external/leg/right),
"l_hand" = list("path" = /obj/item/organ/external/hand),
"r_hand" = list("path" = /obj/item/organ/external/hand/right),
"l_foot" = list("path" = /obj/item/organ/external/foot),
"r_foot" = list("path" = /obj/item/organ/external/foot/right)
)
has_organ = list(
"heart" = /obj/item/organ/heart,
"lungs" = /obj/item/organ/lungs,

View File

@@ -19,7 +19,6 @@
var/blood_mask = 'icons/mob/human_races/masks/blood_human.dmi'
var/prone_icon // If set, draws this from icobase when mob is prone.
var/eyes = "eyes_s" // Icon for eyes.
var/blood_color = "#A10808" // Red.
var/flesh_color = "#FFC896" // Pink.
var/base_color // Used by changelings. Should also be used for icon previes..
@@ -85,7 +84,7 @@
var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning.
var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure.
var/light_dam // If set, mob will be damaged in light over this value and heal in light below its negative.
var/body_temperature = 310.15 // Non-IS_SYNTHETIC species will try to stabilize at this temperature.
var/body_temperature = 310.15 // Species will try to stabilize at this temperature.
// (also affects temperature processing)
var/heat_discomfort_level = 315 // Aesthetic messages about feeling warm.
@@ -177,6 +176,24 @@
/datum/species/proc/get_bodytype()
return name
/datum/species/proc/get_knockout_message(var/mob/living/carbon/human/H)
return ((H && H.isSynthetic()) ? "encounters a hardware fault and suddenly reboots!" : knockout_message)
/datum/species/proc/get_death_message(var/mob/living/carbon/human/H)
return ((H && H.isSynthetic()) ? "gives one shrill beep before falling lifeless." : death_message)
/datum/species/proc/get_ssd(var/mob/living/carbon/human/H)
return ((H && H.isSynthetic()) ? "flashing a 'system offline' glyph on their monitor" : show_ssd)
/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H)
return ((H && H.isSynthetic()) ? "#1F181F" : blood_color)
/datum/species/proc/get_virus_immune(var/mob/living/carbon/human/H)
return ((H && H.isSynthetic()) ? 1 : virus_immune)
/datum/species/proc/get_flesh_colour(var/mob/living/carbon/human/H)
return ((H && H.isSynthetic()) ? "#575757" : flesh_color)
/datum/species/proc/get_environment_discomfort(var/mob/living/carbon/human/H, var/msg_type)
if(!prob(5))

View File

@@ -7,7 +7,7 @@
language = "Sol Common" //todo?
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch)
flags = NO_BREATHE | NO_PAIN | NO_BLOOD | NO_SCAN | NO_POISON | NO_MINOR_CUT
flags = NO_PAIN | NO_SCAN | NO_POISON | NO_MINOR_CUT
spawn_flags = IS_RESTRICTED
siemens_coefficient = 0

View File

@@ -15,8 +15,6 @@
has_fine_manipulation = 0
show_ssd = null
eyes = "blank_eyes"
gibbed_anim = "gibbed-m"
dusted_anim = "dust-m"
death_message = "lets out a faint chimper as it collapses and stops moving..."
@@ -40,6 +38,20 @@
pass_flags = PASSTABLE
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest),
"groin" = list("path" = /obj/item/organ/external/groin),
"head" = list("path" = /obj/item/organ/external/head/no_eyes),
"l_arm" = list("path" = /obj/item/organ/external/arm),
"r_arm" = list("path" = /obj/item/organ/external/arm/right),
"l_leg" = list("path" = /obj/item/organ/external/leg),
"r_leg" = list("path" = /obj/item/organ/external/leg/right),
"l_hand" = list("path" = /obj/item/organ/external/hand),
"r_hand" = list("path" = /obj/item/organ/external/hand/right),
"l_foot" = list("path" = /obj/item/organ/external/foot),
"r_foot" = list("path" = /obj/item/organ/external/foot/right)
)
/datum/species/monkey/handle_npc(var/mob/living/carbon/human/H)
if(H.stat != CONSCIOUS)
return

View File

@@ -8,7 +8,7 @@
language = null //todo?
unarmed_types = list(/datum/unarmed_attack/slime_glomp)
flags = NO_SCAN | NO_SLIP | NO_BREATHE | NO_MINOR_CUT
flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT
spawn_flags = IS_RESTRICTED
siemens_coefficient = 3 //conductive
darksight = 3

View File

@@ -131,7 +131,6 @@
name_plural = "Skrell"
icobase = 'icons/mob/human_races/r_skrell.dmi'
deform = 'icons/mob/human_races/r_def_skrell.dmi'
eyes = "skrell_eyes_s"
primitive_form = "Neaera"
unarmed_types = list(/datum/unarmed_attack/punch)
blurb = "An amphibious species, Skrell come from the star system known as Qerr'Vallis, which translates to 'Star of \
@@ -152,6 +151,20 @@
reagent_tag = IS_SKRELL
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest),
"groin" = list("path" = /obj/item/organ/external/groin),
"head" = list("path" = /obj/item/organ/external/head/skrell),
"l_arm" = list("path" = /obj/item/organ/external/arm),
"r_arm" = list("path" = /obj/item/organ/external/arm/right),
"l_leg" = list("path" = /obj/item/organ/external/leg),
"r_leg" = list("path" = /obj/item/organ/external/leg/right),
"l_hand" = list("path" = /obj/item/organ/external/hand),
"r_hand" = list("path" = /obj/item/organ/external/hand/right),
"l_foot" = list("path" = /obj/item/organ/external/foot),
"r_foot" = list("path" = /obj/item/organ/external/foot/right)
)
/datum/species/diona
name = "Diona"
name_plural = "Dionaea"
@@ -164,7 +177,6 @@
rarity_value = 3
hud_type = /datum/hud_data/diona
siemens_coefficient = 0.3
eyes = "blank_eyes"
show_ssd = "completely quiescent"
num_alternate_languages = 1
name_language = "Rootspeak"
@@ -189,7 +201,7 @@
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/diona/chest),
"groin" = list("path" = /obj/item/organ/external/diona/groin),
"head" = list("path" = /obj/item/organ/external/diona/head),
"head" = list("path" = /obj/item/organ/external/head/no_eyes/diona),
"l_arm" = list("path" = /obj/item/organ/external/diona/arm),
"r_arm" = list("path" = /obj/item/organ/external/diona/arm/right),
"l_leg" = list("path" = /obj/item/organ/external/diona/leg),
@@ -217,7 +229,7 @@
body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not
flags = NO_BREATHE | NO_SCAN | IS_PLANT | NO_BLOOD | NO_PAIN | NO_SLIP | NO_MINOR_CUT
flags = NO_SCAN | IS_PLANT | NO_PAIN | NO_SLIP | NO_MINOR_CUT
spawn_flags = CAN_JOIN | IS_WHITELISTED
blood_color = "#004400"
@@ -254,82 +266,4 @@
else
qdel(D)
H.visible_message("<span class='danger'>[H] splits apart with a wet slithering noise!</span>")
/datum/species/machine
name = "Machine"
name_plural = "machines"
blurb = "Positronic intelligence really took off in the 26th century, and it is not uncommon to see independant, free-willed \
robots on many human stations, particularly in fringe systems where standards are slightly lax and public opinion less relevant \
to corporate operations. IPCs (Integrated Positronic Chassis) are a loose category of self-willed robots with a humanoid form, \
generally self-owned after being 'born' into servitude; they are reliable and dedicated workers, albeit more than slightly \
inhuman in outlook and perspective."
icobase = 'icons/mob/human_races/r_machine.dmi'
deform = 'icons/mob/human_races/r_machine.dmi'
language = "Encoded Audio Language"
unarmed_types = list(/datum/unarmed_attack/punch)
rarity_value = 2
num_alternate_languages = 1 // potentially could be 2?
name_language = "Encoded Audio Language"
eyes = "blank_eyes"
brute_mod = 1.875 // 100% * 1.875 * 0.8 (robolimbs) ~= 150%
burn_mod = 1.875 // So they take 50% extra damage from brute/burn overall.
show_ssd = "flashing a 'system offline' glyph on their monitor"
death_message = "gives one shrill beep before falling lifeless."
knockout_message = "encounters a hardware fault and suddenly reboots!"
warning_low_pressure = 50
hazard_low_pressure = 0
cold_level_1 = 50
cold_level_2 = -1
cold_level_3 = -1
heat_level_1 = 500 // Gives them about 25 seconds in space before taking damage
heat_level_2 = 1000
heat_level_3 = 2000
passive_temp_gain = 10 // This should cause IPCs to stabilize at ~80 C in a 20 C environment.
flags = NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_POISON
spawn_flags = CAN_JOIN | IS_WHITELISTED
blood_color = "#1F181F"
flesh_color = "#575757"
virus_immune = 1
reagent_tag = IS_MACHINE
has_organ = list(
"brain" = /obj/item/organ/mmi_holder/posibrain,
"cell" = /obj/item/organ/cell,
"optics" = /obj/item/organ/optical_sensor
)
vision_organ = "optics"
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest/ipc),
"groin" = list("path" = /obj/item/organ/external/groin/ipc),
"head" = list("path" = /obj/item/organ/external/head/ipc),
"l_arm" = list("path" = /obj/item/organ/external/arm/ipc),
"r_arm" = list("path" = /obj/item/organ/external/arm/right/ipc),
"l_leg" = list("path" = /obj/item/organ/external/leg/ipc),
"r_leg" = list("path" = /obj/item/organ/external/leg/right/ipc),
"l_hand" = list("path" = /obj/item/organ/external/hand/ipc),
"r_hand" = list("path" = /obj/item/organ/external/hand/right/ipc),
"l_foot" = list("path" = /obj/item/organ/external/foot/ipc),
"r_foot" = list("path" = /obj/item/organ/external/foot/right/ipc)
)
/datum/species/machine/handle_death(var/mob/living/carbon/human/H)
..()
H.h_style = ""
spawn(100)
if(H) H.update_hair()
/datum/species/machine/sanitize_name(var/name)
return sanitizeName(name, allow_numbers = 1)
H.visible_message("<span class='danger'>\The [H] splits apart with a wet slithering noise!</span>")

View File

@@ -13,8 +13,6 @@
siemens_coefficient = 0
gluttonous = 3
eyes = "blank_eyes"
brute_mod = 0.5 // Hardened carapace.
burn_mod = 2 // Weak to fire.
@@ -25,7 +23,7 @@
cold_level_2 = -1
cold_level_3 = -1
flags = NO_BREATHE | NO_SCAN | NO_PAIN | NO_SLIP | NO_POISON | NO_MINOR_CUT
flags = NO_SCAN | NO_PAIN | NO_SLIP | NO_POISON | NO_MINOR_CUT
spawn_flags = IS_RESTRICTED
reagent_tag = IS_XENOS
@@ -62,6 +60,20 @@
var/weeds_heal_rate = 1 // Health regen on weeds.
var/weeds_plasma_rate = 5 // Plasma regen on weeds.
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest),
"groin" = list("path" = /obj/item/organ/external/groin),
"head" = list("path" = /obj/item/organ/external/head/no_eyes),
"l_arm" = list("path" = /obj/item/organ/external/arm),
"r_arm" = list("path" = /obj/item/organ/external/arm/right),
"l_leg" = list("path" = /obj/item/organ/external/leg),
"r_leg" = list("path" = /obj/item/organ/external/leg/right),
"l_hand" = list("path" = /obj/item/organ/external/hand),
"r_hand" = list("path" = /obj/item/organ/external/hand/right),
"l_foot" = list("path" = /obj/item/organ/external/foot),
"r_foot" = list("path" = /obj/item/organ/external/foot/right)
)
/datum/species/xenos/get_bodytype()
return "Xenomorph"

View File

@@ -54,7 +54,7 @@ var/global/list/sparring_attack_cache = list()
if("l_arm", "l_hand")
if (target.l_hand)
// Disarm left hand
//Urist McAssistant dropped the macguffin with a scream just sounds odd. Plus it doesn't work with NO_PAIN
//Urist McAssistant dropped the macguffin with a scream just sounds odd.
target.visible_message("<span class='danger'>\The [target.l_hand] was knocked right out of [target]'s grasp!</span>")
target.drop_l_hand()
if("r_arm", "r_hand")
@@ -94,10 +94,13 @@ var/global/list/sparring_attack_cache = list()
/datum/unarmed_attack/proc/handle_eye_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target)
var/obj/item/organ/eyes/eyes = target.internal_organs_by_name["eyes"]
eyes.take_damage(rand(3,4), 1)
user.visible_message("<span class='danger'>[user] presses \his [eye_attack_text] into [target]'s [eyes.name]!</span>")
target << "<span class='danger'>You experience[(target.species.flags & NO_PAIN)? "" : " immense pain as you feel" ] [eye_attack_text_victim] being pressed into your [eyes.name][(target.species.flags & NO_PAIN)? "." : "!"]</span>"
if(eyes)
eyes.take_damage(rand(3,4), 1)
user.visible_message("<span class='danger'>[user] presses \his [eye_attack_text] into [target]'s [eyes.name]!</span>")
var/eye_pain = eyes.can_feel_pain()
target << "<span class='danger'>You experience[(eye_pain) ? "" : " immense pain as you feel" ] [eye_attack_text_victim] being pressed into your [eyes.name][(eye_pain)? "." : "!"]</span>"
return
user.visible_message("<span class='danger'>[user] attempts to press \his [eye_attack_text] into [target]'s eyes, but they don't have any!</span>")
/datum/unarmed_attack/bite
attack_verb = list("bit")

View File

@@ -209,11 +209,11 @@ var/global/list/damage_icon_parts = list()
O.update_icon()
if(O.damage_state == "00") continue
var/icon/DI
var/cache_index = "[O.damage_state]/[O.icon_name]/[species.blood_color]/[species.get_bodytype()]"
var/cache_index = "[O.damage_state]/[O.icon_name]/[O.species.get_blood_colour()]/[species.get_bodytype()]"
if(damage_icon_parts[cache_index] == null)
DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human
DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels
DI.Blend(species.blood_color, ICON_MULTIPLY)
DI.Blend(O.species.get_blood_colour(), ICON_MULTIPLY)
damage_icon_parts[cache_index] = DI
else
DI = damage_icon_parts[cache_index]

View File

@@ -63,7 +63,7 @@
H.custom_pain(painMes)
else if (istype(M, /mob/living/carbon))
var/mob/living/carbon/C = M
if (!(C.species && (C.species.flags & NO_PAIN)))
if (C.can_feel_pain())
M << "<span class='danger'>[painMes]</span>"
gain_nutrition(rand(20,25))

View File

@@ -3,7 +3,7 @@
// proc to find out in how much pain the mob is at the moment
/mob/living/carbon/proc/updateshock()
if (species && (species.flags & NO_PAIN))
if (!can_feel_pain())
src.traumatic_shock = 0
return 0

View File

@@ -813,3 +813,51 @@ default behaviour is:
ear_damage = damage
if(deaf >= 0)
ear_deaf = deaf
/mob/living/proc/vomit(var/skip_wait, var/blood_vomit)
if(isSynthetic())
src << "<span class='danger'>A sudden, dizzying wave of internal feedback rushes over you!</span>"
src.Weaken(5)
return
if(!check_has_mouth())
return
if(!lastpuke)
if (nutrition <= 100)
src << "<span class='danger'>You gag as you want to throw up, but there's nothing in your stomach!</span>"
src.Weaken(10)
src.adjustToxLoss(3)
return
lastpuke = 1
src << "<span class='warning'>You feel nauseous...</span>"
if(!skip_wait)
sleep(150) //15 seconds until second warning
src << "<span class='warning'>You feel like you are about to throw up!</span>"
sleep(100) //and you have 10 more for mad dash to the bucket
Stun(5)
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)
var/turf/simulated/T = get_turf(src)
if(istype(T))
if(blood_vomit)
T.add_blood_floor(src)
else
T.add_vomit_floor(src, 1)
if(blood_vomit)
if(getBruteLoss() < 50)
adjustBruteLoss(3)
else
nutrition -= 40
adjustToxLoss(-3)
sleep(350)
lastpuke = 0

View File

@@ -43,3 +43,4 @@
var/fire_stacks
var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks.
var/lastpuke = 0

View File

@@ -30,7 +30,7 @@ var/list/mob_hat_cache = list()
universal_understand = 1
gender = NEUTER
pass_flags = PASSTABLE
braintype = "Robot"
braintype = "Drone"
lawupdate = 0
density = 1
req_access = list(access_engine, access_robotics)

View File

@@ -247,7 +247,7 @@
if((crisis && security_level == SEC_LEVEL_RED) || crisis_override) //Leaving this in until it's balanced appropriately.
src << "\red Crisis mode active. Combat module available."
modules+="Combat"
modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules
modtype = input("Please, select a module!", "Robot module", null, null) as null|anything in modules
if(module)
return
@@ -267,9 +267,9 @@
modtype = prefix
if(istype(mmi, /obj/item/device/mmi/digital/posibrain))
braintype = "Android"
else if(istype(mmi, /obj/item/device/mmi/digital/robot))
braintype = "Robot"
else if(istype(mmi, /obj/item/device/mmi/digital/robot))
braintype = "Drone"
else
braintype = "Cyborg"
@@ -911,7 +911,7 @@
if(!(icontype in module_sprites))
icontype = module_sprites[1]
else
icontype = input("Select an icon! [triesleft ? "You have [triesleft] more chance\s." : "This is your last try."]", "Robot", icontype, null) in module_sprites
icontype = input("Select an icon! [triesleft ? "You have [triesleft] more chance\s." : "This is your last try."]", "Robot Icon", icontype, null) in module_sprites
icon_state = module_sprites[icontype]
updateicon()

View File

@@ -77,7 +77,7 @@
if(!E || (E.status & ORGAN_DESTROYED))
src << "\The [H] does not have a head!"
if(!H.species.has_organ["brain"])
if(!H.should_have_organ("brain"))
src << "\The [H] does not seem to have an ear canal to breach."
return

View File

@@ -87,7 +87,6 @@
var/canmove = 1
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas.
var/lastpuke = 0
var/unacidable = 0
var/list/pinned = list() // List of things pinning this creature to walls (see living_defense.dm)
var/list/embedded = list() // Embedded items, since simple mobs don't have organs.

View File

@@ -99,7 +99,7 @@
if(!armor && target.headcheck("head") && prob(damage))
target.apply_effect(20, PARALYZE)
target.visible_message("<span class='danger'>[target] [target.species.knockout_message]</span>")
target.visible_message("<span class='danger'>[target] [target.species.get_knockout_message(target)]</span>")
playsound(attacker.loc, "swing_hit", 25, 1, -1)
attacker.attack_log += text("\[[time_stamp()]\] <font color='red'>Headbutted [target.name] ([target.ckey])</font>")

View File

@@ -3,8 +3,18 @@ datum/preferences
proc/randomize_appearance_for(var/mob/living/carbon/human/H)
gender = pick(MALE, FEMALE)
s_tone = random_skin_tone()
h_style = random_hair_style(gender, species)
f_style = random_facial_hair_style(gender, species)
var/use_head_species
var/obj/item/organ/external/head/temp_head = H.get_organ("head")
if(temp_head)
use_head_species = temp_head.species.get_bodytype()
else
use_head_species = H.species.get_bodytype()
if(use_head_species)
h_style = random_hair_style(gender, species)
f_style = random_facial_hair_style(gender, species)
randomize_hair_color("hair")
randomize_hair_color("facial")
randomize_eyes_color()
@@ -191,37 +201,58 @@ datum/preferences
else
icobase = 'icons/mob/human_races/r_human.dmi'
preview_icon = new /icon(icobase, "torso_[g]")
preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY)
preview_icon.Blend(new /icon(icobase, "head_[g]"), ICON_OVERLAY)
for(var/name in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand"))
if(organ_data[name] == "amputated") continue
preview_icon = new /icon(icobase, "")
for(var/name in list("torso", "groin", "head", "r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand"))
if(organ_data[name] == "amputated")
continue
if(organ_data[name] == "cyborg")
var/datum/robolimb/R
if(rlimb_data[name]) R = all_robolimbs[rlimb_data[name]]
if(!R) R = basic_robolimb
preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic.
if(name in list("torso", "groin", "head"))
preview_icon.Blend(icon(R.icon, "[name]_[g]"), ICON_OVERLAY)
else
preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY)
continue
preview_icon.Blend(new /icon(icobase, "[name]"), ICON_OVERLAY)
var/icon/limb_icon
if(name in list("torso", "groin", "head"))
limb_icon = new /icon(icobase, "[name]_[g]")
else
limb_icon = new /icon(icobase, "[name]")
// Skin color
if(current_species && (current_species.appearance_flags & HAS_SKIN_COLOR))
limb_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
// Skin tone
if(current_species && (current_species.appearance_flags & HAS_SKIN_TONE))
if (s_tone >= 0)
limb_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD)
else
limb_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT)
preview_icon.Blend(limb_icon, ICON_OVERLAY)
//Tail
if(current_species && (current_species.tail))
var/icon/temp = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[current_species.tail]_s")
if(current_species && (current_species.appearance_flags & HAS_SKIN_COLOR))
temp.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
if(current_species && (current_species.appearance_flags & HAS_SKIN_TONE))
if (s_tone >= 0)
temp.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD)
else
temp.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT)
preview_icon.Blend(temp, ICON_OVERLAY)
// Skin color
if(current_species && (current_species.appearance_flags & HAS_SKIN_COLOR))
preview_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
// This is absolute garbage but whatever. It will do until this entire file can be rewritten without crashes.
var/use_eye_icon = "eyes_s"
var/list/use_eye_data = current_species.has_limbs["head"]
if(islist(use_eye_data))
var/use_eye_path = use_eye_data["path"]
var/obj/item/organ/external/head/temp_head = new use_eye_path ()
if(istype(temp_head))
use_eye_icon = temp_head.eye_icon
qdel(temp_head)
// Skin tone
if(current_species && (current_species.appearance_flags & HAS_SKIN_TONE))
if (s_tone >= 0)
preview_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD)
else
preview_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT)
var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = current_species ? current_species.eyes : "eyes_s")
var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = use_eye_icon)
if ((current_species && (current_species.appearance_flags & HAS_EYE_COLOR)))
eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD)

View File

@@ -145,9 +145,9 @@
O.loc = loc
O.job = "Cyborg"
if(O.mind.assigned_role == "Cyborg")
if(O.mind.role_alt_title == "Android")
if(O.mind.role_alt_title == "Robot")
O.mmi = new /obj/item/device/mmi/digital/posibrain(O)
else if(O.mind.role_alt_title == "Robot")
else if(O.mind.role_alt_title == "Drone")
O.mmi = new /obj/item/device/mmi/digital/robot(O)
else
O.mmi = new /obj/item/device/mmi(O)

View File

@@ -19,7 +19,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
vessel = new/datum/reagents(600)
vessel.my_atom = src
if(species && species.flags & NO_BLOOD) //We want the var for safety but we can do without the actual blood.
if(!should_have_organ("heart")) //We want the var for safety but we can do without the actual blood.
return
vessel.add_reagent("blood",560)
@@ -30,7 +30,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
/mob/living/carbon/human/proc/fixblood()
for(var/datum/reagent/blood/B in vessel.reagent_list)
if(B.id == "blood")
B.data = list( "donor"=src,"viruses"=null,"species"=species.name,"blood_DNA"=dna.unique_enzymes,"blood_colour"= species.blood_color,"blood_type"=dna.b_type, \
B.data = list( "donor"=src,"viruses"=null,"species"=species.name,"blood_DNA"=dna.unique_enzymes,"blood_colour"= species.get_blood_colour(src),"blood_type"=dna.b_type, \
"resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = list())
B.color = B.data["blood_colour"]
@@ -39,7 +39,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
if(in_stasis)
return
if(species && species.flags & NO_BLOOD)
if(!should_have_organ("heart"))
return
if(stat != DEAD && bodytemperature >= 170) //Dead or cryosleep people do not pump the blood.
@@ -62,7 +62,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
// Damaged heart virtually reduces the blood volume, as the blood isn't
// being pumped properly anymore.
if(species && species.has_organ["heart"])
if(species && should_have_organ("heart"))
var/obj/item/organ/heart/heart = internal_organs_by_name["heart"]
if(!heart)
@@ -126,7 +126,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
//Bleeding out
var/blood_max = 0
for(var/obj/item/organ/external/temp in organs)
if(!(temp.status & ORGAN_BLEEDING) || temp.status & ORGAN_ROBOT)
if(!(temp.status & ORGAN_BLEEDING) || (temp.status & ORGAN_ROBOT))
continue
for(var/datum/wound/W in temp.wounds) if(W.bleeding())
blood_max += W.damage / 40
@@ -137,7 +137,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
//Makes a blood drop, leaking amt units of blood from the mob
/mob/living/carbon/human/proc/drip(var/amt as num)
if(species && species.flags & NO_BLOOD) //TODO: Make drips come from the reagents instead.
if(!should_have_organ("heart")) //TODO: Make drips come from the reagents instead.
return
if(!amt)
@@ -175,7 +175,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
// Putting this here due to return shenanigans.
if(istype(src,/mob/living/carbon/human))
var/mob/living/carbon/human/H = src
B.data["blood_colour"] = H.species.blood_color
B.data["blood_colour"] = H.species.get_blood_colour(H)
B.color = B.data["blood_colour"]
var/list/temp_chem = list()
@@ -188,7 +188,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
//For humans, blood does not appear from blue, it comes from vessels.
/mob/living/carbon/human/take_blood(obj/item/weapon/reagent_containers/container, var/amount)
if(species && species.flags & NO_BLOOD)
if(!should_have_organ("heart"))
return null
if(vessel.get_reagent_amount("blood") < amount)
@@ -216,7 +216,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
//Transfers blood from reagents to vessel, respecting blood types compatability.
/mob/living/carbon/human/inject_blood(var/datum/reagent/blood/injected, var/amount)
if(species.flags & NO_BLOOD)
if(should_have_organ("heart"))
reagents.add_reagent("blood", amount, injected.data)
reagents.update_total()
return

View File

@@ -46,7 +46,8 @@
/obj/item/organ/stack
name = "cortical stack"
parent_organ = "head"
robotic = 2
icon_state = "brain-prosthetic"
organ_tag = "stack"
vital = 1
var/backup_time = 0
var/datum/mind/backup
@@ -56,15 +57,5 @@
backup_time = world.time
if(owner.mind) backup = owner.mind
/obj/item/organ/stack/vox
/obj/item/organ/stack/vox/stack
/obj/item/organ/stack
name = "cortical stack"
icon_state = "brain-prosthetic"
organ_tag = "stack"
robotic = 2
/obj/item/organ/stack/vox
name = "vox cortical stack"

View File

@@ -3,33 +3,37 @@ var/list/organ_cache = list()
/obj/item/organ
name = "organ"
icon = 'icons/obj/surgery.dmi'
germ_level = 0
// Strings.
var/organ_tag = "organ"
var/parent_organ = "chest"
// Appearance.
var/dead_icon
var/mob/living/carbon/human/owner = null
// Status tracking.
var/status = 0
var/vital //Lose a vital limb, die immediately.
var/damage = 0 // amount of damage to the organ
var/min_bruised_damage = 10
var/min_broken_damage = 30
var/max_damage
var/organ_tag = "organ"
var/parent_organ = "chest"
var/robotic = 0 //For being a robot
var/rejecting // Is this organ already being rejected?
// Reference data.
var/mob/living/carbon/human/owner = null
var/list/transplant_data
var/list/datum/autopsy_data/autopsy_data = list()
var/list/trace_chemicals = list() // traces of chemicals in the organ,
// links chemical IDs to number of ticks for which they'll stay in the blood
germ_level = 0
var/datum/dna/dna
var/datum/species/species
// Damage vars.
var/min_bruised_damage = 10
var/min_broken_damage = 30
var/max_damage
var/rejecting // Is this organ already being rejected?
/obj/item/organ/Destroy()
if(!owner)
return ..()
if(istype(owner, /mob/living/carbon))
if((owner.internal_organs) && (src in owner.internal_organs))
owner.internal_organs -= src
@@ -42,7 +46,7 @@ var/list/organ_cache = list()
owner.organs_by_name -= src
if(src in owner.contents)
owner.contents -= src
owner = null
return ..()
/obj/item/organ/proc/update_health()
@@ -189,8 +193,25 @@ var/list/organ_cache = list()
/obj/item/organ/proc/receive_chem(chemical as obj)
return 0
/obj/item/organ/proc/rejuvenate()
/obj/item/organ/proc/rejuvenate(var/ignore_prosthetic_prefs)
damage = 0
status = 0
if(!ignore_prosthetic_prefs && owner && owner.client && owner.client.prefs && owner.client.prefs.real_name == owner.real_name)
var/status = owner.client.prefs.organ_data[organ_tag]
if(status == "assisted")
mechassist()
else if(status == "mechanical")
robotize()
/obj/item/organ/proc/remove_rejuv()
if(owner)
owner.internal_organs -= src
owner.internal_organs_by_name[organ_tag] = null
while(null in owner.internal_organs)
owner.internal_organs -= null
while(null in owner.internal_organs_by_name)
owner.internal_organs_by_name -= null
qdel(src)
/obj/item/organ/proc/is_damaged()
return damage > 0
@@ -241,19 +262,13 @@ var/list/organ_cache = list()
owner.custom_pain("Something inside your [parent.name] hurts a lot.", 1)
/obj/item/organ/proc/robotize() //Being used to make robutt hearts, etc
robotic = 2
src.status &= ~ORGAN_BROKEN
src.status &= ~ORGAN_BLEEDING
src.status &= ~ORGAN_SPLINTED
src.status &= ~ORGAN_CUT_AWAY
src.status &= ~ORGAN_DESTROYED
src.status |= ORGAN_ROBOT
src.status |= ORGAN_ASSISTED
status = 0
status |= ORGAN_ASSISTED
status |= ORGAN_ROBOT
/obj/item/organ/proc/mechassist() //Used to add things like pacemakers, etc
robotize()
src.status &= ~ORGAN_ROBOT
robotic = 1
status = 0
status |= ORGAN_ASSISTED
min_bruised_damage = 15
min_broken_damage = 35
@@ -320,8 +335,6 @@ var/list/organ_cache = list()
target.internal_organs |= src
affected.internal_organs |= src
target.internal_organs_by_name[organ_tag] = src
if(robotic)
status |= ORGAN_ROBOT
/obj/item/organ/eyes/replaced(var/mob/living/carbon/human/target)
@@ -335,10 +348,10 @@ var/list/organ_cache = list()
/obj/item/organ/proc/bitten(mob/user)
if(robotic)
if(status & ORGAN_ROBOT)
return
user << "\blue You take an experimental bite out of \the [src]."
user << "<span class='notice'>You take an experimental bite out of \the [src].</span>"
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list
blood_splatter(src,B,1)
@@ -361,6 +374,9 @@ var/list/organ_cache = list()
/obj/item/organ/attack_self(mob/user as mob)
// Convert it to an edible form, yum yum.
if(!robotic && user.a_intent == "help" && user.zone_sel.selecting == "mouth")
if((status & ORGAN_ROBOT) && user.a_intent == "help" && user.zone_sel.selecting == "mouth")
bitten(user)
return
/obj/item/organ/proc/can_feel_pain()
return !(status & (ORGAN_ROBOT|ORGAN_DESTROYED)) && !(species.flags & NO_PAIN)

View File

@@ -14,49 +14,57 @@
dir = SOUTH
organ_tag = "limb"
var/brute_mod = 1
var/burn_mod = 1
// Strings
var/limb_name
// Damage vars.
var/brute_mod = 1 // Multiplier for incoming brute damage.
var/burn_mod = 1 // As above for burn.
var/damage_state = "00" // Modifier used for generating the on-mob damage overlay for this limb.
var/brute_dam = 0 // Actual current brute damage.
var/burn_dam = 0 // Actual current burn damage.
var/last_dam = -1
// Appearance vars.
var/icon_name = null
var/body_part = null
var/icon_position = 0
var/model
var/force_icon
var/damage_state = "00"
var/brute_dam = 0
var/burn_dam = 0
var/max_size = 0
var/last_dam = -1
var/icon/mob_icon
var/gendered_icon = 0
var/limb_name
var/disfigured = 0
var/cannot_amputate
var/cannot_break
var/s_tone
var/list/s_col
var/list/h_col
var/body_hair
// Wound and structural data.
var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often
var/list/wounds = list()
var/number_wounds = 0 // cache the number of wounds, which is NOT wounds.len!
var/perma_injury = 0
var/obj/item/organ/external/parent
var/list/obj/item/organ/external/children
var/list/internal_organs = list() // Internal organs of this body part
var/damage_msg = "\red You feel an intense pain"
var/broken_description
var/open = 0
var/stage = 0
var/cavity = 0
var/sabotaged = 0 // If a prosthetic limb is emagged, it will detonate when it fails.
var/encased // Needs to be opened with a saw to access the organs.
var/list/implants = list()
var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often
// Joint/state stuff.
var/can_grasp //It would be more appropriate if these two were named "affects_grasp" and "affects_stand" at this point
var/can_stand
var/disfigured = 0
var/cannot_amputate
var/cannot_break
var/joint = "joint" // Descriptive string used in dislocation.
var/amputation_point // Descriptive string used in amputation.
var/dislocated = 0 // If you target a joint, you can dislocate the limb, causing temporary damage to the organ.
var/can_grasp //It would be more appropriate if these two were named "affects_grasp" and "affects_stand" at this point
var/can_stand
var/body_hair
var/encased // Needs to be opened with a saw to access the organs.
// Surgery vars.
var/open = 0
var/stage = 0
var/cavity = 0
/obj/item/organ/external/Destroy()
if(parent && parent.children)
@@ -188,12 +196,6 @@
parent.children = list()
parent.children.Add(src)
/obj/item/organ/external/robotize()
..()
//robit limbs take reduced damage
brute_mod = 0.8
burn_mod = 0.8
/****************************************************
DAMAGE PROCS
****************************************************/
@@ -219,7 +221,7 @@
brute -= brute / 2
if(status & ORGAN_BROKEN && prob(40) && brute)
if (!(owner.species && (owner.species.flags & NO_PAIN)))
if(!((species.flags & NO_PAIN) || (status & ORGAN_ROBOT)))
owner.emote("scream") //getting hit on broken hand hurts
if(used_weapon)
add_autopsy_data("[used_weapon]", brute + burn)
@@ -316,7 +318,6 @@
if(internal)
status &= ~ORGAN_BROKEN
perma_injury = 0
/*if((brute || burn) && children && children.len && (owner.species.flags & REGENERATES_LIMBS))
var/obj/item/organ/external/stump/S = locate() in children
@@ -333,13 +334,10 @@
/*
This function completely restores a damaged organ to perfect condition.
*/
/obj/item/organ/external/rejuvenate()
/obj/item/organ/external/rejuvenate(var/ignore_prosthetic_prefs)
damage_state = "00"
if(status & 128) //Robotic organs stay robotic. Fix because right click rejuvinate makes IPC's organs organic.
status = 128
else
status = 0
perma_injury = 0
status = 0
brute_dam = 0
burn_dam = 0
germ_level = 0
@@ -348,16 +346,44 @@ This function completely restores a damaged organ to perfect condition.
// handle internal organs
for(var/obj/item/organ/current_organ in internal_organs)
current_organ.rejuvenate()
current_organ.rejuvenate(ignore_prosthetic_prefs)
// remove embedded objects and drop them on the floor
for(var/obj/implanted_object in implants)
if(!istype(implanted_object,/obj/item/weapon/implant)) // We don't want to remove REAL implants. Just shrapnel etc.
implanted_object.loc = owner.loc
implanted_object.loc = get_turf(src)
implants -= implanted_object
owner.updatehealth()
if(owner && !ignore_prosthetic_prefs)
if(owner.client && owner.client.prefs && owner.client.prefs.real_name == owner.real_name)
var/status = owner.client.prefs.organ_data[limb_name]
if(status == "amputated")
remove_rejuv()
else if(status == "cyborg")
var/robodata = owner.client.prefs.rlimb_data[limb_name]
if(robodata)
robotize(robodata)
else
robotize()
owner.updatehealth()
/obj/item/organ/external/remove_rejuv()
if(owner)
owner.organs -= src
owner.organs_by_name[limb_name] = null
while(null in owner.organs)
owner.organs -= null
while(null in owner.organs_by_name)
owner.organs_by_name -= null
if(children && children.len)
for(var/obj/item/organ/external/E in children)
E.remove_rejuv()
children.Cut()
for(var/obj/item/organ/O in contents)
O.remove_rejuv()
qdel(src)
/obj/item/organ/external/proc/createwound(var/type = CUT, var/damage)
if(damage == 0) return
@@ -384,13 +410,13 @@ This function completely restores a damaged organ to perfect condition.
W.open_wound(damage)
if(prob(25))
if(status & ORGAN_ROBOT)
owner.visible_message("\red The damage to [owner.name]'s [name] worsens.",\
"\red The damage to your [name] worsens.",\
"You hear the screech of abused metal.")
owner.visible_message("<span class='danger'>The damage to [owner.name]'s [name] worsens.</span>",\
"<span class='danger'>The damage to your [name] worsens.</span>",\
"<span class='danger'>You hear the screech of abused metal.</span>")
else
owner.visible_message("\red The wound on [owner.name]'s [name] widens with a nasty ripping noise.",\
"\red The wound on your [name] widens with a nasty ripping noise.",\
"You hear a nasty ripping noise, as if flesh is being torn apart.")
owner.visible_message("<span class='danger'>The wound on [owner.name]'s [name] widens with a nasty ripping noise.</span>",\
"<span class='danger'>The wound on your [name] widens with a nasty ripping noise.</span>",\
"<span class='danger'>You hear a nasty ripping noise, as if flesh is being torn apart.</span>")
return
//Creating wound
@@ -451,9 +477,6 @@ This function completely restores a damaged organ to perfect condition.
if(trace_chemicals[chemID] <= 0)
trace_chemicals.Remove(chemID)
if(!(status & ORGAN_BROKEN))
perma_injury = 0
//Infections
update_germs()
else
@@ -629,7 +652,7 @@ Note that amputating the affected organ does in fact remove the infection from t
else if(W.damage_type == BURN)
burn_dam += W.damage
if(!(status & ORGAN_ROBOT) && W.bleeding() && (H && !(H.species.flags & NO_BLOOD)))
if(!(status & ORGAN_ROBOT) && W.bleeding() && (H && H.should_have_organ("heart")))
W.bleed_timer--
status |= ORGAN_BLEEDING
@@ -638,7 +661,7 @@ Note that amputating the affected organ does in fact remove the infection from t
number_wounds += W.amount
//things tend to bleed if they are CUT OPEN
if (open && !clamped && (H && !(H.species.flags & NO_BLOOD)))
if (open && !clamped && (H && H.should_have_organ("heart")))
status |= ORGAN_BLEEDING
//Bone fractures
@@ -687,7 +710,7 @@ Note that amputating the affected organ does in fact remove the infection from t
****************************************************/
//Handles dismemberment
/obj/item/organ/external/proc/droplimb(var/clean, var/disintegrate, var/ignore_children)
/obj/item/organ/external/proc/droplimb(var/clean, var/disintegrate, var/ignore_children, var/silent)
if(cannot_amputate || !owner)
return
@@ -762,12 +785,18 @@ Note that amputating the affected organ does in fact remove the infection from t
I.loc = get_turf(src)
qdel(src)
if(DROPLIMB_BLUNT)
var/obj/effect/decal/cleanable/blood/gibs/gore = new victim.species.single_gib_type(get_turf(victim))
if(victim.species.flesh_color)
gore.fleshcolor = victim.species.flesh_color
if(victim.species.blood_color)
gore.basecolor = victim.species.blood_color
gore.update_icon()
var/obj/effect/decal/cleanable/blood/gibs/gore
if(status & ORGAN_ROBOT)
gore = new /obj/effect/decal/cleanable/blood/gibs/robot(get_turf(victim))
else
gore = new victim.species.single_gib_type(get_turf(victim))
if(species)
if(species.get_flesh_colour())
gore.fleshcolor = species.get_flesh_colour()
if(species.get_blood_colour())
gore.basecolor = species.get_blood_colour()
gore.update_icon()
gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
for(var/obj/item/organ/I in internal_organs)
@@ -849,15 +878,14 @@ Note that amputating the affected organ does in fact remove the infection from t
if(owner)
owner.visible_message(\
"\red You hear a loud cracking sound coming from \the [owner].",\
"\red <b>Something feels like it shattered in your [name]!</b>",\
"You hear a sickening crack.")
if(owner.species && !(owner.species.flags & NO_PAIN))
"<span class='danger'>You hear a loud cracking sound coming from \the [owner].</span>",\
"<span class='danger'>Something feels like it shattered in your [name]!</span>",\
"<span class='danger'>You hear a sickening crack.</span>")
if(!(species.flags & NO_PAIN))
owner.emote("scream")
status |= ORGAN_BROKEN
broken_description = pick("broken","fracture","hairline fracture")
perma_injury = brute_dam
// Fractures have a chance of getting you out of restraints
if (prob(25))
@@ -891,26 +919,55 @@ Note that amputating the affected organ does in fact remove the infection from t
status &= ~ORGAN_BROKEN
return 1
/obj/item/organ/external/robotize(var/company)
/obj/item/organ/external/robotize(var/company, var/ski)
if(status & ORGAN_ROBOT)
return
..()
brute_mod = 0.8
burn_mod = 0.8
brute_mod = 0.8
burn_mod = 0.8
if(company)
model = company
var/datum/robolimb/R = all_robolimbs[company]
if(species && (species.name in R.species_cannot_use))
if(!R || (species && (species.name in R.species_cannot_use)))
R = basic_robolimb
if(R)
force_icon = R.icon
name = "[R.company] [initial(name)]"
desc = "[R.desc]"
name = "robotic [initial(name)]"
desc = "[R.desc] It looks like it was produced by [R.company]."
dislocated = -1 //TODO, make robotic limbs a separate type, remove snowflake
dislocated = -1
cannot_break = 1
get_icon()
unmutate()
for (var/obj/item/organ/external/T in children)
if(T)
T.robotize()
for(var/obj/item/organ/external/T in children)
T.robotize(company, 1)
if(owner)
if(!skip_prosthetics)
owner.full_prosthetic = null // Will be rechecked next isSynthetic() call.
for(var/obj/item/organ/thing in src.contents)
if(istype(thing))
if(thing.vital)
continue
owner.internal_organs_by_name[thing.organ_tag] = null
owner.internal_organs.Remove(thing)
qdel(thing)
while(null in owner.internal_organs)
owner.internal_organs -= null
while(null in owner.internal_organs_by_name)
owner.internal_organs -= null
return 1
/obj/item/organ/external/proc/mutate()
if(src.status & ORGAN_ROBOT)
@@ -923,7 +980,7 @@ Note that amputating the affected organ does in fact remove the infection from t
if(owner) owner.update_body()
/obj/item/organ/external/proc/get_damage() //returns total damage
return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use max_damage?
return (brute_dam+burn_dam) //could use max_damage?
/obj/item/organ/external/proc/has_infected_wound()
for(var/datum/wound/W in wounds)
@@ -1012,13 +1069,13 @@ Note that amputating the affected organ does in fact remove the infection from t
return
if(owner)
if(type == "brute")
owner.visible_message("\red You hear a sickening cracking sound coming from \the [owner]'s [name].", \
"\red <b>Your [name] becomes a mangled mess!</b>", \
"\red You hear a sickening crack.")
owner.visible_message("<span class='danger'>You hear a sickening cracking sound coming from \the [owner]'s [name].</span>", \
"<span class='danger'>Your [name] becomes a mangled mess!</span>", \
"<span class='danger'>You hear a sickening crack.</span>")
else
owner.visible_message("\red \The [owner]'s [name] melts away, turning into mangled mess!", \
"\red <b>Your [name] melts away!</b>", \
"\red You hear a sickening sizzle.")
owner.visible_message("<span class='danger'>\The [owner]'s [name] melts away, turning into mangled mess!</span>", \
"<span class='danger'>Your [name] melts away!</span>", \
"<span class='danger'>You hear a sickening sizzle.</span>")
disfigured = 1
/obj/item/organ/external/proc/get_wounds_desc()
@@ -1098,6 +1155,12 @@ Note that amputating the affected organ does in fact remove the infection from t
parent_organ = null
encased = "ribcage"
/obj/item/organ/external/chest/robotize()
if(..())
// Give them a new cell.
owner.internal_organs_by_name["cell"] = new /obj/item/organ/cell(owner,1)
/obj/item/organ/external/groin
name = "lower body"
limb_name = "groin"
@@ -1224,6 +1287,8 @@ Note that amputating the affected organ does in fact remove the infection from t
gendered_icon = 1
encased = "skull"
var/eye_icon = "eyes_s"
/obj/item/organ/external/head/removed()
if(owner)
name = "[owner.real_name]'s head"
@@ -1244,3 +1309,32 @@ Note that amputating the affected organ does in fact remove the infection from t
disfigure("brute")
if (burn_dam > 40)
disfigure("burn")
/obj/item/organ/external/head/skrell
eye_icon = "skrell_eyes_s"
/obj/item/organ/external/head/resomi
eye_icon = "eyes_resomi"
/obj/item/organ/external/head/vox
eye_icon = "vox_eyes_s"
/obj/item/organ/external/head/no_eyes
eye_icon = "blank_eyes"
/obj/item/organ/external/head/no_eyes/diona
max_damage = 50
min_broken_damage = 25
cannot_break = 1
amputation_point = "branch"
joint = "structural ligament"
dislocated = -1
vital = 0
/obj/item/organ/external/head/no_eyes/diona/removed()
var/mob/living/carbon/human/H = owner
..()
if(!istype(H) || !H.organs || !H.organs.len)
H.death()
if(prob(50) && spawn_diona_nymph(get_turf(src)))
qdel(src)

View File

@@ -53,10 +53,10 @@ var/global/list/limb_icon_cache = list()
overlays.Cut()
if(!owner || !owner.species)
return
if(owner.species.has_organ["eyes"])
if(owner.should_have_organ("eyes"))
var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"]
if(species.eyes)
var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes)
if(eye_icon)
var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', eye_icon)
if(eyes)
eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD)
else
@@ -91,7 +91,7 @@ var/global/list/limb_icon_cache = list()
var/gender
if(force_icon)
mob_icon = new /icon(force_icon, "[icon_name]")
mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_f" : ""]")
else
if(!dna)
mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_f" : ""]")

View File

@@ -70,6 +70,13 @@
parent_organ = "head"
var/list/eye_colour = list(0,0,0)
/obj/item/organ/eyes/robotize()
..()
name = "optical sensor"
icon = 'icons/obj/robot_component.dmi'
icon_state = "camera"
dead_icon = "camera_broken"
/obj/item/organ/eyes/proc/update_colour()
if(!owner)
return
@@ -109,7 +116,7 @@
if (germ_level > INFECTION_LEVEL_ONE)
if(prob(1))
owner << "\red Your skin itches."
owner << "<span class='danger'>Your skin itches.</span>"
if (germ_level > INFECTION_LEVEL_TWO)
if(prob(1))
spawn owner.vomit()

View File

@@ -8,9 +8,9 @@ mob/var/next_pain_time = 0
// partname is the name of a body part
// amount is a num from 1 to 100
mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0)
if(stat >= 1)
if(stat >= 1)
return
if(species && (species.flags & NO_PAIN))
if(!can_feel_pain())
return
if(analgesic > 40)
return
@@ -25,13 +25,13 @@ mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0
if(burning)
switch(amount)
if(1 to 10)
msg = "\red <b>Your [partname] burns.</b>"
msg = "<span class='danger'>Your [partname] burns.</span>"
if(11 to 90)
flash_weak_pain()
msg = "\red <b><font size=2>Your [partname] burns badly!</font></b>"
msg = "<span class='danger'><font size=2>Your [partname] burns badly!</font></span>"
if(91 to 10000)
flash_pain()
msg = "\red <b><font size=3>OH GOD! Your [partname] is on fire!</font></b>"
msg = "<span class='danger'><font size=3>OH GOD! Your [partname] is on fire!</font></span>"
else
switch(amount)
if(1 to 10)
@@ -51,9 +51,9 @@ mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0
// message is the custom message to be displayed
// flash_strength is 0 for weak pain flash, 1 for strong pain flash
mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength)
if(stat >= 1)
if(stat >= 1)
return
if(species.flags & NO_PAIN)
if(!can_feel_pain())
return
if(reagents.has_reagent("tramadol"))
return
@@ -61,9 +61,9 @@ mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength)
return
if(analgesic)
return
var/msg = "\red <b>[message]</b>"
var/msg = "<span class='danger'>[message]</span>"
if(flash_strength >= 1)
msg = "\red <font size=3><b>[message]</b></font>"
msg = "<span class='danger'><font size=3>[message]</font></span>"
// Anti message spam checks
if(msg && ((msg != last_pain_message) || (world.time >= next_pain_time)))
@@ -74,7 +74,7 @@ mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength)
mob/living/carbon/human/proc/handle_pain()
// not when sleeping
if(species.flags & NO_PAIN) return
if(!can_feel_pain()) return
if(stat >= 2) return
if(analgesic > 70)

View File

@@ -41,4 +41,3 @@ var/global/datum/robolimb/basic_robolimb
company = "Morpheus Cyberkinetics"
desc = "This limb is simple and functional; no effort has been made to make it look human."
icon = 'icons/mob/human_races/cyberlimbs/ipc.dmi'
unavailable_at_chargen = 1

View File

@@ -122,22 +122,6 @@
body_part = HAND_RIGHT
parent_organ = "r_arm"
/obj/item/organ/external/diona/head
limb_name = "head"
icon_name = "head"
name = "head"
max_damage = 50
min_broken_damage = 25
w_class = 3
body_part = HEAD
parent_organ = "chest"
/obj/item/organ/external/diona/head/removed()
if(owner)
owner.u_equip(owner.head)
owner.u_equip(owner.l_ear)
..()
//DIONA ORGANS.
/obj/item/organ/external/diona/removed()
var/mob/living/carbon/human/H = owner

View File

@@ -1,77 +1,3 @@
// IPC limbs.
/obj/item/organ/external/head/ipc
dislocated = -1
can_intake_reagents = 0
vital = 0
max_damage = 50 //made same as arm, since it is not vital
min_broken_damage = 30
encased = null
/obj/item/organ/external/head/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/chest/ipc
dislocated = -1
encased = null
/obj/item/organ/external/chest/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/groin/ipc
dislocated = -1
/obj/item/organ/external/groin/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/arm/ipc
dislocated = -1
/obj/item/organ/external/arm/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/arm/right/ipc
dislocated = -1
/obj/item/organ/external/arm/right/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/leg/ipc
dislocated = -1
/obj/item/organ/external/leg/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/leg/right/ipc
dislocated = -1
/obj/item/organ/external/leg/right/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/foot/ipc
dislocated = -1
/obj/item/organ/external/foot/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/foot/right/ipc
dislocated = -1
/obj/item/organ/external/foot/right/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/hand/ipc
dislocated = -1
/obj/item/organ/external/hand/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/external/hand/right/ipc
dislocated = -1
/obj/item/organ/external/hand/right/ipc/New()
robotize("Morpheus Cyberkinetics")
..()
/obj/item/organ/cell
name = "microbattery"
desc = "A small, powerful cell for use in fully prosthetic bodies."
@@ -92,34 +18,59 @@
owner.stat = 0
owner.visible_message("<span class='danger'>\The [owner] twitches visibly!</span>")
/obj/item/organ/optical_sensor
name = "optical sensor"
organ_tag = "eyes"
parent_organ = "head"
icon = 'icons/obj/robot_component.dmi'
icon_state = "camera"
dead_icon = "camera_broken"
/obj/item/organ/optical_sensor/New()
robotize()
..()
// Used for an MMI or posibrain being installed into a human.
/obj/item/organ/mmi_holder
name = "brain"
organ_tag = "brain"
parent_organ = "chest"
parent_organ = "head"
vital = 1
var/obj/item/device/mmi/stored_mmi
/obj/item/organ/mmi_holder/Destroy()
stored_mmi = null
return ..()
/obj/item/organ/mmi_holder/New()
..()
if(!stored_mmi)
stored_mmi = new(src)
spawn(1)
if(!owner)
if(stored_mmi)
stored_mmi.loc = get_turf(src)
qdel(src)
return
update_from_mmi()
if(stored_mmi.brainmob && owner && owner.stat == DEAD)
owner.stat = 0
owner.visible_message("<span class='danger'>\The [owner] twitches visibly!</span>")
/obj/item/organ/mmi_holder/proc/update_from_mmi()
if(!stored_mmi)
return
if(!stored_mmi.brainmob)
stored_mmi.brainmob = new(src)
stored_mmi.brainmob.real_name = owner.name
stored_mmi.brainmob.name = stored_mmi.brainmob.real_name
if(owner)
stored_mmi.name = "[initial(stored_mmi.name)] ([owner.name])"
name = stored_mmi.name
desc = stored_mmi.desc
icon = stored_mmi.icon
icon_state = stored_mmi.icon_state
/obj/item/organ/mmi_holder/removed()
update_from_mmi()
return ..()
/obj/item/organ/mmi_holder/removed(var/mob/living/user)
if(stored_mmi)
@@ -133,25 +84,9 @@
holder_mob.drop_from_inventory(src)
qdel(src)
/obj/item/organ/mmi_holder/New()
..()
// This is very ghetto way of rebooting an IPC. TODO better way.
spawn(1)
if(owner && owner.stat == DEAD)
owner.stat = 0
owner.visible_message("<span class='danger'>\The [owner] twitches visibly!</span>")
/obj/item/organ/mmi_holder/posibrain
name = "positronic brain"
/obj/item/organ/mmi_holder/posibrain/New()
robotize()
stored_mmi = new /obj/item/device/mmi/digital/posibrain(src)
..()
spawn(1)
if(owner)
stored_mmi.name = "positronic brain ([owner.name])"
stored_mmi.brainmob.real_name = owner.name
stored_mmi.brainmob.name = stored_mmi.brainmob.real_name
stored_mmi.icon_state = "posibrain-occupied"
update_from_mmi()
else
stored_mmi.loc = get_turf(src)
qdel(src)

View File

@@ -119,6 +119,7 @@ By design, d1 is the smallest direction and d2 is the highest
// - Cable coil : merge cables
// - Multitool : get the power currently passing through the cable
//
/obj/structure/cable/attackby(obj/item/W, mob/user)
var/turf/T = src.loc
@@ -512,14 +513,18 @@ obj/structure/cable/proc/cableColor(var/colorC)
///////////////////////////////////
//you can use wires to heal robotics
/obj/item/stack/cable_coil/attack(var/atom/A, var/mob/living/user, var/def_zone)
if(ishuman(A) && user.a_intent == I_HELP)
return
return ..()
/obj/item/stack/cable_coil/afterattack(var/mob/M, var/mob/user)
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/S = H.organs_by_name[user.zone_sel.selecting]
if (!S) return
if(!(S.status & ORGAN_ROBOT) || user.a_intent != I_HELP)
if(!S || !(S.status & ORGAN_ROBOT) || user.a_intent != I_HELP)
return ..()
if(S.burn_dam)
@@ -528,10 +533,9 @@ obj/structure/cable/proc/cableColor(var/colorC)
user.visible_message("<span class='danger'>\The [user] repairs some burn damage on \the [M]'s [S.name] with \the [src].</span>")
else if(S.open != 2)
user << "<span class='danger'>The damage is far too severe to patch over externally.</span>"
return 1
else if(S.open != 2)
user << "<span class='notice'>Nothing to fix!</span>"
return
else
return ..()

View File

@@ -67,9 +67,13 @@
if(M.gender == MALE)
H.gender = MALE
H.name = pick(first_names_male)
else
else if(M.gender == FEMALE)
H.gender = FEMALE
H.name = pick(first_names_female)
else
H.gender = NEUTER
H.name = pick(first_names_female|first_names_male)
H.name += " [pick(last_names)]"
H.real_name = H.name

View File

@@ -70,8 +70,10 @@
infect_virus2(M, V.getcopy())
/datum/reagent/blood/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_MACHINE)
return
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.check_is_prosthetic())
return
if(data && data["viruses"])
for(var/datum/disease/D in data["viruses"])
if(D.spread_type == SPECIAL || D.spread_type == NON_CONTAGIOUS)

View File

@@ -328,7 +328,7 @@
if(affecting.take_damage(0, removed * power * 0.1))
H.UpdateDamageIcon()
if(prob(100 * removed / meltdose)) // Applies disfigurement
if (!(H.species && (H.species.flags & NO_PAIN)))
if (affecting.can_feel_pain())
H.emote("scream")
H.status_flags |= DISFIGURED
else

View File

@@ -233,12 +233,13 @@
M.adjustToxLoss(0.5 * removed)
/datum/reagent/capsaicin/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA || alien == IS_MACHINE)
if(alien == IS_DIONA)
return
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.species && (H.species.flags & (NO_PAIN)))
if(!H.can_feel_pain())
return
if(dose < 5 && (dose == metabolism || prob(5)))
M << "<span class='danger'>Your insides feel uncomfortably hot!</span>"
if(dose >= 5)
@@ -268,7 +269,7 @@
var/obj/item/safe_thing = null
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(H.species && (H.species.flags & NO_PAIN))
if(!H.can_feel_pain())
return
if(H.head)
if(H.head.body_parts_covered & EYES)
@@ -314,7 +315,7 @@
/datum/reagent/condensedcapsaicin/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.species && (H.species.flags & (NO_PAIN)))
if(!H.can_feel_pain())
return
if(dose == metabolism)
M << "<span class='danger'>You feel like your insides are burning!</span>"

View File

@@ -274,7 +274,7 @@
var/mob/living/carbon/human/H = M
for(var/obj/item/organ/I in H.internal_organs)
if((I.damage > 0) && (I.robotic != 2)) //Peridaxon heals only non-robotic organs
if((I.damage > 0) && !(I.status & ORGAN_ROBOT)) //Peridaxon heals only non-robotic organs
I.damage = max(I.damage - removed, 0)
/datum/reagent/ryetalyn

View File

@@ -234,9 +234,14 @@
affect_blood(M, alien, removed)
/datum/reagent/mutagen/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(M.isSynthetic())
return
var/mob/living/carbon/human/H = M
if(istype(H) && (H.species.flags & NO_SCAN))
return
if(M.dna)
if(prob(removed * 0.1)) // Approx. one mutation per 10 injected/20 ingested/30 touching units
randmuti(M)

View File

@@ -96,7 +96,7 @@
var/datum/reagent/B
if(istype(T, /mob/living/carbon/human))
var/mob/living/carbon/human/H = T
if(H.species && H.species.flags & NO_BLOOD)
if(H.species && !H.should_have_organ("heart"))
H.reagents.trans_to_obj(src, amount)
else
B = T.take_blood(src, amount)

View File

@@ -142,7 +142,6 @@
affected.status &= ~ORGAN_BROKEN
affected.status &= ~ORGAN_SPLINTED
affected.stage = 0
affected.perma_injury = 0
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)

View File

@@ -51,9 +51,6 @@
//Could be cleaner ...
affected.open = 1
if(istype(target) && !(target.species.flags & NO_BLOOD))
affected.status |= ORGAN_BLEEDING
affected.createwound(CUT, 1)
affected.clamp()
spread_germs_to_organ(affected, user)
@@ -91,7 +88,7 @@
"\blue You have constructed a prepared incision on and within [target]'s [affected.name] with \the [tool].",)
affected.open = 1
if(istype(target) && !(target.species.flags & NO_BLOOD))
if(istype(target) && target.should_have_organ("heart"))
affected.status |= ORGAN_BLEEDING
affected.createwound(CUT, 1)
@@ -133,7 +130,7 @@
"\blue You have made an incision on [target]'s [affected.name] with \the [tool].",)
affected.open = 1
if(istype(target) && !(target.species.flags & NO_BLOOD))
if(istype(target) && target.should_have_organ("heart"))
affected.status |= ORGAN_BLEEDING
affected.createwound(CUT, 1)

View File

@@ -91,7 +91,7 @@
for(var/obj/item/organ/I in affected.internal_organs)
if(I && I.damage > 0)
if(I.robotic < 2)
if(!(I.status & ORGAN_ROBOT))
user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \
"You start treating damage to [target]'s [I.name] with [tool_name]." )
@@ -111,7 +111,7 @@
for(var/obj/item/organ/I in affected.internal_organs)
if(I && I.damage > 0)
if(I.robotic < 2)
if(!(I.status & ORGAN_ROBOT))
user.visible_message("<span class='notice'>[user] treats damage to [target]'s [I.name] with [tool_name].</span>", \
"<span class='notice'>You treat damage to [target]'s [I.name] with [tool_name].</span>" )
I.damage = 0
@@ -285,7 +285,7 @@
if(O.organ_tag == "limb")
return 0
else if(target.species.has_organ[O.organ_tag])
else if(target.should_have_organ(O.organ_tag))
if(O.damage > (O.max_damage * 0.75))
user << "<span class='warning'>\The [O.organ_tag] [o_is] in no state to be transplanted.</span>"

View File

@@ -212,7 +212,7 @@
if(!affected) return
var/is_organ_damaged = 0
for(var/obj/item/organ/I in affected.internal_organs)
if(I.damage > 0 && I.robotic >= 2)
if(I.damage > 0 && (I.status & ORGAN_ROBOT))
is_organ_damaged = 1
break
return affected.open == 2 && is_organ_damaged
@@ -225,7 +225,7 @@
for(var/obj/item/organ/I in affected.internal_organs)
if(I && I.damage > 0)
if(I.robotic >= 2)
if(I.status & ORGAN_ROBOT)
user.visible_message("[user] starts mending the damage to [target]'s [I.name]'s mechanisms.", \
"You start mending the damage to [target]'s [I.name]'s mechanisms." )
@@ -241,7 +241,7 @@
for(var/obj/item/organ/I in affected.internal_organs)
if(I && I.damage > 0)
if(I.robotic >= 2)
if(I.status & ORGAN_ROBOT)
user.visible_message("<span class='notice'>[user] repairs [target]'s [I.name] with [tool].</span>", \
"<span class='notice'>You repair [target]'s [I.name] with [tool].</span>" )
I.damage = 0
@@ -393,7 +393,7 @@
user << "<span class='danger'>You have no idea what species this person is. Report this on the bug tracker.</span>"
return SURGERY_FAILURE
if(!target.species.has_organ["brain"])
if(!target.should_have_organ("brain"))
user << "<span class='danger'>You're pretty sure [target.species.name_plural] don't normally have a brain.</span>"
return SURGERY_FAILURE

View File

@@ -87,7 +87,7 @@
var/f = 1
for(var/k in all_species)
var/datum/species/S = all_species[k]
if(S.virus_immune)
if(S.get_virus_immune())
continue
if(!f) H += " | "
else f = 0

View File

@@ -45,7 +45,7 @@
var/list/res = list()
for (var/specie in all_species)
var/datum/species/S = all_species[specie]
if(!S.virus_immune)
if(!S.get_virus_immune())
meat += S
if(meat.len)
var/num = rand(1,meat.len)
@@ -71,7 +71,7 @@
// Some species are flat out immune to organic viruses.
var/mob/living/carbon/human/H = mob
if(istype(H) && H.species.virus_immune)
if(istype(H) && H.species.get_virus_immune(H))
cure(mob)
return

View File

@@ -4,7 +4,7 @@ proc/infection_check(var/mob/living/carbon/M, var/vector = "Airborne")
return 0
var/mob/living/carbon/human/H = M
if(istype(H) && H.species.virus_immune)
if(istype(H) && H.species.get_virus_immune(H))
return 0
var/protection = M.getarmor(null, "bio") //gets the full body bio armour value, weighted by body part coverage.

View File

@@ -16,7 +16,7 @@
var/mob/living/carbon/C = M
if (istype(C,/mob/living/carbon/human/))
var/mob/living/carbon/human/H = C
if(H.species.flags & NO_BLOOD)
if(!H.should_have_organ("heart"))
report("Scan aborted: The target does not have blood.", user)
return