Merge pull request #1 from PolarisSS13/master

Update
This commit is contained in:
SinTwo
2015-11-08 18:51:43 -05:00
235 changed files with 8451 additions and 9025 deletions
+4 -3
View File
@@ -1293,7 +1293,7 @@ proc/admin_notice(var/message, var/rights)
var/datum/antagonist/antag = all_antag_types[antag_type]
message_admins("[key_name(usr)] attempting to force latespawn with template [antag.id].")
antag.attempt_auto_spawn()
antag.attempt_late_spawn()
/datum/admins/proc/force_mode_latespawn()
set category = "Admin"
@@ -1310,5 +1310,6 @@ proc/admin_notice(var/message, var/rights)
usr << "Mode has not started."
return
message_admins("[key_name(usr)] attempting to force mode autospawn.")
ticker.mode.process_autoantag()
message_admins("[key_name(usr)] attempting to force mode latespawn.")
ticker.mode.next_spawn = 0
ticker.mode.try_latespawn()
+1 -4
View File
@@ -1,9 +1,6 @@
/mob/var/lastattacker = null
/mob/var/lastattacked = null
/mob/var/attack_log = list()
proc/log_and_message_admins_with_location(var/message, var/x, var/y, var/z, var/mob/user = usr)
log_and_message_admins("[message] (<a HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)", user)
/mob/var/attack_log = list( )
proc/log_and_message_admins(var/message as text, var/mob/user = usr)
log_admin(user ? "[key_name(user)] [message]" : "EVENT [message]")
+10
View File
@@ -1119,6 +1119,16 @@
log_admin("[key_name(usr)] AIized [key_name(H)]")
H.AIize()
else if(href_list["makealien"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makealien"])
if(!istype(H))
usr << "This can only be used on instances of type /mob/living/carbon/human"
return
usr.client.cmd_admin_alienize(H)
else if(href_list["makeslime"])
if(!check_rights(R_SPAWN)) return
+17 -1
View File
@@ -16,7 +16,6 @@
// callproc moved to code/modules/admin/callproc
/client/proc/Cell()
set category = "Debug"
set name = "Cell"
@@ -101,6 +100,23 @@
paiController.pai_candidates.Remove(candidate)
feedback_add_details("admin_verb","MPAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_alienize(var/mob/M in mob_list)
set category = "Fun"
set name = "Make Alien"
if(!ticker)
alert("Wait until the game starts")
return
if(ishuman(M))
log_admin("[key_name(src)] has alienized [M.key].")
spawn(10)
M:Alienize()
feedback_add_details("admin_verb","MKAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] made [key_name(M)] into an alien.")
message_admins("\blue [key_name_admin(usr)] made [key_name(M)] into an alien.", 1)
else
alert("Invalid mob")
/client/proc/cmd_admin_slimeize(var/mob/M in mob_list)
set category = "Fun"
set name = "Make slime"
-1
View File
@@ -162,7 +162,6 @@ var/list/debug_verbs = list (
,/client/proc/testZAScolors_remove
,/client/proc/setup_supermatter_engine
,/client/proc/atmos_toggle_debug
,/client/proc/spawn_tanktransferbomb
)
@@ -278,6 +278,20 @@
return
holder.Topic(href, list("makerobot"=href_list["makerobot"]))
else if(href_list["makealien"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makealien"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makealien"=href_list["makealien"]))
else if(href_list["makeslime"])
if(!check_rights(R_SPAWN)) return
@@ -1,38 +0,0 @@
var/global/list/uplink_locations = list("PDA", "Headset", "None")
/datum/category_item/player_setup_item/antagonism/basic
name = "Basic"
sort_order = 1
/datum/category_item/player_setup_item/antagonism/basic/load_character(var/savefile/S)
S["uplinklocation"] >> pref.uplinklocation
S["exploit_record"] >> pref.exploit_record
/datum/category_item/player_setup_item/antagonism/basic/save_character(var/savefile/S)
S["uplinklocation"] << pref.uplinklocation
S["exploit_record"] << pref.exploit_record
/datum/category_item/player_setup_item/antagonism/basic/sanitize_character()
pref.uplinklocation = sanitize_inlist(pref.uplinklocation, uplink_locations, initial(pref.uplinklocation))
/datum/category_item/player_setup_item/antagonism/basic/content(var/mob/user)
. +="<b>Uplink Type : <a href='?src=\ref[src];antagtask=1'>[pref.uplinklocation]</a></b>"
. +="<br>"
. +="<b>Exploitable information:</b><br>"
if(jobban_isbanned(user, "Records"))
. += "<b>You are banned from using character records.</b><br>"
else
. +="<a href='?src=\ref[src];exploitable_record=1'>[TextPreview(pref.exploit_record,40)]</a><br>"
/datum/category_item/player_setup_item/antagonism/basic/OnTopic(var/href,var/list/href_list, var/mob/user)
if (href_list["antagtask"])
pref.uplinklocation = next_in_list(pref.uplinklocation, uplink_locations)
return TOPIC_REFRESH
if(href_list["exploitable_record"])
var/exploitmsg = sanitize(input(user,"Set exploitable information about you here.","Exploitable Information", html_decode(pref.exploit_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
if(!isnull(exploitmsg) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
pref.exploit_record = exploitmsg
return TOPIC_REFRESH
return ..()
@@ -1,54 +0,0 @@
var/global/list/special_roles = list( //keep synced with the defines BE_* in setup.dm --rastaf
//some autodetection here.
// TODO: Update to new antagonist system.
"traitor" = IS_MODE_COMPILED("traitor"), // 0
"operative" = IS_MODE_COMPILED("nuclear"), // 1
"changeling" = IS_MODE_COMPILED("changeling"), // 2
"wizard" = IS_MODE_COMPILED("wizard"), // 3
"malf AI" = IS_MODE_COMPILED("malfunction"), // 4
"revolutionary" = IS_MODE_COMPILED("revolution"), // 5
"alien candidate" = 1, //always show // 6
"positronic brain" = 1, // 7
"cultist" = IS_MODE_COMPILED("cult"), // 8
"infested monkey" = IS_MODE_COMPILED("monkey"), // 9
"ninja" = "true", // 10
"raider" = IS_MODE_COMPILED("heist"), // 11
"diona" = 1, // 12
"loyalist" = IS_MODE_COMPILED("revolution"), // 13
"pAI candidate" = 1, // -- TLE // 14
)
/datum/category_item/player_setup_item/antagonism/candidacy
name = "Candidacy"
sort_order = 2
/datum/category_item/player_setup_item/antagonism/candidacy/load_character(var/savefile/S)
S["be_special"] >> pref.be_special
/datum/category_item/player_setup_item/antagonism/candidacy/save_character(var/savefile/S)
S["be_special"] << pref.be_special
/datum/category_item/player_setup_item/antagonism/candidacy/sanitize_character()
pref.be_special = sanitize_integer(pref.be_special, 0, 65535, initial(pref.be_special))
/datum/category_item/player_setup_item/antagonism/candidacy/content(var/mob/user)
if(jobban_isbanned(user, "Syndicate"))
. += "<b>You are banned from antagonist roles.</b>"
pref.be_special = 0
else
var/n = 0
for (var/i in special_roles)
if(special_roles[i]) //if mode is available on the server
if(jobban_isbanned(user, i) || (i == "positronic brain" && jobban_isbanned(user, "AI") && jobban_isbanned(user, "Cyborg")) || (i == "pAI candidate" && jobban_isbanned(user, "pAI")))
. += "<b>Be [i]:</b> <font color=red><b> \[BANNED]</b></font><br>"
else
. += "<b>Be [i]:</b> <a href='?src=\ref[src];be_special=[n]'><b>[pref.be_special&(1<<n) ? "Yes" : "No"]</b></a><br>"
n++
/datum/category_item/player_setup_item/antagonism/candidacy/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["be_special"])
var/num = text2num(href_list["be_special"])
pref.be_special ^= (1<<num)
return TOPIC_REFRESH
return ..()
@@ -1,90 +0,0 @@
/datum/category_item/player_setup_item/general/basic
name = "Basic"
sort_order = 1
/datum/category_item/player_setup_item/general/basic/load_character(var/savefile/S)
S["real_name"] >> pref.real_name
S["name_is_always_random"] >> pref.be_random_name
S["gender"] >> pref.gender
S["age"] >> pref.age
S["spawnpoint"] >> pref.spawnpoint
S["OOC_Notes"] >> pref.metadata
/datum/category_item/player_setup_item/general/basic/save_character(var/savefile/S)
S["real_name"] << pref.real_name
S["name_is_always_random"] << pref.be_random_name
S["gender"] << pref.gender
S["age"] << pref.age
S["spawnpoint"] << pref.spawnpoint
S["OOC_Notes"] << pref.metadata
/datum/category_item/player_setup_item/general/basic/sanitize_character()
pref.real_name = sanitizeName(pref.real_name)
if(!pref.real_name)
pref.real_name = random_name(pref.gender, pref.species)
pref.spawnpoint = sanitize_inlist(pref.spawnpoint, spawntypes, initial(pref.spawnpoint))
pref.be_random_name = sanitize_integer(pref.be_random_name, 0, 1, initial(pref.be_random_name))
pref.age = sanitize_integer(pref.age, AGE_MIN, AGE_MAX, initial(pref.age))
/datum/category_item/player_setup_item/general/basic/content()
. = "<b>Name:</b> "
. += "<a href='?src=\ref[src];rename=1'><b>[pref.real_name]</b></a><br>"
. += "(<a href='?src=\ref[src];random_name=1'>Random Name</A>) "
. += "(<a href='?src=\ref[src];always_random_name=1'>Always Random Name: [pref.be_random_name ? "Yes" : "No"]</a>)"
. += "<br>"
. += "<b>Gender:</b> <a href='?src=\ref[src];gender=1'><b>[pref.gender == MALE ? "Male" : "Female"]</b></a><br>"
. += "<b>Age:</b> <a href='?src=\ref[src];age=1'>[pref.age]</a><br>"
. += "<b>Spawn Point</b>: <a href='?src=\ref[src];spawnpoint=1'>[pref.spawnpoint]</a><br>"
if(config.allow_Metadata)
. += "<b>OOC Notes:</b> <a href='?src=\ref[src];metadata=1'> Edit </a><br>"
/datum/category_item/player_setup_item/general/basic/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["rename"])
var/raw_name = input(user, "Choose your character's name:", "Character Name") as text|null
if (!isnull(raw_name) && CanUseTopic(user))
var/new_name = sanitizeName(raw_name)
if(new_name)
pref.real_name = new_name
return TOPIC_REFRESH
else
user << "<span class='warning'>Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and .</span>"
return TOPIC_NOACTION
else if(href_list["random_name"])
pref.real_name = random_name(pref.gender, pref.species)
return TOPIC_REFRESH
else if(href_list["always_random_name"])
pref.be_random_name = !pref.be_random_name
return TOPIC_REFRESH
else if(href_list["gender"])
if(pref.gender == MALE)
pref.gender = FEMALE
else
pref.gender = MALE
return TOPIC_REFRESH
else if(href_list["age"])
var/new_age = input(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX])", "Character Preference", pref.age) as num|null
if(new_age && CanUseTopic(user))
pref.age = max(min(round(text2num(new_age)), AGE_MAX), AGE_MIN)
return TOPIC_REFRESH
else if(href_list["spawnpoint"])
var/list/spawnkeys = list()
for(var/S in spawntypes)
spawnkeys += S
var/choice = input(user, "Where would you like to spawn when late-joining?") as null|anything in spawnkeys
if(!choice || !spawntypes[choice] || !CanUseTopic(user)) return TOPIC_NOACTION
pref.spawnpoint = choice
return TOPIC_REFRESH
else if(href_list["metadata"])
var/new_metadata = sanitize(input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , pref.metadata)) as message|null
if(new_metadata && CanUseTopic(user))
pref.metadata = sanitize(new_metadata)
return TOPIC_REFRESH
return ..()
@@ -1,93 +0,0 @@
/datum/category_item/player_setup_item/general/language
name = "Language"
sort_order = 2
/datum/category_item/player_setup_item/general/language/load_character(var/savefile/S)
S["language"] >> pref.alternate_languages
S["language_prefixes"] >> pref.language_prefixes
/datum/category_item/player_setup_item/general/language/save_character(var/savefile/S)
S["language"] << pref.alternate_languages
S["language_prefixes"] << pref.language_prefixes
/datum/category_item/player_setup_item/general/language/sanitize_character()
if(!islist(pref.alternate_languages)) pref.alternate_languages = list()
if(isnull(pref.language_prefixes) || !pref.language_prefixes.len)
pref.language_prefixes = config.language_prefixes.Copy()
/datum/category_item/player_setup_item/general/language/content()
. += "<b>Languages</b><br>"
var/datum/species/S = all_species[pref.species]
if(S.language)
. += "- [S.language]<br>"
if(S.default_language && S.default_language != S.language)
. += "- [S.default_language]<br>"
if(S.num_alternate_languages)
if(pref.alternate_languages.len)
for(var/i = 1 to pref.alternate_languages.len)
var/lang = pref.alternate_languages[i]
. += "- [lang] - <a href='?src=\ref[src];remove_language=[i]'>remove</a><br>"
if(pref.alternate_languages.len < S.num_alternate_languages)
. += "- <a href='?src=\ref[src];add_language=1'>add</a> ([S.num_alternate_languages - pref.alternate_languages.len] remaining)<br>"
else
. += "- [pref.species] cannot choose secondary languages.<br>"
. += "<b>Language Keys</b><br>"
. += " [english_list(pref.language_prefixes, and_text = " ", comma_text = " ")] <a href='?src=\ref[src];change_prefix=1'>Change</a> <a href='?src=\ref[src];reset_prefix=1'>Reset</a><br>"
/datum/category_item/player_setup_item/general/language/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["remove_language"])
var/index = text2num(href_list["remove_language"])
pref.alternate_languages.Cut(index, index+1)
return TOPIC_REFRESH
else if(href_list["add_language"])
var/datum/species/S = all_species[pref.species]
if(pref.alternate_languages.len >= S.num_alternate_languages)
alert(user, "You have already selected the maximum number of alternate languages for this species!")
else
var/list/available_languages = S.secondary_langs.Copy()
for(var/L in all_languages)
var/datum/language/lang = all_languages[L]
if(!(lang.flags & RESTRICTED) && (!config.usealienwhitelist || is_alien_whitelisted(user, L) || !(lang.flags & WHITELISTED)))
available_languages |= L
// make sure we don't let them waste slots on the default languages
available_languages -= S.language
available_languages -= S.default_language
available_languages -= pref.alternate_languages
if(!available_languages.len)
alert(user, "There are no additional languages available to select.")
else
var/new_lang = input(user, "Select an additional language", "Character Generation", null) as null|anything in available_languages
if(new_lang)
pref.alternate_languages |= new_lang
return TOPIC_REFRESH
else if(href_list["change_prefix"])
var/char
var/keys[0]
do
char = input("Enter a single special character.\nYou may re-select the same characters.\nThe following characters are already in use by radio: ; : .\nThe following characters are already in use by special say commands: ! * ^", "Enter Character - [3 - keys.len] remaining") as null|text
if(char)
if(length(char) > 1)
alert(user, "Only single characters allowed.", "Error", "Ok")
else if(char in list(";", ":", "."))
alert(user, "Radio character. Rejected.", "Error", "Ok")
else if(char in list("!","*", "^"))
alert(user, "Say character. Rejected.", "Error", "Ok")
else if(contains_az09(char))
alert(user, "Non-special character. Rejected.", "Error", "Ok")
else
keys.Add(char)
while(char && keys.len < 3)
if(keys.len == 3)
pref.language_prefixes = keys
return TOPIC_REFRESH
else if(href_list["reset_prefix"])
pref.language_prefixes = config.language_prefixes.Copy()
return TOPIC_REFRESH
return ..()
@@ -1,498 +0,0 @@
var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-")
/datum/category_item/player_setup_item/general/body
name = "Body"
sort_order = 3
/datum/category_item/player_setup_item/general/body/load_character(var/savefile/S)
S["species"] >> pref.species
S["hair_red"] >> pref.r_hair
S["hair_green"] >> pref.g_hair
S["hair_blue"] >> pref.b_hair
S["facial_red"] >> pref.r_facial
S["facial_green"] >> pref.g_facial
S["facial_blue"] >> pref.b_facial
S["skin_tone"] >> pref.s_tone
S["skin_red"] >> pref.r_skin
S["skin_green"] >> pref.g_skin
S["skin_blue"] >> pref.b_skin
S["hair_style_name"] >> pref.h_style
S["facial_style_name"] >> pref.f_style
S["eyes_red"] >> pref.r_eyes
S["eyes_green"] >> pref.g_eyes
S["eyes_blue"] >> pref.b_eyes
S["b_type"] >> pref.b_type
S["disabilities"] >> pref.disabilities
S["organ_data"] >> pref.organ_data
S["rlimb_data"] >> pref.rlimb_data
/datum/category_item/player_setup_item/general/body/save_character(var/savefile/S)
S["species"] << pref.species
S["hair_red"] << pref.r_hair
S["hair_green"] << pref.g_hair
S["hair_blue"] << pref.b_hair
S["facial_red"] << pref.r_facial
S["facial_green"] << pref.g_facial
S["facial_blue"] << pref.b_facial
S["skin_tone"] << pref.s_tone
S["skin_red"] << pref.r_skin
S["skin_green"] << pref.g_skin
S["skin_blue"] << pref.b_skin
S["hair_style_name"] << pref.h_style
S["facial_style_name"] << pref.f_style
S["eyes_red"] << pref.r_eyes
S["eyes_green"] << pref.g_eyes
S["eyes_blue"] << pref.b_eyes
S["b_type"] << pref.b_type
S["disabilities"] << pref.disabilities
S["organ_data"] << pref.organ_data
S["rlimb_data"] << pref.rlimb_data
/datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S)
if(!pref.species || !(pref.species in playable_species))
pref.species = "Human"
pref.r_hair = sanitize_integer(pref.r_hair, 0, 255, initial(pref.r_hair))
pref.g_hair = sanitize_integer(pref.g_hair, 0, 255, initial(pref.g_hair))
pref.b_hair = sanitize_integer(pref.b_hair, 0, 255, initial(pref.b_hair))
pref.r_facial = sanitize_integer(pref.r_facial, 0, 255, initial(pref.r_facial))
pref.g_facial = sanitize_integer(pref.g_facial, 0, 255, initial(pref.g_facial))
pref.b_facial = sanitize_integer(pref.b_facial, 0, 255, initial(pref.b_facial))
pref.s_tone = sanitize_integer(pref.s_tone, -185, 34, initial(pref.s_tone))
pref.r_skin = sanitize_integer(pref.r_skin, 0, 255, initial(pref.r_skin))
pref.g_skin = sanitize_integer(pref.g_skin, 0, 255, initial(pref.g_skin))
pref.b_skin = sanitize_integer(pref.b_skin, 0, 255, initial(pref.b_skin))
pref.h_style = sanitize_inlist(pref.h_style, hair_styles_list, initial(pref.h_style))
pref.f_style = sanitize_inlist(pref.f_style, facial_hair_styles_list, initial(pref.f_style))
pref.r_eyes = sanitize_integer(pref.r_eyes, 0, 255, initial(pref.r_eyes))
pref.g_eyes = sanitize_integer(pref.g_eyes, 0, 255, initial(pref.g_eyes))
pref.b_eyes = sanitize_integer(pref.b_eyes, 0, 255, initial(pref.b_eyes))
pref.b_type = sanitize_text(pref.b_type, initial(pref.b_type))
pref.disabilities = sanitize_integer(pref.disabilities, 0, 65535, initial(pref.disabilities))
if(!pref.organ_data) pref.organ_data = list()
if(!pref.rlimb_data) pref.rlimb_data = list()
/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")
var/mob_species = all_species[pref.species]
. += "<table><tr style='vertical-align:top'><td><b>Body</b> "
. += "(<a href='?src=\ref[src];random=1'>&reg;</A>)"
. += "<br>"
. += "Species: <a href='?src=\ref[src];show_species=1'>[pref.species]</a><br>"
. += "Blood Type: <a href='?src=\ref[src];blood_type=1'>[pref.b_type]</a><br>"
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>"
. += "Internal Organs: <a href='?src=\ref[src];organs=1'>Adjust</a><br>"
//display limbs below
var/ind = 0
for(var/name in pref.organ_data)
var/status = pref.organ_data[name]
var/organ_name = null
switch(name)
if("l_arm")
organ_name = "left arm"
if("r_arm")
organ_name = "right arm"
if("l_leg")
organ_name = "left leg"
if("r_leg")
organ_name = "right leg"
if("l_foot")
organ_name = "left foot"
if("r_foot")
organ_name = "right foot"
if("l_hand")
organ_name = "left hand"
if("r_hand")
organ_name = "right hand"
if("heart")
organ_name = "heart"
if("eyes")
organ_name = "eyes"
if(status == "cyborg")
++ind
if(ind > 1)
. += ", "
var/datum/robolimb/R
if(pref.rlimb_data[name] && all_robolimbs[pref.rlimb_data[name]])
R = all_robolimbs[pref.rlimb_data[name]]
else
R = basic_robolimb
. += "\t[R.company] [organ_name] prothesis"
else if(status == "amputated")
++ind
if(ind > 1)
. += ", "
. += "\tAmputated [organ_name]"
else if(status == "mechanical")
++ind
if(ind > 1)
. += ", "
. += "\tMechanical [organ_name]"
else if(status == "assisted")
++ind
if(ind > 1)
. += ", "
switch(organ_name)
if("heart")
. += "\tPacemaker-assisted [organ_name]"
if("voicebox") //on adding voiceboxes for speaking skrell/similar replacements
. += "\tSurgically altered [organ_name]"
if("eyes")
. += "\tRetinal overlayed [organ_name]"
else
. += "\tMechanically assisted [organ_name]"
if(!ind)
. += "\[...\]<br><br>"
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></tr></table>"
. += "<b>Hair</b><br>"
if(has_flag(mob_species, HAS_HAIR_COLOR))
. += "<a href='?src=\ref[src];hair_color=1'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(pref.r_hair, 2)][num2hex(pref.g_hair, 2)][num2hex(pref.b_hair, 2)]'><table style='display:inline;' bgcolor='#[num2hex(pref.r_hair, 2)][num2hex(pref.g_hair, 2)][num2hex(pref.b_hair)]'><tr><td>__</td></tr></table></font> "
. += " Style: <a href='?src=\ref[src];hair_style=1'>[pref.h_style]</a><br>"
. += "<br><b>Facial</b><br>"
if(has_flag(mob_species, HAS_HAIR_COLOR))
. += "<a href='?src=\ref[src];facial_color=1'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(pref.r_facial, 2)][num2hex(pref.g_facial, 2)][num2hex(pref.b_facial, 2)]'><table style='display:inline;' bgcolor='#[num2hex(pref.r_facial, 2)][num2hex(pref.g_facial, 2)][num2hex(pref.b_facial)]'><tr><td>__</td></tr></table></font> "
. += " Style: <a href='?src=\ref[src];facial_style=1'>[pref.f_style]</a><br>"
if(has_flag(mob_species, HAS_EYE_COLOR))
. += "<br><b>Eyes</b><br>"
. += "<a href='?src=\ref[src];eye_color=1'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(pref.r_eyes, 2)][num2hex(pref.g_eyes, 2)][num2hex(pref.b_eyes, 2)]'><table style='display:inline;' bgcolor='#[num2hex(pref.r_eyes, 2)][num2hex(pref.g_eyes, 2)][num2hex(pref.b_eyes)]'><tr><td>__</td></tr></table></font><br>"
if(has_flag(mob_species, HAS_SKIN_COLOR))
. += "<br><b>Body Color</b><br>"
. += "<a href='?src=\ref[src];skin_color=1'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(pref.r_skin, 2)][num2hex(pref.g_skin, 2)][num2hex(pref.b_skin, 2)]'><table style='display:inline;' bgcolor='#[num2hex(pref.r_skin, 2)][num2hex(pref.g_skin, 2)][num2hex(pref.b_skin)]'><tr><td>__</td></tr></table></font><br>"
/datum/category_item/player_setup_item/general/body/proc/has_flag(var/datum/species/mob_species, var/flag)
return mob_species && (mob_species.appearance_flags & flag)
/datum/category_item/player_setup_item/general/body/OnTopic(var/href,var/list/href_list, var/mob/user)
var/mob_species = all_species[pref.species]
if(href_list["random"])
pref.randomize_appearance_for()
return TOPIC_REFRESH
else if(href_list["blood_type"])
var/new_b_type = input(user, "Choose your character's blood-type:", "Character Preference") as null|anything in valid_bloodtypes
if(new_b_type && CanUseTopic(user))
pref.b_type = new_b_type
return TOPIC_REFRESH
else if(href_list["show_species"])
// Actual whitelist checks are handled elsewhere, this is just for accessing the preview window.
var/choice = input("Which species would you like to look at?") as null|anything in playable_species
if(!choice) return
pref.species_preview = choice
SetSpecies(preference_mob())
pref.alternate_languages.Cut() // Reset their alternate languages. Todo: attempt to just fix it instead?
return TOPIC_HANDLED
else if(href_list["set_species"])
user << browse(null, "window=species")
if(!pref.species_preview || !(pref.species_preview in all_species))
return TOPIC_NOACTION
var/prev_species = pref.species
pref.species = href_list["set_species"]
if(prev_species != pref.species)
//grab one of the valid hair styles for the newly chosen species
var/list/valid_hairstyles = list()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
if(pref.gender == MALE && S.gender == FEMALE)
continue
if(pref.gender == FEMALE && S.gender == MALE)
continue
if(!(pref.species in S.species_allowed))
continue
valid_hairstyles[hairstyle] = hair_styles_list[hairstyle]
if(valid_hairstyles.len)
pref.h_style = pick(valid_hairstyles)
else
//this shouldn't happen
pref.h_style = hair_styles_list["Bald"]
//grab one of the valid facial hair styles for the newly chosen species
var/list/valid_facialhairstyles = list()
for(var/facialhairstyle in facial_hair_styles_list)
var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle]
if(pref.gender == MALE && S.gender == FEMALE)
continue
if(pref.gender == FEMALE && S.gender == MALE)
continue
if(!(pref.species in S.species_allowed))
continue
valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle]
if(valid_facialhairstyles.len)
pref.f_style = pick(valid_facialhairstyles)
else
//this shouldn't happen
pref.f_style = facial_hair_styles_list["Shaved"]
//reset hair colour and skin colour
pref.r_hair = 0//hex2num(copytext(new_hair, 2, 4))
pref.g_hair = 0//hex2num(copytext(new_hair, 4, 6))
pref.b_hair = 0//hex2num(copytext(new_hair, 6, 8))
pref.s_tone = 0
return TOPIC_REFRESH
else if(href_list["hair_color"])
if(!has_flag(mob_species, HAS_HAIR_COLOR))
return TOPIC_NOACTION
var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference", rgb(pref.r_hair, pref.g_hair, pref.b_hair)) as color|null
if(new_hair && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
pref.r_hair = hex2num(copytext(new_hair, 2, 4))
pref.g_hair = hex2num(copytext(new_hair, 4, 6))
pref.b_hair = hex2num(copytext(new_hair, 6, 8))
return TOPIC_REFRESH
else if(href_list["hair_style"])
var/list/valid_hairstyles = list()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
if(!(pref.species in S.species_allowed))
continue
valid_hairstyles[hairstyle] = hair_styles_list[hairstyle]
var/new_h_style = input(user, "Choose your character's hair style:", "Character Preference", pref.h_style) as null|anything in valid_hairstyles
if(new_h_style && CanUseTopic(user))
pref.h_style = new_h_style
return TOPIC_REFRESH
else if(href_list["facial_color"])
if(!has_flag(mob_species, HAS_HAIR_COLOR))
return TOPIC_NOACTION
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference", rgb(pref.r_facial, pref.g_facial, pref.b_facial)) as color|null
if(new_facial && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
pref.r_facial = hex2num(copytext(new_facial, 2, 4))
pref.g_facial = hex2num(copytext(new_facial, 4, 6))
pref.b_facial = hex2num(copytext(new_facial, 6, 8))
return TOPIC_REFRESH
else if(href_list["eye_color"])
if(!has_flag(mob_species, HAS_EYE_COLOR))
return TOPIC_NOACTION
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference", rgb(pref.r_eyes, pref.g_eyes, pref.b_eyes)) as color|null
if(new_eyes && has_flag(mob_species, HAS_EYE_COLOR) && CanUseTopic(user))
pref.r_eyes = hex2num(copytext(new_eyes, 2, 4))
pref.g_eyes = hex2num(copytext(new_eyes, 4, 6))
pref.b_eyes = hex2num(copytext(new_eyes, 6, 8))
return TOPIC_REFRESH
else if(href_list["skin_tone"])
if(!has_flag(mob_species, HAS_SKIN_TONE))
return TOPIC_NOACTION
var/new_s_tone = input(user, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Character Preference", pref.s_tone) as num|null
if(new_s_tone && has_flag(mob_species, HAS_SKIN_TONE) && CanUseTopic(user))
pref.s_tone = 35 - max(min( round(new_s_tone), 220),1)
return TOPIC_REFRESH
else if(href_list["skin_color"])
if(!has_flag(mob_species, HAS_SKIN_COLOR))
return TOPIC_NOACTION
var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference", rgb(pref.r_skin, pref.g_skin, pref.b_skin)) as color|null
if(new_skin && has_flag(mob_species, HAS_SKIN_COLOR) && CanUseTopic(user))
pref.r_skin = hex2num(copytext(new_skin, 2, 4))
pref.g_skin = hex2num(copytext(new_skin, 4, 6))
pref.b_skin = hex2num(copytext(new_skin, 6, 8))
return TOPIC_REFRESH
else if(href_list["facial_style"])
var/list/valid_facialhairstyles = list()
for(var/facialhairstyle in facial_hair_styles_list)
var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle]
if(pref.gender == MALE && S.gender == FEMALE)
continue
if(pref.gender == FEMALE && S.gender == MALE)
continue
if(!(pref.species in S.species_allowed))
continue
valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle]
var/new_f_style = input(user, "Choose your character's facial-hair style:", "Character Preference", pref.f_style) as null|anything in valid_facialhairstyles
if(new_f_style && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
pref.f_style = new_f_style
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")
if(!limb_name && !CanUseTopic(user)) return TOPIC_NOACTION
var/limb = null
var/second_limb = null // if you try to change the arm, the hand should also change
var/third_limb = null // if you try to unchange the hand, the arm should also change
switch(limb_name)
if("Left Leg")
limb = "l_leg"
second_limb = "l_foot"
if("Right Leg")
limb = "r_leg"
second_limb = "r_foot"
if("Left Arm")
limb = "l_arm"
second_limb = "l_hand"
if("Right Arm")
limb = "r_arm"
second_limb = "r_hand"
if("Left Foot")
limb = "l_foot"
third_limb = "l_leg"
if("Right Foot")
limb = "r_foot"
third_limb = "r_leg"
if("Left Hand")
limb = "l_hand"
third_limb = "l_arm"
if("Right Hand")
limb = "r_hand"
third_limb = "r_arm"
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
switch(new_state)
if("Normal")
pref.organ_data[limb] = null
pref.rlimb_data[limb] = null
if(third_limb)
pref.organ_data[third_limb] = null
pref.rlimb_data[third_limb] = null
if("Amputated")
pref.organ_data[limb] = "amputated"
pref.rlimb_data[limb] = null
if(second_limb)
pref.organ_data[second_limb] = "amputated"
pref.rlimb_data[second_limb] = null
if("Prothesis")
var/tmp_species = pref.species ? pref.species : "Human"
var/list/usable_manufacturers = list()
for(var/company in chargen_robolimbs)
var/datum/robolimb/M = chargen_robolimbs[company]
if(tmp_species in M.species_cannot_use)
continue
usable_manufacturers[company] = M
if(!usable_manufacturers.len)
return
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
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")
if(!organ_name) return
var/organ = null
switch(organ_name)
if("Heart")
organ = "heart"
if("Eyes")
organ = "eyes"
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")
pref.organ_data[organ] = null
if("Assisted")
pref.organ_data[organ] = "assisted"
if("Mechanical")
pref.organ_data[organ] = "mechanical"
return TOPIC_REFRESH
else if(href_list["disabilities"])
var/disability_flag = text2num(href_list["disabilities"])
pref.disabilities ^= disability_flag
return TOPIC_REFRESH
return ..()
/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"
var/datum/species/current_species = all_species[pref.species_preview]
var/dat = "<body>"
dat += "<center><h2>[current_species.name] \[<a href='?src=\ref[src];show_species=1'>change</a>\]</h2></center><hr/>"
dat += "<table padding='8px'>"
dat += "<tr>"
dat += "<td width = 400>[current_species.blurb]</td>"
dat += "<td width = 200 align='center'>"
if("preview" in icon_states(current_species.icobase))
usr << browse_rsc(icon(current_species.icobase,"preview"), "species_preview_[current_species.name].png")
dat += "<img src='species_preview_[current_species.name].png' width='64px' height='64px'><br/><br/>"
dat += "<b>Language:</b> [current_species.language]<br/>"
dat += "<small>"
if(current_species.spawn_flags & CAN_JOIN)
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.flags & NO_SCAN)
dat += "</br><b>Does not have DNA.</b>"
if(current_species.flags & NO_PAIN)
dat += "</br><b>Does not feel pain.</b>"
if(current_species.flags & NO_SLIP)
dat += "</br><b>Has excellent traction.</b>"
if(current_species.flags & NO_POISON)
dat += "</br><b>Immune to most poisons.</b>"
if(current_species.appearance_flags & HAS_SKIN_TONE)
dat += "</br><b>Has a variety of skin tones.</b>"
if(current_species.appearance_flags & HAS_SKIN_COLOR)
dat += "</br><b>Has a variety of skin colours.</b>"
if(current_species.appearance_flags & HAS_EYE_COLOR)
dat += "</br><b>Has a variety of eye colours.</b>"
if(current_species.flags & IS_PLANT)
dat += "</br><b>Has a plantlike physiology.</b>"
dat += "</small></td>"
dat += "</tr>"
dat += "</table><center><hr/>"
var/restricted = 0
if(config.usealienwhitelist) //If we're using the whitelist, make sure to check it!
if(!(current_species.spawn_flags & CAN_JOIN))
restricted = 2
else if((current_species.spawn_flags & IS_WHITELISTED) && !is_alien_whitelisted(preference_mob(),current_species))
restricted = 1
if(restricted)
if(restricted == 1)
dat += "<font color='red'><b>You cannot play as this species.</br><small>If you wish to be whitelisted, you can make an application post on <a href='?src=\ref[user];preference=open_whitelist_forum'>the forums</a>.</small></b></font></br>"
else if(restricted == 2)
dat += "<font color='red'><b>You cannot play as this species.</br><small>This species is not available for play as a station race..</small></b></font></br>"
if(!restricted || check_rights(R_ADMIN, 0))
dat += "\[<a href='?src=\ref[src];set_species=[pref.species_preview]'>select</a>\]"
dat += "</center></body>"
user << browse(dat, "window=species;size=700x400")
@@ -1,146 +0,0 @@
/datum/category_item/player_setup_item/general/equipment
name = "Equipment"
sort_order = 4
/datum/category_item/player_setup_item/general/equipment/load_character(var/savefile/S)
S["underwear"] >> pref.underwear
S["undershirt"] >> pref.undershirt
S["socks"] >> pref.socks
S["backbag"] >> pref.backbag
S["gear"] >> pref.gear
/datum/category_item/player_setup_item/general/equipment/save_character(var/savefile/S)
S["underwear"] << pref.underwear
S["undershirt"] << pref.undershirt
S["socks"] << pref.socks
S["backbag"] << pref.backbag
S["gear"] << pref.gear
/datum/category_item/player_setup_item/general/equipment/sanitize_character()
pref.backbag = sanitize_integer(pref.backbag, 1, backbaglist.len, initial(pref.backbag))
if(!islist(pref.gear)) pref.gear = list()
var/undies = get_undies()
if(!get_key_by_value(undies, pref.underwear))
pref.underwear = undies[1]
if(!get_key_by_value(undershirt_t, pref.undershirt))
pref.undershirt = undershirt_t[1]
if(!get_key_by_value(socks_t, pref.socks))
pref.socks = socks_t[1]
var/total_cost = 0
for(var/gear_name in pref.gear)
if(!gear_datums[gear_name])
pref.gear -= gear_name
else if(!(gear_name in valid_gear_choices()))
pref.gear -= gear_name
else
var/datum/gear/G = gear_datums[gear_name]
if(total_cost + G.cost > MAX_GEAR_COST)
pref.gear -= gear_name
else
total_cost += G.cost
/datum/category_item/player_setup_item/general/equipment/content()
. += "<b>Equipment Loadout:</b><br>"
. += "Underwear: <a href='?src=\ref[src];change_underwear=1'><b>[get_key_by_value(get_undies(),pref.underwear)]</b></a><br>"
. += "Undershirt: <a href='?src=\ref[src];change_undershirt=1'><b>[get_key_by_value(undershirt_t,pref.undershirt)]</b></a><br>"
. += "Socks: <a href='?src=\ref[src];change_socks=1'><b>[get_key_by_value(socks_t,pref.socks)]</b></a><br>"
. += "Backpack Type: <a href='?src=\ref[src];change_backpack=1'><b>[backbaglist[pref.backbag]]</b></a><br>"
. += "<br><b>Custom Loadout:</b><br>"
var/total_cost = 0
if(pref.gear && pref.gear.len)
for(var/i = 1; i <= pref.gear.len; i++)
var/datum/gear/G = gear_datums[pref.gear[i]]
if(G)
total_cost += G.cost
. += "[pref.gear[i]] ([G.cost] points) <a href='?src=\ref[src];remove_loadout=[i]'>Remove</a><br>"
. += "<b>Used:</b> [total_cost] points."
else
. += "None."
if(total_cost < MAX_GEAR_COST)
. += " <a href='?src=\ref[src];add_loadout=1'>Add</a>"
if(pref.gear && pref.gear.len)
. += " <a href='?src=\ref[src];clear_loadout=1'>Clear</a>"
. += "<br>"
/datum/category_item/player_setup_item/general/equipment/proc/get_undies()
return pref.gender == MALE ? underwear_m : underwear_f
/datum/category_item/player_setup_item/general/equipment/proc/valid_gear_choices(var/max_cost)
var/list/valid_gear_choices = list()
for(var/gear_name in gear_datums)
var/datum/gear/G = gear_datums[gear_name]
if(G.whitelisted && !is_alien_whitelisted(preference_mob(), G.whitelisted))
continue
if(max_cost && G.cost > max_cost)
continue
valid_gear_choices += gear_name
return valid_gear_choices
/datum/category_item/player_setup_item/general/equipment/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["change_underwear"])
var/underwear_options = get_undies()
var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference", get_key_by_value(get_undies(),pref.underwear)) as null|anything in underwear_options
if(!isnull(new_underwear) && CanUseTopic(user))
pref.underwear = underwear_options[new_underwear]
return TOPIC_REFRESH
else if(href_list["change_undershirt"])
var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference", get_key_by_value(undershirt_t,pref.undershirt)) as null|anything in undershirt_t
if(!isnull(new_undershirt) && CanUseTopic(user))
pref.undershirt = undershirt_t[new_undershirt]
return TOPIC_REFRESH
else if(href_list["change_socks"])
var/new_socks = input(user, "Choose your character's socks:", "Character Preference", get_key_by_value(socks_t,pref.socks)) as null|anything in socks_t
if(!isnull(new_socks) && CanUseTopic(user))
pref.socks = socks_t[new_socks]
return TOPIC_REFRESH
/*
+ if("socks")
+ var/r = pick(socks_t)
+ socks = socks_t[r]
+ ShowChoices(user)
*/
else if(href_list["change_backpack"])
var/new_backbag = input(user, "Choose your character's style of bag:", "Character Preference", backbaglist[pref.backbag]) as null|anything in backbaglist
if(!isnull(new_backbag) && CanUseTopic(user))
pref.backbag = backbaglist.Find(new_backbag)
return TOPIC_REFRESH
else if(href_list["add_loadout"])
var/total_cost = 0
for(var/gear_name in pref.gear)
if(gear_datums[gear_name])
var/datum/gear/G = gear_datums[gear_name]
total_cost += G.cost
var/choice = input(user, "Select gear to add:", "Character Preference") as null|anything in valid_gear_choices(MAX_GEAR_COST - total_cost)
if(choice && gear_datums[choice] && CanUseTopic(user))
var/datum/gear/C = gear_datums[choice]
total_cost += C.cost
if(C && total_cost <= MAX_GEAR_COST)
pref.gear += choice
user << "<span class='notice'>Added \the '[choice]' for [C.cost] points ([MAX_GEAR_COST - total_cost] points remaining).</span>"
else
user << "<span class='warning'>Adding \the '[choice]' will exceed the maximum loadout cost of [MAX_GEAR_COST] points.</span>"
return TOPIC_REFRESH
else if(href_list["remove_loadout"])
var/i_remove = text2num(href_list["remove_loadout"])
if(i_remove < 1 || i_remove > pref.gear.len) return TOPIC_NOACTION
pref.gear.Cut(i_remove, i_remove + 1)
return TOPIC_REFRESH
else if(href_list["clear_loadout"])
pref.gear.Cut()
return TOPIC_REFRESH
return ..()
@@ -1,125 +0,0 @@
/datum/category_item/player_setup_item/general/background
name = "Background"
sort_order = 5
/datum/category_item/player_setup_item/general/background/load_character(var/savefile/S)
S["med_record"] >> pref.med_record
S["sec_record"] >> pref.sec_record
S["gen_record"] >> pref.gen_record
S["home_system"] >> pref.home_system
S["citizenship"] >> pref.citizenship
S["faction"] >> pref.faction
S["religion"] >> pref.religion
S["nanotrasen_relation"] >> pref.nanotrasen_relation
/datum/category_item/player_setup_item/general/background/save_character(var/savefile/S)
S["med_record"] << pref.med_record
S["sec_record"] << pref.sec_record
S["gen_record"] << pref.gen_record
S["home_system"] << pref.home_system
S["citizenship"] << pref.citizenship
S["faction"] << pref.faction
S["religion"] << pref.religion
S["nanotrasen_relation"] << pref.nanotrasen_relation
/datum/category_item/player_setup_item/general/background/sanitize_character()
if(!pref.home_system) pref.home_system = "Unset"
if(!pref.citizenship) pref.citizenship = "None"
if(!pref.faction) pref.faction = "None"
if(!pref.religion) pref.religion = "None"
pref.nanotrasen_relation = sanitize_inlist(pref.nanotrasen_relation, COMPANY_ALIGNMENTS, initial(pref.nanotrasen_relation))
/datum/category_item/player_setup_item/general/background/content(var/mob/user)
. += "<b>Background Information</b><br>"
. += "[company_name] Relation: <a href='?src=\ref[src];nt_relation=1'>[pref.nanotrasen_relation]</a><br/>"
. += "Home System: <a href='?src=\ref[src];home_system=1'>[pref.home_system]</a><br/>"
. += "Citizenship: <a href='?src=\ref[src];citizenship=1'>[pref.citizenship]</a><br/>"
. += "Faction: <a href='?src=\ref[src];faction=1'>[pref.faction]</a><br/>"
. += "Religion: <a href='?src=\ref[src];religion=1'>[pref.religion]</a><br/>"
. += "<br/><b>Records</b>:<br/>"
if(jobban_isbanned(user, "Records"))
. += "<span class='danger'>You are banned from using character records.</span><br>"
else
. += "Medical Records:<br>"
. += "<a href='?src=\ref[src];set_medical_records=1'>[TextPreview(pref.med_record,40)]</a><br><br>"
. += "Employment Records:<br>"
. += "<a href='?src=\ref[src];set_general_records=1'>[TextPreview(pref.gen_record,40)]</a><br><br>"
. += "Security Records:<br>"
. += "<a href='?src=\ref[src];set_security_records=1'>[TextPreview(pref.sec_record,40)]</a><br>"
/datum/category_item/player_setup_item/general/background/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["nt_relation"])
var/new_relation = input(user, "Choose your relation to NT. Note that this represents what others can find out about your character by researching your background, not what your character actually thinks.", "Character Preference", pref.nanotrasen_relation) as null|anything in COMPANY_ALIGNMENTS
if(new_relation && CanUseTopic(user))
pref.nanotrasen_relation = new_relation
return TOPIC_REFRESH
else if(href_list["home_system"])
var/choice = input(user, "Please choose a home system.", "Character Preference", pref.home_system) as null|anything in home_system_choices + list("Unset","Other")
if(!choice || !CanUseTopic(user))
return TOPIC_NOACTION
if(choice == "Other")
var/raw_choice = sanitize(input(user, "Please enter a home system.", "Character Preference") as text|null, MAX_NAME_LEN)
if(raw_choice && CanUseTopic(user))
pref.home_system = raw_choice
else
pref.home_system = choice
return TOPIC_REFRESH
else if(href_list["citizenship"])
var/choice = input(user, "Please choose your current citizenship.", "Character Preference", pref.citizenship) as null|anything in citizenship_choices + list("None","Other")
if(!choice || !CanUseTopic(user))
return TOPIC_NOACTION
if(choice == "Other")
var/raw_choice = sanitize(input(user, "Please enter your current citizenship.", "Character Preference") as text|null, MAX_NAME_LEN)
if(raw_choice && CanUseTopic(user))
pref.citizenship = raw_choice
else
pref.citizenship = choice
return TOPIC_REFRESH
else if(href_list["faction"])
var/choice = input(user, "Please choose a faction to work for.", "Character Preference", pref.faction) as null|anything in faction_choices + list("None","Other")
if(!choice || !CanUseTopic(user))
return TOPIC_NOACTION
if(choice == "Other")
var/raw_choice = sanitize(input(user, "Please enter a faction.", "Character Preference") as text|null, MAX_NAME_LEN)
if(raw_choice)
pref.faction = raw_choice
else
pref.faction = choice
return TOPIC_REFRESH
else if(href_list["religion"])
var/choice = input(user, "Please choose a religion.", "Character Preference", pref.religion) as null|anything in religion_choices + list("None","Other")
if(!choice || !CanUseTopic(user))
return TOPIC_NOACTION
if(choice == "Other")
var/raw_choice = sanitize(input(user, "Please enter a religon.", "Character Preference") as text|null, MAX_NAME_LEN)
if(raw_choice)
pref.religion = sanitize(raw_choice)
else
pref.religion = choice
return TOPIC_REFRESH
else if(href_list["set_medical_records"])
var/new_medical = sanitize(input(user,"Enter medical information here.","Character Preference", html_decode(pref.med_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
if(!isnull(new_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
pref.med_record = new_medical
return TOPIC_REFRESH
else if(href_list["set_general_records"])
var/new_general = sanitize(input(user,"Enter employment information here.","Character Preference", html_decode(pref.gen_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
if(!isnull(new_general) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
pref.gen_record = new_general
return TOPIC_REFRESH
else if(href_list["set_security_records"])
var/sec_medical = sanitize(input(user,"Enter security information here.","Character Preference", html_decode(pref.sec_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
if(!isnull(sec_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
pref.sec_record = sec_medical
return TOPIC_REFRESH
return ..()
@@ -1,127 +0,0 @@
/datum/category_item/player_setup_item/general/flavor
name = "Flavor"
sort_order = 6
/datum/category_item/player_setup_item/general/flavor/load_character(var/savefile/S)
S["flavor_texts_general"] >> pref.flavor_texts["general"]
S["flavor_texts_head"] >> pref.flavor_texts["head"]
S["flavor_texts_face"] >> pref.flavor_texts["face"]
S["flavor_texts_eyes"] >> pref.flavor_texts["eyes"]
S["flavor_texts_torso"] >> pref.flavor_texts["torso"]
S["flavor_texts_arms"] >> pref.flavor_texts["arms"]
S["flavor_texts_hands"] >> pref.flavor_texts["hands"]
S["flavor_texts_legs"] >> pref.flavor_texts["legs"]
S["flavor_texts_feet"] >> pref.flavor_texts["feet"]
//Flavour text for robots.
S["flavour_texts_robot_Default"] >> pref.flavour_texts_robot["Default"]
for(var/module in robot_module_types)
S["flavour_texts_robot_[module]"] >> pref.flavour_texts_robot[module]
/datum/category_item/player_setup_item/general/flavor/save_character(var/savefile/S)
S["flavor_texts_general"] << pref.flavor_texts["general"]
S["flavor_texts_head"] << pref.flavor_texts["head"]
S["flavor_texts_face"] << pref.flavor_texts["face"]
S["flavor_texts_eyes"] << pref.flavor_texts["eyes"]
S["flavor_texts_torso"] << pref.flavor_texts["torso"]
S["flavor_texts_arms"] << pref.flavor_texts["arms"]
S["flavor_texts_hands"] << pref.flavor_texts["hands"]
S["flavor_texts_legs"] << pref.flavor_texts["legs"]
S["flavor_texts_feet"] << pref.flavor_texts["feet"]
S["flavour_texts_robot_Default"] << pref.flavour_texts_robot["Default"]
for(var/module in robot_module_types)
S["flavour_texts_robot_[module]"] << pref.flavour_texts_robot[module]
/datum/category_item/player_setup_item/general/flavor/sanitize_character()
return
/datum/category_item/player_setup_item/general/flavor/content(var/mob/user)
. += "<b>Flavor:</b><br>"
. += "<a href='?src=\ref[src];flavor_text=open'>Set Flavor Text</a><br/>"
. += "<a href='?src=\ref[src];flavour_text_robot=open'>Set Robot Flavor Text</a><br/>"
/datum/category_item/player_setup_item/general/flavor/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["flavor_text"])
switch(href_list["flavor_text"])
if("open")
else if("general")
var/msg = sanitize(input(usr,"Give a general description of your character. This will be shown regardless of clothing, and may include OOC notes and preferences.","Flavor Text",html_decode(pref.flavor_texts[href_list["task"]])) as message, extra = 0)
if(CanUseTopic(user))
pref.flavor_texts[href_list["flavor_text"]] = msg
else
var/msg = sanitize(input(usr,"Set the flavor text for your [href_list["flavor_text"]].","Flavor Text",html_decode(pref.flavor_texts[href_list["flavor_text"]])) as message, extra = 0)
if(CanUseTopic(user))
pref.flavor_texts[href_list["flavor_text"]] = msg
SetFlavorText(user)
return TOPIC_HANDLED
else if(href_list["flavour_text_robot"])
switch(href_list["flavour_text_robot"])
if("open")
else if("Default")
var/msg = sanitize(input(usr,"Set the default flavour text for your robot. It will be used for any module without individual setting.","Flavour Text",html_decode(pref.flavour_texts_robot["Default"])) as message, extra = 0)
if(CanUseTopic(user))
pref.flavour_texts_robot[href_list["flavour_text_robot"]] = msg
else
var/msg = sanitize(input(usr,"Set the flavour text for your robot with [href_list["flavour_text_robot"]] module. If you leave this empty, default flavour text will be used for this module.","Flavour Text",html_decode(pref.flavour_texts_robot[href_list["flavour_text_robot"]])) as message, extra = 0)
if(CanUseTopic(user))
pref.flavour_texts_robot[href_list["flavour_text_robot"]] = msg
SetFlavourTextRobot(user)
return TOPIC_HANDLED
return ..()
/datum/category_item/player_setup_item/general/flavor/proc/SetFlavorText(mob/user)
var/HTML = "<body>"
HTML += "<tt><center>"
HTML += "<b>Set Flavour Text</b> <hr />"
HTML += "<br></center>"
HTML += "<a href='?src=\ref[src];flavor_text=general'>General:</a> "
HTML += TextPreview(pref.flavor_texts["general"])
HTML += "<br>"
HTML += "<a href='?src=\ref[src];flavor_text=head'>Head:</a> "
HTML += TextPreview(pref.flavor_texts["head"])
HTML += "<br>"
HTML += "<a href='?src=\ref[src];flavor_text=face'>Face:</a> "
HTML += TextPreview(pref.flavor_texts["face"])
HTML += "<br>"
HTML += "<a href='?src=\ref[src];flavor_text=eyes'>Eyes:</a> "
HTML += TextPreview(pref.flavor_texts["eyes"])
HTML += "<br>"
HTML += "<a href='?src=\ref[src];flavor_text=torso'>Body:</a> "
HTML += TextPreview(pref.flavor_texts["torso"])
HTML += "<br>"
HTML += "<a href='?src=\ref[src];flavor_text=arms'>Arms:</a> "
HTML += TextPreview(pref.flavor_texts["arms"])
HTML += "<br>"
HTML += "<a href='?src=\ref[src];flavor_text=hands'>Hands:</a> "
HTML += TextPreview(pref.flavor_texts["hands"])
HTML += "<br>"
HTML += "<a href='?src=\ref[src];flavor_text=legs'>Legs:</a> "
HTML += TextPreview(pref.flavor_texts["legs"])
HTML += "<br>"
HTML += "<a href='?src=\ref[src];flavor_text=feet'>Feet:</a> "
HTML += TextPreview(pref.flavor_texts["feet"])
HTML += "<br>"
HTML += "<hr />"
HTML += "<tt>"
user << browse(HTML, "window=flavor_text;size=430x300")
return
/datum/category_item/player_setup_item/general/flavor/proc/SetFlavourTextRobot(mob/user)
var/HTML = "<body>"
HTML += "<tt><center>"
HTML += "<b>Set Robot Flavour Text</b> <hr />"
HTML += "<br></center>"
HTML += "<a href='?src=\ref[src];flavour_text_robot=Default'>Default:</a> "
HTML += TextPreview(pref.flavour_texts_robot["Default"])
HTML += "<hr />"
for(var/module in robot_module_types)
HTML += "<a href='?src=\ref[src];flavour_text_robot=[module]'>[module]:</a> "
HTML += TextPreview(pref.flavour_texts_robot[module])
HTML += "<br>"
HTML += "<hr />"
HTML += "<tt>"
user << browse(HTML, "window=flavour_text_robot;size=430x300")
return
@@ -1,73 +0,0 @@
/datum/category_item/player_setup_item/player_global/ui
name = "UI"
sort_order = 1
/datum/category_item/player_setup_item/player_global/ui/load_preferences(var/savefile/S)
S["UI_style"] >> pref.UI_style
S["UI_style_color"] >> pref.UI_style_color
S["UI_style_alpha"] >> pref.UI_style_alpha
S["ooccolor"] >> pref.ooccolor
/datum/category_item/player_setup_item/player_global/ui/save_preferences(var/savefile/S)
S["UI_style"] << pref.UI_style
S["UI_style_color"] << pref.UI_style_color
S["UI_style_alpha"] << pref.UI_style_alpha
S["ooccolor"] << pref.ooccolor
/datum/category_item/player_setup_item/player_global/ui/sanitize_preferences()
pref.UI_style = sanitize_inlist(pref.UI_style, all_ui_styles, initial(pref.UI_style))
pref.UI_style_color = sanitize_hexcolor(pref.UI_style_color, initial(pref.UI_style_color))
pref.UI_style_alpha = sanitize_integer(pref.UI_style_alpha, 0, 255, initial(pref.UI_style_alpha))
pref.ooccolor = sanitize_hexcolor(pref.ooccolor, initial(pref.ooccolor))
/datum/category_item/player_setup_item/player_global/ui/content(var/mob/user)
. = "<b>UI Style:</b> <a href='?src=\ref[src];select_style=1'><b>[pref.UI_style]</b></a><br>"
. += "<b>Custom UI</b> (recommended for White UI):<br>"
. += "-Color: <a href='?src=\ref[src];select_color=1'><b>[pref.UI_style_color]</b></a> <table style='display:inline;' bgcolor='[pref.UI_style_color]'><tr><td>__</td></tr></table> <a href='?src=\ref[src];reset=ui'>reset</a><br>"
. += "-Alpha(transparency): <a href='?src=\ref[src];select_alpha=1'><b>[pref.UI_style_alpha]</b></a> <a href='?src=\ref[src];reset=alpha'>reset</a><br>"
if(can_select_ooc_color(user))
. += "<b>OOC Color:</b> "
if(pref.ooccolor == initial(pref.ooccolor))
. += "<a href='?src=\ref[src];select_ooc_color=1'><b>Using Default</b></a><br>"
else
. += "<a href='?src=\ref[src];select_ooc_color=1'><b>[pref.ooccolor]</b></a> <table style='display:inline;' bgcolor='[pref.ooccolor]'><tr><td>__</td></tr></table> <a href='?src=\ref[src];reset=ooc'>reset</a><br>"
/datum/category_item/player_setup_item/player_global/ui/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["select_style"])
var/UI_style_new = input(user, "Choose UI style.", "Character Preference", pref.UI_style) as null|anything in all_ui_styles
if(!UI_style_new || !CanUseTopic(user)) return TOPIC_NOACTION
pref.UI_style = UI_style_new
return TOPIC_REFRESH
else if(href_list["select_color"])
var/UI_style_color_new = input(user, "Choose UI color, dark colors are not recommended!", "Global Preference", pref.UI_style_color) as color|null
if(isnull(UI_style_color_new) || !CanUseTopic(user)) return TOPIC_NOACTION
pref.UI_style_color = UI_style_color_new
return TOPIC_REFRESH
else if(href_list["select_alpha"])
var/UI_style_alpha_new = input(user, "Select UI alpha (transparency) level, between 50 and 255.", "Global Preference", pref.UI_style_alpha) as num|null
if(isnull(UI_style_alpha_new) || (UI_style_alpha_new < 50 || UI_style_alpha_new > 255) || !CanUseTopic(user)) return TOPIC_NOACTION
pref.UI_style_alpha = UI_style_alpha_new
return TOPIC_REFRESH
else if(href_list["select_ooc_color"])
var/new_ooccolor = input(user, "Choose OOC color:", "Global Preference") as color|null
if(new_ooccolor && can_select_ooc_color(user) && CanUseTopic(user))
pref.ooccolor = new_ooccolor
return TOPIC_REFRESH
else if(href_list["reset"])
switch(href_list["reset"])
if("ui")
pref.UI_style_color = initial(pref.UI_style_color)
if("alpha")
pref.UI_style_alpha = initial(pref.UI_style_alpha)
if("ooc")
pref.ooccolor = initial(pref.ooccolor)
return TOPIC_REFRESH
return ..()
/datum/category_item/player_setup_item/player_global/ui/proc/can_select_ooc_color(var/mob/user)
return config.allow_admin_ooccolor && check_rights(R_ADMIN, 0, user)
@@ -1,38 +0,0 @@
/datum/category_item/player_setup_item/player_global/settings
name = "Settings"
sort_order = 2
/datum/category_item/player_setup_item/player_global/settings/load_preferences(var/savefile/S)
S["lastchangelog"] >> pref.lastchangelog
S["default_slot"] >> pref.default_slot
S["toggles"] >> pref.toggles
/datum/category_item/player_setup_item/player_global/settings/save_preferences(var/savefile/S)
S["lastchangelog"] << pref.lastchangelog
S["default_slot"] << pref.default_slot
S["toggles"] << pref.toggles
/datum/category_item/player_setup_item/player_global/settings/sanitize_preferences()
pref.lastchangelog = sanitize_text(pref.lastchangelog, initial(pref.lastchangelog))
pref.default_slot = sanitize_integer(pref.default_slot, 1, config.character_slots, initial(pref.default_slot))
pref.toggles = sanitize_integer(pref.toggles, 0, 65535, initial(pref.toggles))
/datum/category_item/player_setup_item/player_global/settings/content(var/mob/user)
. += "<b>Play admin midis:</b> <a href='?src=\ref[src];toggle=[SOUND_MIDI]'><b>[(pref.toggles & SOUND_MIDI) ? "Yes" : "No"]</b></a><br>"
. += "<b>Play lobby music:</b> <a href='?src=\ref[src];toggle=[SOUND_LOBBY]'><b>[(pref.toggles & SOUND_LOBBY) ? "Yes" : "No"]</b></a><br>"
. += "<b>Ghost ears:</b> <a href='?src=\ref[src];toggle=[CHAT_GHOSTEARS]'><b>[(pref.toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]</b></a><br>"
. += "<b>Ghost sight:</b> <a href='?src=\ref[src];toggle=[CHAT_GHOSTSIGHT]'><b>[(pref.toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]</b></a><br>"
. += "<b>Ghost radio:</b> <a href='?src=\ref[src];toggle=[CHAT_GHOSTRADIO]'><b>[(pref.toggles & CHAT_GHOSTRADIO) ? "All Chatter" : "Nearest Speakers"]</b></a><br>"
/datum/category_item/player_setup_item/player_global/settings/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["toggle"])
var/toggle_flag = text2num(href_list["toggle"])
pref.toggles ^= toggle_flag
if(toggle_flag == SOUND_LOBBY && isnewplayer(user))
if(pref.toggles & SOUND_LOBBY)
user << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1)
else
user << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1)
return TOPIC_REFRESH
return ..()
@@ -1,54 +0,0 @@
/datum/category_item/player_setup_item/player_global/pai
name = "pAI"
sort_order = 3
var/datum/paiCandidate/candidate
/datum/category_item/player_setup_item/player_global/pai/load_preferences(var/savefile/S)
if(!candidate)
candidate = new()
if(!preference_mob())
return
candidate.savefile_load(preference_mob())
/datum/category_item/player_setup_item/player_global/pai/save_preferences(var/savefile/S)
if(!candidate)
return
if(!preference_mob())
return
candidate.savefile_save(preference_mob())
/datum/category_item/player_setup_item/player_global/pai/content(var/mob/user)
. += "<b>pAI:</b><br>"
. += "Name: <a href='?src=\ref[src];option=name'>[candidate.name ? candidate.name : "None Set"]</a><br>"
. += "Description: <a href='?src=\ref[src];option=desc'>[candidate.description ? TextPreview(candidate.description, 40) : "None Set"]</a><br>"
. += "Role: <a href='?src=\ref[src];option=role'>[candidate.role ? TextPreview(candidate.role, 40) : "None Set"]</a><br>"
. += "OOC Comments: <a href='?src=\ref[src];option=ooc'>[candidate.comments ? TextPreview(candidate.comments, 40) : "None Set"]</a><br>"
/datum/category_item/player_setup_item/player_global/pai/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["option"])
var/t
switch(href_list["option"])
if("name")
t = sanitizeName(input(user, "Enter a name for your pAI", "Global Preference", candidate.name) as text|null, MAX_NAME_LEN, 1)
if(t && CanUseTopic(user))
candidate.name = t
if("desc")
t = input(user, "Enter a description for your pAI", "Global Preference", html_decode(candidate.description)) as message|null
if(!isnull(t) && CanUseTopic(user))
candidate.description = sanitize(t)
if("role")
t = input(user, "Enter a role for your pAI", "Global Preference", html_decode(candidate.role)) as text|null
if(!isnull(t) && CanUseTopic(user))
candidate.role = sanitize(t)
if("ooc")
t = input(user, "Enter any OOC comments", "Global Preference", html_decode(candidate.comments)) as message
if(!isnull(t) && CanUseTopic(user))
candidate.comments = sanitize(t)
return TOPIC_REFRESH
return ..()
@@ -1,291 +0,0 @@
//used for pref.alternate_option
#define GET_RANDOM_JOB 0
#define BE_ASSISTANT 1
#define RETURN_TO_LOBBY 2
/datum/category_item/player_setup_item/occupation
name = "Occupation"
sort_order = 1
/datum/category_item/player_setup_item/occupation/load_character(var/savefile/S)
S["alternate_option"] >> pref.alternate_option
S["job_civilian_high"] >> pref.job_civilian_high
S["job_civilian_med"] >> pref.job_civilian_med
S["job_civilian_low"] >> pref.job_civilian_low
S["job_medsci_high"] >> pref.job_medsci_high
S["job_medsci_med"] >> pref.job_medsci_med
S["job_medsci_low"] >> pref.job_medsci_low
S["job_engsec_high"] >> pref.job_engsec_high
S["job_engsec_med"] >> pref.job_engsec_med
S["job_engsec_low"] >> pref.job_engsec_low
S["player_alt_titles"] >> pref.player_alt_titles
/datum/category_item/player_setup_item/occupation/save_character(var/savefile/S)
S["alternate_option"] << pref.alternate_option
S["job_civilian_high"] << pref.job_civilian_high
S["job_civilian_med"] << pref.job_civilian_med
S["job_civilian_low"] << pref.job_civilian_low
S["job_medsci_high"] << pref.job_medsci_high
S["job_medsci_med"] << pref.job_medsci_med
S["job_medsci_low"] << pref.job_medsci_low
S["job_engsec_high"] << pref.job_engsec_high
S["job_engsec_med"] << pref.job_engsec_med
S["job_engsec_low"] << pref.job_engsec_low
S["player_alt_titles"] << pref.player_alt_titles
/datum/category_item/player_setup_item/occupation/sanitize_character()
pref.alternate_option = sanitize_integer(pref.alternate_option, 0, 2, initial(pref.alternate_option))
pref.job_civilian_high = sanitize_integer(pref.job_civilian_high, 0, 65535, initial(pref.job_civilian_high))
pref.job_civilian_med = sanitize_integer(pref.job_civilian_med, 0, 65535, initial(pref.job_civilian_med))
pref.job_civilian_low = sanitize_integer(pref.job_civilian_low, 0, 65535, initial(pref.job_civilian_low))
pref.job_medsci_high = sanitize_integer(pref.job_medsci_high, 0, 65535, initial(pref.job_medsci_high))
pref.job_medsci_med = sanitize_integer(pref.job_medsci_med, 0, 65535, initial(pref.job_medsci_med))
pref.job_medsci_low = sanitize_integer(pref.job_medsci_low, 0, 65535, initial(pref.job_medsci_low))
pref.job_engsec_high = sanitize_integer(pref.job_engsec_high, 0, 65535, initial(pref.job_engsec_high))
pref.job_engsec_med = sanitize_integer(pref.job_engsec_med, 0, 65535, initial(pref.job_engsec_med))
pref.job_engsec_low = sanitize_integer(pref.job_engsec_low, 0, 65535, initial(pref.job_engsec_low))
if(!pref.player_alt_titles) pref.player_alt_titles = new()
if(!job_master)
return
for(var/datum/job/job in job_master.occupations)
var/alt_title = pref.player_alt_titles[job.title]
if(alt_title && !(alt_title in job.alt_titles))
pref.player_alt_titles -= job.title
/datum/category_item/player_setup_item/occupation/content(mob/user, limit = 16, list/splitJobs = list("Chief Medical Officer"))
if(!job_master)
return
. += "<tt><center>"
. += "<b>Choose occupation chances</b><br>Unavailable occupations are crossed out.<br>"
. += "<table width='100%' cellpadding='1' cellspacing='0'><tr><td width='20%'>" // Table within a table for alignment, also allows you to easily add more colomns.
. += "<table width='100%' cellpadding='1' cellspacing='0'>"
var/index = -1
//The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows.
var/datum/job/lastJob
if (!job_master) return
for(var/datum/job/job in job_master.occupations)
index += 1
if((index >= limit) || (job.title in splitJobs))
if((index < limit) && (lastJob != null))
//If the cells were broken up by a job in the splitJob list then it will fill in the rest of the cells with
//the last job's selection color. Creating a rather nice effect.
for(var/i = 0, i < (limit - index), i += 1)
. += "<tr bgcolor='[lastJob.selection_color]'><td width='60%' align='right'><a>&nbsp</a></td><td><a>&nbsp</a></td></tr>"
. += "</table></td><td width='20%'><table width='100%' cellpadding='1' cellspacing='0'>"
index = 0
. += "<tr bgcolor='[job.selection_color]'><td width='60%' align='right'>"
var/rank = job.title
lastJob = job
if(jobban_isbanned(user, rank))
. += "<del>[rank]</del></td><td><b> \[BANNED]</b></td></tr>"
continue
if(!job.player_old_enough(user.client))
var/available_in_days = job.available_in_days(user.client)
. += "<del>[rank]</del></td><td> \[IN [(available_in_days)] DAYS]</td></tr>"
continue
if((pref.job_civilian_low & ASSISTANT) && (rank != "Assistant"))
. += "<font color=orange>[rank]</font></td><td></td></tr>"
continue
if((rank in command_positions) || (rank == "AI"))//Bold head jobs
. += "<b>[rank]</b>"
else
. += "[rank]"
. += "</td><td width='40%'>"
. += "<a href='?src=\ref[src];set_job=[rank]'>"
if(rank == "Assistant")//Assistant is special
if(pref.job_civilian_low & ASSISTANT)
. += " <font color=green>\[Yes]</font>"
else
. += " <font color=red>\[No]</font>"
if(job.alt_titles) //Blatantly cloned from a few lines down.
. += "</a></td></tr><tr bgcolor='[lastJob.selection_color]'><td width='60%' align='center'>&nbsp</td><td><a href='?src=\ref[src];select_alt_title=\ref[job]'>\[[pref.GetPlayerAltTitle(job)]\]</a></td></tr>"
. += "</a></td></tr>"
continue
if(pref.GetJobDepartment(job, 1) & job.flag)
. += " <font color=blue>\[High]</font>"
else if(pref.GetJobDepartment(job, 2) & job.flag)
. += " <font color=green>\[Medium]</font>"
else if(pref.GetJobDepartment(job, 3) & job.flag)
. += " <font color=orange>\[Low]</font>"
else
. += " <font color=red>\[NEVER]</font>"
if(job.alt_titles)
. += "</a></td></tr><tr bgcolor='[lastJob.selection_color]'><td width='60%' align='center'>&nbsp</td><td><a href='?src=\ref[src];select_alt_title=\ref[job]'>\[[pref.GetPlayerAltTitle(job)]\]</a></td></tr>"
. += "</a></td></tr>"
. += "</td'></tr></table>"
. += "</center></table>"
switch(pref.alternate_option)
if(GET_RANDOM_JOB)
. += "<center><br><u><a href='?src=\ref[src];job_alternative=1'><font color=green>Get random job if preferences unavailable</font></a></u></center><br>"
if(BE_ASSISTANT)
. += "<center><br><u><a href='?src=\ref[src];job_alternative=1'><font color=red>Be assistant if preference unavailable</font></a></u></center><br>"
if(RETURN_TO_LOBBY)
. += "<center><br><u><a href='?src=\ref[src];job_alternative=1'><font color=purple>Return to lobby if preference unavailable</font></a></u></center><br>"
. += "<center><a href='?src=\ref[src];reset_jobs=1'>\[Reset\]</a></center>"
. += "</tt>"
/datum/category_item/player_setup_item/occupation/OnTopic(href, href_list, user)
if(href_list["reset_jobs"])
ResetJobs()
return TOPIC_REFRESH
else if(href_list["job_alternative"])
if(pref.alternate_option == GET_RANDOM_JOB || pref.alternate_option == BE_ASSISTANT)
pref.alternate_option += 1
else if(pref.alternate_option == RETURN_TO_LOBBY)
pref.alternate_option = 0
return TOPIC_REFRESH
else if(href_list["select_alt_title"])
var/datum/job/job = locate(href_list["select_alt_title"])
if (job)
var/choices = list(job.title) + job.alt_titles
var/choice = input("Choose an title for [job.title].", "Choose Title", pref.GetPlayerAltTitle(job)) as anything in choices|null
if(choice && CanUseTopic(user))
SetPlayerAltTitle(job, choice)
return TOPIC_REFRESH
else if(href_list["set_job"])
if(SetJob(user, href_list["set_job"])) return TOPIC_REFRESH
return ..()
/datum/category_item/player_setup_item/occupation/proc/SetPlayerAltTitle(datum/job/job, new_title)
// remove existing entry
pref.player_alt_titles -= job.title
// add one if it's not default
if(job.title != new_title)
pref.player_alt_titles[job.title] = new_title
/datum/category_item/player_setup_item/occupation/proc/SetJob(mob/user, role)
var/datum/job/job = job_master.GetJob(role)
if(!job)
return 0
if(role == "Assistant")
if(pref.job_civilian_low & job.flag)
pref.job_civilian_low &= ~job.flag
else
pref.job_civilian_low |= job.flag
return 1
if(pref.GetJobDepartment(job, 1) & job.flag)
SetJobDepartment(job, 1)
else if(pref.GetJobDepartment(job, 2) & job.flag)
SetJobDepartment(job, 2)
else if(pref.GetJobDepartment(job, 3) & job.flag)
SetJobDepartment(job, 3)
else//job = Never
SetJobDepartment(job, 4)
return 1
/datum/category_item/player_setup_item/occupation/proc/SetJobDepartment(var/datum/job/job, var/level)
if(!job || !level) return 0
switch(level)
if(1)//Only one of these should ever be active at once so clear them all here
pref.job_civilian_high = 0
pref.job_medsci_high = 0
pref.job_engsec_high = 0
return 1
if(2)//Set current highs to med, then reset them
pref.job_civilian_med |= pref.job_civilian_high
pref.job_medsci_med |= pref.job_medsci_high
pref.job_engsec_med |= pref.job_engsec_high
pref.job_civilian_high = 0
pref.job_medsci_high = 0
pref.job_engsec_high = 0
switch(job.department_flag)
if(CIVILIAN)
switch(level)
if(2)
pref.job_civilian_high = job.flag
pref.job_civilian_med &= ~job.flag
if(3)
pref.job_civilian_med |= job.flag
pref.job_civilian_low &= ~job.flag
else
pref.job_civilian_low |= job.flag
if(MEDSCI)
switch(level)
if(2)
pref.job_medsci_high = job.flag
pref.job_medsci_med &= ~job.flag
if(3)
pref.job_medsci_med |= job.flag
pref.job_medsci_low &= ~job.flag
else
pref.job_medsci_low |= job.flag
if(ENGSEC)
switch(level)
if(2)
pref.job_engsec_high = job.flag
pref.job_engsec_med &= ~job.flag
if(3)
pref.job_engsec_med |= job.flag
pref.job_engsec_low &= ~job.flag
else
pref.job_engsec_low |= job.flag
return 1
/datum/category_item/player_setup_item/occupation/proc/ResetJobs()
pref.job_civilian_high = 0
pref.job_civilian_med = 0
pref.job_civilian_low = 0
pref.job_medsci_high = 0
pref.job_medsci_med = 0
pref.job_medsci_low = 0
pref.job_engsec_high = 0
pref.job_engsec_med = 0
pref.job_engsec_low = 0
pref.player_alt_titles.Cut()
/datum/preferences/proc/GetPlayerAltTitle(datum/job/job)
return (job.title in player_alt_titles) ? player_alt_titles[job.title] : job.title
/datum/preferences/proc/GetJobDepartment(var/datum/job/job, var/level)
if(!job || !level) return 0
switch(job.department_flag)
if(CIVILIAN)
switch(level)
if(1)
return job_civilian_high
if(2)
return job_civilian_med
if(3)
return job_civilian_low
if(MEDSCI)
switch(level)
if(1)
return job_medsci_high
if(2)
return job_medsci_med
if(3)
return job_medsci_low
if(ENGSEC)
switch(level)
if(1)
return job_engsec_high
if(2)
return job_engsec_med
if(3)
return job_engsec_low
return 0
@@ -1,209 +0,0 @@
// These are not flags, binary operations not intended
#define TOPIC_NOACTION 0
#define TOPIC_HANDLED 1
#define TOPIC_REFRESH 2
/datum/category_group/player_setup_category/general_preferences
name = "General"
sort_order = 1
category_item_type = /datum/category_item/player_setup_item/general
/datum/category_group/player_setup_category/skill_preferences
name = "Skills"
sort_order = 2
category_item_type = /datum/category_item/player_setup_item/skills
/datum/category_group/player_setup_category/occupation_preferences
name = "Occupation"
sort_order = 3
category_item_type = /datum/category_item/player_setup_item/occupation
/datum/category_group/player_setup_category/appearance_preferences
name = "Antagonism"
sort_order = 4
category_item_type = /datum/category_item/player_setup_item/antagonism
/datum/category_group/player_setup_category/global_preferences
name = "Global"
sort_order = 5
category_item_type = /datum/category_item/player_setup_item/player_global
/****************************
* Category Collection Setup *
****************************/
/datum/category_collection/player_setup_collection
category_group_type = /datum/category_group/player_setup_category
var/datum/preferences/preferences
var/datum/category_group/player_setup_category/selected_category = null
/datum/category_collection/player_setup_collection/New(var/datum/preferences/preferences)
src.preferences = preferences
..()
selected_category = categories[1]
/datum/category_collection/player_setup_collection/Destroy()
preferences = null
selected_category = null
return ..()
/datum/category_collection/player_setup_collection/proc/load_character(var/savefile/S)
for(var/datum/category_group/player_setup_category/PS in categories)
PS.load_character(S)
/datum/category_collection/player_setup_collection/proc/save_character(var/savefile/S)
for(var/datum/category_group/player_setup_category/PS in categories)
PS.save_character(S)
/datum/category_collection/player_setup_collection/proc/load_preferences(var/savefile/S)
for(var/datum/category_group/player_setup_category/PS in categories)
PS.load_preferences(S)
/datum/category_collection/player_setup_collection/proc/save_preferences(var/savefile/S)
for(var/datum/category_group/player_setup_category/PS in categories)
PS.save_preferences(S)
/datum/category_collection/player_setup_collection/proc/header()
var/dat = ""
for(var/datum/category_group/player_setup_category/PS in categories)
if(PS == selected_category)
dat += "[PS.name] " // TODO: Check how to properly mark a href/button selected in a classic browser window
else
dat += "<a href='?src=\ref[src];category=\ref[PS]'>[PS.name]</a> "
return dat
/datum/category_collection/player_setup_collection/proc/content(var/mob/user)
if(selected_category)
return selected_category.content(user)
/datum/category_collection/player_setup_collection/Topic(var/href,var/list/href_list)
if(..())
return 1
var/mob/user = usr
if(!user.client)
return 1
if(href_list["category"])
var/category = locate(href_list["category"])
if(category && category in categories)
selected_category = category
. = 1
if(.)
user.client.prefs.ShowChoices(user)
/**************************
* Category Category Setup *
**************************/
/datum/category_group/player_setup_category
var/sort_order = 0
/datum/category_group/player_setup_category/dd_SortValue()
return sort_order
/datum/category_group/player_setup_category/proc/load_character(var/savefile/S)
for(var/datum/category_item/player_setup_item/PI in items)
PI.load_character(S)
PI.sanitize_character()
/datum/category_group/player_setup_category/proc/save_character(var/savefile/S)
for(var/datum/category_item/player_setup_item/PI in items)
PI.sanitize_character()
PI.save_character(S)
/datum/category_group/player_setup_category/proc/load_preferences(var/savefile/S)
for(var/datum/category_item/player_setup_item/PI in items)
PI.load_preferences(S)
PI.sanitize_preferences()
/datum/category_group/player_setup_category/proc/save_preferences(var/savefile/S)
for(var/datum/category_item/player_setup_item/PI in items)
PI.sanitize_preferences()
PI.save_preferences(S)
/datum/category_group/player_setup_category/proc/content(var/mob/user)
. = "<table style='width:100%'><tr style='vertical-align:top'><td style='width:50%'>"
var/current = 0
var/halfway = items.len / 2
for(var/datum/category_item/player_setup_item/PI in items)
if(halfway && current++ >= halfway)
halfway = 0
. += "</td><td></td><td style='width:50%'>"
. += "[PI.content(user)]<br>"
. += "</td></tr></table>"
/datum/category_group/player_setup_category/occupation_preferences/content(var/mob/user)
for(var/datum/category_item/player_setup_item/PI in items)
. += "[PI.content(user)]<br>"
/**********************
* Category Item Setup *
**********************/
/datum/category_item/player_setup_item
var/sort_order = 0
var/datum/preferences/pref
/datum/category_item/player_setup_item/New()
..()
var/datum/category_collection/player_setup_collection/psc = category.collection
pref = psc.preferences
/datum/category_item/player_setup_item/Destroy()
pref = null
return ..()
/datum/category_item/player_setup_item/dd_SortValue()
return sort_order
/*
* Called when the item is asked to load per character settings
*/
/datum/category_item/player_setup_item/proc/load_character(var/savefile/S)
return
/*
* Called when the item is asked to save per character settings
*/
/datum/category_item/player_setup_item/proc/save_character(var/savefile/S)
return
/*
* Called when the item is asked to load user/global settings
*/
/datum/category_item/player_setup_item/proc/load_preferences(var/savefile/S)
return
/*
* Called when the item is asked to save user/global settings
*/
/datum/category_item/player_setup_item/proc/save_preferences(var/savefile/S)
return
/datum/category_item/player_setup_item/proc/content()
return
/datum/category_item/player_setup_item/proc/sanitize_character()
return
/datum/category_item/player_setup_item/proc/sanitize_preferences()
return
/datum/category_item/player_setup_item/Topic(var/href,var/list/href_list)
if(..())
return 1
var/mob/user = usr
if(!user.client)
return 1
. = OnTopic(href, href_list, user)
if(. == TOPIC_REFRESH)
user.client.prefs.ShowChoices(user)
/datum/category_item/player_setup_item/CanUseTopic(var/mob/user)
return 1
/datum/category_item/player_setup_item/proc/OnTopic(var/href,var/list/href_list, var/mob/user)
return TOPIC_NOACTION
/datum/category_item/player_setup_item/proc/preference_mob()
if(pref && pref.client && pref.client.mob)
return pref.client.mob
@@ -1,77 +0,0 @@
/datum/category_item/player_setup_item/skills
name = "Skills"
sort_order = 1
/datum/category_item/player_setup_item/skills/load_character(var/savefile/S)
S["skills"] >> pref.skills
S["used_skillpoints"] >> pref.used_skillpoints
S["skill_specialization"] >> pref.skill_specialization
/datum/category_item/player_setup_item/skills/save_character(var/savefile/S)
S["skills"] << pref.skills
S["used_skillpoints"] << pref.used_skillpoints
S["skill_specialization"] << pref.skill_specialization
/datum/category_item/player_setup_item/skills/sanitize_character()
if(SKILLS == null) setup_skills()
if(!pref.skills) pref.skills = list()
if(!pref.skills.len) pref.ZeroSkills()
if(pref.used_skillpoints < 0) pref.used_skillpoints = 0
/datum/category_item/player_setup_item/skills/content()
. += "<b>Select your Skills</b><br>"
. += "Current skill level: <b>[pref.GetSkillClass(pref.used_skillpoints)]</b> ([pref.used_skillpoints])<br>"
. += "<a href='?src=\ref[src];preconfigured=1'>Use preconfigured skillset</a><br>"
. += "<table>"
for(var/V in SKILLS)
. += "<tr><th colspan = 5><b>[V]</b>"
. += "</th></tr>"
for(var/datum/skill/S in SKILLS[V])
var/level = pref.skills[S.ID]
. += "<tr style='text-align:left;'>"
. += "<th><a href='?src=\ref[src];skillinfo=\ref[S]'>[S.name]</a></th>"
. += "<th><a href='?src=\ref[src];setskill=\ref[S];newvalue=[SKILL_NONE]'><font color=[(level == SKILL_NONE) ? "red" : "black"]>\[Untrained\]</font></a></th>"
// secondary skills don't have an amateur level
if(S.secondary)
. += "<th></th>"
else
. += "<th><a href='?src=\ref[src];setskill=\ref[S];newvalue=[SKILL_BASIC]'><font color=[(level == SKILL_BASIC) ? "red" : "black"]>\[Amateur\]</font></a></th>"
. += "<th><a href='?src=\ref[src];setskill=\ref[S];newvalue=[SKILL_ADEPT]'><font color=[(level == SKILL_ADEPT) ? "red" : "black"]>\[Trained\]</font></a></th>"
. += "<th><a href='?src=\ref[src];setskill=\ref[S];newvalue=[SKILL_EXPERT]'><font color=[(level == SKILL_EXPERT) ? "red" : "black"]>\[Professional\]</font></a></th>"
. += "</tr>"
. += "</table>"
/datum/category_item/player_setup_item/skills/OnTopic(href, href_list, user)
if(href_list["skillinfo"])
var/datum/skill/S = locate(href_list["skillinfo"])
var/HTML = "<b>[S.name]</b><br>[S.desc]"
user << browse(HTML, "window=\ref[user]skillinfo")
return TOPIC_HANDLED
else if(href_list["setskill"])
var/datum/skill/S = locate(href_list["setskill"])
var/value = text2num(href_list["newvalue"])
pref.skills[S.ID] = value
pref.CalculateSkillPoints()
return TOPIC_REFRESH
else if(href_list["preconfigured"])
var/selected = input(user, "Select a skillset", "Skillset") as null|anything in SKILL_PRE
if(!selected && !CanUseTopic(user)) return
pref.ZeroSkills(1)
for(var/V in SKILL_PRE[selected])
if(V == "field")
pref.skill_specialization = SKILL_PRE[selected]["field"]
continue
pref.skills[V] = SKILL_PRE[selected][V]
pref.CalculateSkillPoints()
return TOPIC_REFRESH
else if(href_list["setspecialization"])
pref.skill_specialization = href_list["setspecialization"]
pref.CalculateSkillPoints()
return TOPIC_REFRESH
return ..()
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -342,18 +342,17 @@ var/global/list/gear_datums = list()
allowed_roles = list("Security Officer","Head of Security","Warden")
/datum/gear/thugshades
display_name = "Sunglasses, Fat"
display_name = "Sunglasses, Fat (Security)"
path = /obj/item/clothing/glasses/sunglasses/big
cost = 1
slot = slot_glasses
allowed_roles = list("Security Officer","Head of Security","Warden","Detective","Internal Affairs Agent","Quartermaster","Head of Personnel","Captain")
allowed_roles = list("Security Officer","Head of Security","Warden")
/datum/gear/prescriptionsun
display_name = "sunglasses, presciption"
path = /obj/item/clothing/glasses/sunglasses/prescription
cost = 2
slot = slot_glasses
allowed_roles = list("Security Officer","Head of Security","Warden","Detective","Internal Affairs Agent","Quartermaster","Head of Personnel","Captain")
// Mask
+294 -5
View File
@@ -47,7 +47,26 @@
save_character()
return 0
player_setup.load_preferences(S)
//general preferences
S["ooccolor"] >> ooccolor
S["lastchangelog"] >> lastchangelog
S["UI_style"] >> UI_style
S["be_special"] >> be_special
S["default_slot"] >> default_slot
S["toggles"] >> toggles
S["UI_style_color"] >> UI_style_color
S["UI_style_alpha"] >> UI_style_alpha
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
UI_style = sanitize_inlist(UI_style, all_ui_styles, initial(UI_style))
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))
default_slot = sanitize_integer(default_slot, 1, config.character_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color))
UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha))
return 1
/datum/preferences/proc/save_preferences()
@@ -57,7 +76,15 @@
S.cd = "/"
S["version"] << savefile_version
player_setup.save_preferences(S)
//general preferences
S["ooccolor"] << ooccolor
S["lastchangelog"] << lastchangelog
S["UI_style"] << UI_style
S["be_special"] << be_special
S["default_slot"] << default_slot
S["toggles"] << toggles
return 1
/datum/preferences/proc/load_character(slot)
@@ -73,7 +100,184 @@
S["default_slot"] << slot
S.cd = "/character[slot]"
player_setup.load_character(S)
//Character
S["OOC_Notes"] >> metadata
S["real_name"] >> real_name
S["name_is_always_random"] >> be_random_name
S["gender"] >> gender
S["age"] >> age
S["species"] >> species
S["spawnpoint"] >> spawnpoint
S["language"] >> alternate_languages
S["language_prefixes"] >> language_prefixes
if(isnull(alternate_languages))
alternate_languages = list()
if(isnull(language_prefixes) || !language_prefixes.len)
language_prefixes = config.language_prefixes.Copy()
if(!islist(alternate_languages))
if(client)
// Warn them that we (probably) just broke their languages
client << "<span class='danger'>Your current character slot's languages list has been updated from an old version, and may not be what you expect.</span>"
if(alternate_languages in all_languages)
alternate_languages = list(alternate_languages)
else
alternate_languages = list()
// try to give them their species language
var/datum/species/SP = all_species[species]
if(SP)
alternate_languages |= SP.language
alternate_languages |= SP.default_language
// remove the Galcom that most races have as default_language
alternate_languages -= "Galactic Common"
//colors to be consolidated into hex strings (requires some work with dna code)
S["hair_red"] >> r_hair
S["hair_green"] >> g_hair
S["hair_blue"] >> b_hair
S["facial_red"] >> r_facial
S["facial_green"] >> g_facial
S["facial_blue"] >> b_facial
S["skin_tone"] >> s_tone
S["skin_red"] >> r_skin
S["skin_green"] >> g_skin
S["skin_blue"] >> b_skin
S["hair_style_name"] >> h_style
S["facial_style_name"] >> f_style
S["eyes_red"] >> r_eyes
S["eyes_green"] >> g_eyes
S["eyes_blue"] >> b_eyes
S["underwear"] >> underwear
S["undershirt"] >> undershirt
S["socks"] >> socks
S["backbag"] >> backbag
S["b_type"] >> b_type
//Jobs
S["alternate_option"] >> alternate_option
S["job_civilian_high"] >> job_civilian_high
S["job_civilian_med"] >> job_civilian_med
S["job_civilian_low"] >> job_civilian_low
S["job_medsci_high"] >> job_medsci_high
S["job_medsci_med"] >> job_medsci_med
S["job_medsci_low"] >> job_medsci_low
S["job_engsec_high"] >> job_engsec_high
S["job_engsec_med"] >> job_engsec_med
S["job_engsec_low"] >> job_engsec_low
//Flavour Text
S["flavor_texts_general"] >> flavor_texts["general"]
S["flavor_texts_head"] >> flavor_texts["head"]
S["flavor_texts_face"] >> flavor_texts["face"]
S["flavor_texts_eyes"] >> flavor_texts["eyes"]
S["flavor_texts_torso"] >> flavor_texts["torso"]
S["flavor_texts_arms"] >> flavor_texts["arms"]
S["flavor_texts_hands"] >> flavor_texts["hands"]
S["flavor_texts_legs"] >> flavor_texts["legs"]
S["flavor_texts_feet"] >> flavor_texts["feet"]
//Flavour text for robots.
S["flavour_texts_robot_Default"] >> flavour_texts_robot["Default"]
for(var/module in robot_module_types)
S["flavour_texts_robot_[module]"] >> flavour_texts_robot[module]
//Miscellaneous
S["med_record"] >> med_record
S["sec_record"] >> sec_record
S["gen_record"] >> gen_record
S["be_special"] >> be_special
S["disabilities"] >> disabilities
S["player_alt_titles"] >> player_alt_titles
S["used_skillpoints"] >> used_skillpoints
S["skills"] >> skills
S["skill_specialization"] >> skill_specialization
S["organ_data"] >> organ_data
S["rlimb_data"] >> rlimb_data
S["gear"] >> gear
S["home_system"] >> home_system
S["citizenship"] >> citizenship
S["faction"] >> faction
S["religion"] >> religion
S["nanotrasen_relation"] >> nanotrasen_relation
//S["skin_style"] >> skin_style
S["uplinklocation"] >> uplinklocation
S["exploit_record"] >> exploit_record
S["UI_style_color"] << UI_style_color
S["UI_style_alpha"] << UI_style_alpha
//Sanitize
metadata = sanitize_text(metadata, initial(metadata))
real_name = sanitizeName(real_name)
if(isnull(species) || !(species in playable_species))
species = "Human"
if(isnum(underwear))
var/list/undies = gender == MALE ? underwear_m : underwear_f
underwear = undies[undies[underwear]]
if(isnum(undershirt))
undershirt = undershirt_t[undershirt_t[undershirt]]
if(isnum(socks))
socks = socks_t[socks_t[socks]]
if(isnull(alternate_languages)) alternate_languages = list()
if(isnull(spawnpoint)) spawnpoint = "Arrivals Shuttle"
if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation)
if(!real_name) real_name = random_name(gender)
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
gender = sanitize_gender(gender)
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair))
g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair))
b_hair = sanitize_integer(b_hair, 0, 255, initial(b_hair))
r_facial = sanitize_integer(r_facial, 0, 255, initial(r_facial))
g_facial = sanitize_integer(g_facial, 0, 255, initial(g_facial))
b_facial = sanitize_integer(b_facial, 0, 255, initial(b_facial))
s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone))
r_skin = sanitize_integer(r_skin, 0, 255, initial(r_skin))
g_skin = sanitize_integer(g_skin, 0, 255, initial(g_skin))
b_skin = sanitize_integer(b_skin, 0, 255, initial(b_skin))
h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style))
f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style))
r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes))
g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes))
b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes))
backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag))
b_type = sanitize_text(b_type, initial(b_type))
alternate_option = sanitize_integer(alternate_option, 0, 2, initial(alternate_option))
job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high))
job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med))
job_civilian_low = sanitize_integer(job_civilian_low, 0, 65535, initial(job_civilian_low))
job_medsci_high = sanitize_integer(job_medsci_high, 0, 65535, initial(job_medsci_high))
job_medsci_med = sanitize_integer(job_medsci_med, 0, 65535, initial(job_medsci_med))
job_medsci_low = sanitize_integer(job_medsci_low, 0, 65535, initial(job_medsci_low))
job_engsec_high = sanitize_integer(job_engsec_high, 0, 65535, initial(job_engsec_high))
job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med))
job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low))
if(!skills) skills = list()
if(!used_skillpoints) used_skillpoints= 0
if(isnull(disabilities)) disabilities = 0
if(!player_alt_titles) player_alt_titles = new()
if(!organ_data) src.organ_data = list()
if(!rlimb_data) src.rlimb_data = list()
if(!gear) src.gear = list()
//if(!skin_style) skin_style = "Default"
if(!home_system) home_system = "Unset"
if(!citizenship) citizenship = "None"
if(!faction) faction = "None"
if(!religion) religion = "None"
return 1
/datum/preferences/proc/save_character()
@@ -82,9 +286,94 @@
if(!S) return 0
S.cd = "/character[default_slot]"
player_setup.save_character(S)
//Character
S["OOC_Notes"] << metadata
S["real_name"] << real_name
S["name_is_always_random"] << be_random_name
S["gender"] << gender
S["age"] << age
S["species"] << species
S["language"] << alternate_languages
S["language_prefixes"] << language_prefixes
S["hair_red"] << r_hair
S["hair_green"] << g_hair
S["hair_blue"] << b_hair
S["facial_red"] << r_facial
S["facial_green"] << g_facial
S["facial_blue"] << b_facial
S["skin_tone"] << s_tone
S["skin_red"] << r_skin
S["skin_green"] << g_skin
S["skin_blue"] << b_skin
S["hair_style_name"] << h_style
S["facial_style_name"] << f_style
S["eyes_red"] << r_eyes
S["eyes_green"] << g_eyes
S["eyes_blue"] << b_eyes
S["underwear"] << underwear
S["undershirt"] << undershirt
S["socks"] << socks
S["backbag"] << backbag
S["b_type"] << b_type
S["spawnpoint"] << spawnpoint
//Jobs
S["alternate_option"] << alternate_option
S["job_civilian_high"] << job_civilian_high
S["job_civilian_med"] << job_civilian_med
S["job_civilian_low"] << job_civilian_low
S["job_medsci_high"] << job_medsci_high
S["job_medsci_med"] << job_medsci_med
S["job_medsci_low"] << job_medsci_low
S["job_engsec_high"] << job_engsec_high
S["job_engsec_med"] << job_engsec_med
S["job_engsec_low"] << job_engsec_low
//Flavour Text
S["flavor_texts_general"] << flavor_texts["general"]
S["flavor_texts_head"] << flavor_texts["head"]
S["flavor_texts_face"] << flavor_texts["face"]
S["flavor_texts_eyes"] << flavor_texts["eyes"]
S["flavor_texts_torso"] << flavor_texts["torso"]
S["flavor_texts_arms"] << flavor_texts["arms"]
S["flavor_texts_hands"] << flavor_texts["hands"]
S["flavor_texts_legs"] << flavor_texts["legs"]
S["flavor_texts_feet"] << flavor_texts["feet"]
//Flavour text for robots.
S["flavour_texts_robot_Default"] << flavour_texts_robot["Default"]
for(var/module in robot_module_types)
S["flavour_texts_robot_[module]"] << flavour_texts_robot[module]
//Miscellaneous
S["med_record"] << med_record
S["sec_record"] << sec_record
S["gen_record"] << gen_record
S["player_alt_titles"] << player_alt_titles
S["be_special"] << be_special
S["disabilities"] << disabilities
S["used_skillpoints"] << used_skillpoints
S["skills"] << skills
S["skill_specialization"] << skill_specialization
S["organ_data"] << organ_data
S["rlimb_data"] << rlimb_data
S["gear"] << gear
S["home_system"] << home_system
S["citizenship"] << citizenship
S["faction"] << faction
S["religion"] << religion
S["nanotrasen_relation"] << nanotrasen_relation
//S["skin_style"] << skin_style
S["uplinklocation"] << uplinklocation
S["exploit_record"] << exploit_record
S["UI_style_color"] << UI_style_color
S["UI_style_alpha"] << UI_style_alpha
return 1
#undef SAVEFILE_VERSION_MAX
#undef SAVEFILE_VERSION_MIN
#undef SAVEFILE_VERSION_MIN
+1 -3
View File
@@ -1,9 +1,7 @@
/obj/item/clothing
name = "clothing"
siemens_coefficient = 0.9
var/flash_protection = FLASH_PROTECTION_NONE // Sets the item's level of flash protection.
var/tint = TINT_NONE // Sets the item's level of visual impairment tint.
var/list/species_restricted = null //Only these species can wear this kit.
var/list/species_restricted = null //Only these species can wear this kit.
/*
Sprites used when the clothing item is refit. This is done by setting icon_override.
+3 -17
View File
@@ -12,7 +12,6 @@
var/active = 1
var/activation_sound = 'sound/items/goggles_charge.ogg'
var/obj/screen/overlay = null
var/obj/item/clothing/glasses/hud/hud = null // Hud glasses, if any
/obj/item/clothing/glasses/attack_self(mob/user)
if(toggleable)
@@ -20,8 +19,6 @@
active = 0
icon_state = off_state
user.update_inv_glasses()
flash_protection = FLASH_PROTECTION_NONE
tint = TINT_NONE
usr << "You deactivate the optical matrix on the [src]."
else
active = 1
@@ -29,8 +26,6 @@
user.update_inv_glasses()
if(activation_sound)
usr << activation_sound
flash_protection = initial(flash_protection)
tint = initial(tint)
usr << "You activate the optical matrix on the [src]."
user.update_action_buttons()
@@ -109,7 +104,7 @@
item_state = "glasses"
prescription = 1
body_parts_covered = 0
/obj/item/clothing/glasses/regular/scanners
name = "Scanning Goggles"
desc = "A very oddly shaped pair of goggles with bits of wire poking out the sides. A soft humming sound emanates from it."
@@ -141,7 +136,6 @@
icon_state = "sun"
item_state = "sunglasses"
darkness_view = -1
flash_protection = FLASH_PROTECTION_MODERATE
/obj/item/clothing/glasses/welding
name = "welding goggles"
@@ -150,8 +144,6 @@
item_state = "welding-g"
action_button_name = "Flip Welding Goggles"
var/up = 0
flash_protection = FLASH_PROTECTION_MAJOR
tint = TINT_HEAVY
/obj/item/clothing/glasses/welding/attack_self()
toggle()
@@ -168,16 +160,12 @@
flags_inv |= HIDEEYES
body_parts_covered |= EYES
icon_state = initial(icon_state)
flash_protection = initial(flash_protection)
tint = initial(tint)
usr << "You flip \the [src] down to protect your eyes."
else
src.up = !src.up
flags_inv &= ~HIDEEYES
body_parts_covered &= ~EYES
icon_state = "[initial(icon_state)]up"
flash_protection = FLASH_PROTECTION_NONE
tint = TINT_NONE
usr << "You push \the [src] up out of your face."
update_clothing_icon()
usr.update_action_buttons()
@@ -187,14 +175,13 @@
desc = "Welding goggles made from more expensive materials, strangely smells like potatoes."
icon_state = "rwelding-g"
item_state = "rwelding-g"
tint = TINT_MODERATE
/obj/item/clothing/glasses/sunglasses/blindfold
name = "blindfold"
desc = "Covers the eyes, preventing sight."
icon_state = "blindfold"
item_state = "blindfold"
tint = TINT_BLIND
//vision_flags = BLIND // This flag is only supposed to be used if it causes permanent blindness, not temporary because of glasses
/obj/item/clothing/glasses/sunglasses/prescription
name = "prescription sunglasses"
@@ -209,6 +196,7 @@
name = "HUDSunglasses"
desc = "Sunglasses with a HUD."
icon_state = "sunhud"
var/obj/item/clothing/glasses/hud/security/hud = null
New()
..()
@@ -228,8 +216,6 @@
origin_tech = list(TECH_MAGNET = 3)
toggleable = 1
vision_flags = SEE_MOBS
see_invisible = SEE_INVISIBLE_NOLIGHTING
flash_protection = FLASH_PROTECTION_REDUCED
emp_act(severity)
if(istype(src.loc, /mob/living/carbon/human))
+3 -5
View File
@@ -5,12 +5,10 @@
origin_tech = list(TECH_MAGNET = 3, TECH_BIO = 2)
var/list/icon/current = list() //the current hud icons
/obj/item/clothing/glasses/proc/process_hud(var/mob/M)
if(hud)
hud.process_hud(M)
proc
process_hud(var/mob/M) return
/obj/item/clothing/glasses/hud/process_hud(var/mob/M)
return
/obj/item/clothing/glasses/hud/health
name = "Health Scanner HUD"
@@ -28,8 +28,6 @@
siemens_coefficient = 0.9
w_class = 3
var/base_state
flash_protection = FLASH_PROTECTION_MAJOR
tint = TINT_HEAVY
/obj/item/clothing/head/welding/attack_self()
if(!base_state)
@@ -47,15 +45,11 @@
src.up = !src.up
body_parts_covered |= (EYES|FACE)
flags_inv |= (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE)
flash_protection = initial(flash_protection)
tint = initial(tint)
icon_state = base_state
usr << "You flip the [src] down to protect your eyes."
else
src.up = !src.up
body_parts_covered &= ~(EYES|FACE)
flash_protection = FLASH_PROTECTION_NONE
tint = TINT_NONE
flags_inv &= ~(HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE)
icon_state = "[base_state]up"
usr << "You push the [src] up out of your face."
@@ -100,7 +100,7 @@
icon_state = "emergencyhelm"
item_state = "emergencyhelm"
desc = "A simple helmet with a built in light, smells like mothballs."
flash_protection = FLASH_PROTECTION_NONE
/obj/item/clothing/suit/space/emergency
name = "Emergency Softsuit"
@@ -40,7 +40,7 @@
airtight = 0
seal_delay = 5 //not being vaccum-proof has an upside I guess
helm_type = /obj/item/clothing/head/lightrig/hacker
chest_type = /obj/item/clothing/suit/lightrig/hacker
glove_type = /obj/item/clothing/gloves/lightrig/hacker
@@ -20,7 +20,6 @@
min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE
siemens_coefficient = 0.9
species_restricted = list("exclude","Diona", "Xenomorph")
flash_protection = FLASH_PROTECTION_MAJOR
var/obj/machinery/camera/camera
var/list/camera_networks
@@ -38,8 +38,6 @@
/obj/item/clothing/accessory/badge/attack(mob/living/carbon/human/M, mob/living/user)
if(isliving(user))
user.visible_message("<span class='danger'>[user] invades [M]'s personal space, thrusting [src] into their face insistently.</span>","<span class='danger'>You invade [M]'s personal space, thrusting [src] into their face insistently.</span>")
user.do_attack_animation(M)
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //to prevent spam
//.Holobadges.
/obj/item/clothing/accessory/badge/holo
+2 -4
View File
@@ -1,5 +1,6 @@
/datum/event/blob
announceWhen = 12
endWhen = 120
var/obj/effect/blob/core/Blob
@@ -7,13 +8,10 @@
level_seven_announcement()
/datum/event/blob/start()
var/turf/T = pick_area_turf(/area/maintenance, list(/proc/is_station_turf, /proc/not_turf_contains_dense_objects))
var/turf/T = pick(blobstart)
if(!T)
log_and_message_admins("Blob failed to find a viable turf.")
kill()
return
log_and_message_admins_with_location("Event: Blob spawned at \the [get_area(T)] ([T.x],[T.y],[T.z])", T.x, T.y, T.z)
Blob = new /obj/effect/blob/core(T)
for(var/i = 1; i < rand(3, 4), i++)
Blob.process()
+26 -54
View File
@@ -6,13 +6,10 @@
use_power = 1
active_power_usage = 8000 //8kW for the scenery + 500W per holoitem
circuit = /obj/item/weapon/circuitboard/holodeckcontrol
var/item_power_usage = 500
var/area/linkedholodeck = null
var/linkedholodeck_area
var/area/target = null
var/active = 0
var/list/holographic_objs = list()
var/list/holographic_mobs = list()
@@ -21,39 +18,34 @@
var/mob/last_to_emag = null
var/last_change = 0
var/last_gravity_change = 0
var/list/supported_programs
var/list/restricted_programs
/obj/machinery/computer/HolodeckControl/New()
..()
linkedholodeck = locate(linkedholodeck_area)
supported_programs = list()
restricted_programs = list()
var/list/supported_programs = list( \
"Empty Court" = "emptycourt", \
"Basketball Court" = "basketball", \
"Thunderdome Court" = "thunderdomecourt", \
"Boxing Ring"="boxingcourt", \
"Beach" = "beach", \
"Desert" = "desert", \
"Space" = "space", \
"Picnic Area" = "picnicarea", \
"Snow Field" = "snowfield", \
"Theatre" = "theatre", \
"Meeting Hall" = "meetinghall", \
"Courtroom" = "courtroom" \
)
var/list/restricted_programs = list("Atmospheric Burn Simulation" = "burntest", "Wildlife Simulation" = "wildlifecarp")
/obj/machinery/computer/HolodeckControl/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
/obj/machinery/computer/HolodeckControl/attack_hand(var/mob/user as mob)
if(..())
return 1
return
user.set_machine(src)
var/dat
dat += "<B>Holodeck Control System</B><BR>"
dat += "<HR>Current Loaded Programs:<BR>"
if(!linkedholodeck)
dat += "<span class='danger'>Warning: Unable to locate holodeck.<br></span>"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
if(!supported_programs.len)
dat += "<span class='danger'>Warning: No supported holo-programs loaded.<br></span>"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
for(var/prog in supported_programs)
dat += "<A href='?src=\ref[src];program=[supported_programs[prog]]'>([prog])</A><BR>"
@@ -91,8 +83,10 @@
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
/obj/machinery/computer/HolodeckControl/Topic(href, href_list)
if(..())
return 1
@@ -138,9 +132,8 @@
user << "Warning. Automatic shutoff and derezing protocols have been corrupted. Please call [company_name] maintenance and do not use the simulator."
log_game("[key_name(usr)] emagged the Holodeck Control Computer")
return 1
src.updateUsrDialog()
else
..()
src.updateUsrDialog()
return
/obj/machinery/computer/HolodeckControl/proc/update_projections()
if (safety_disabled)
@@ -157,6 +150,10 @@
if (last_to_emag)
C.friends = list(last_to_emag)
/obj/machinery/computer/HolodeckControl/New()
..()
linkedholodeck = locate(/area/holodeck/alphadeck)
//This could all be done better, but it works for now.
/obj/machinery/computer/HolodeckControl/Destroy()
emergencyShutdown()
@@ -336,28 +333,3 @@
active = 0
use_power = 1
/obj/machinery/computer/HolodeckControl/Exodus
linkedholodeck_area = /area/holodeck/alphadeck
/obj/machinery/computer/HolodeckControl/Exodus/New()
..()
supported_programs = list(
"Empty Court" = "emptycourt",
"Basketball Court" = "basketball",
"Thunderdome Court" = "thunderdomecourt",
"Boxing Ring" = "boxingcourt",
"Beach" = "beach",
"Desert" = "desert",
"Space" = "space",
"Picnic Area" = "picnicarea",
"Snow Field" = "snowfield",
"Theatre" = "theatre",
"Meeting Hall" = "meetinghall",
"Courtroom" = "courtroom"
)
restricted_programs = list(
"Atmospheric Burn Simulation" = "burntest",
"Wildlife Simulation" = "wildlifecarp"
)
+3
View File
@@ -263,6 +263,9 @@
return 1
return 0
/obj/item/weapon/holo/esword/attack(target as mob, mob/user as mob)
..()
/obj/item/weapon/holo/esword/New()
item_color = pick("red","blue","green","purple")
+60 -16
View File
@@ -234,22 +234,66 @@
return
..()
/obj/item/weapon/reagent_containers/food/snacks/grown/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
. = ..()
if(seed && seed.get_trait(TRAIT_STINGS))
if(!reagents || reagents.total_volume <= 0)
return
reagents.remove_any(rand(1,3))
seed.thrown_at(src, target)
sleep(-1)
if(!src)
return
if(prob(35))
if(user)
user << "<span class='danger'>\The [src] has fallen to bits.</span>"
user.drop_from_inventory(src)
qdel(src)
/obj/item/weapon/reagent_containers/food/snacks/grown/attack(var/mob/living/carbon/M, var/mob/user, var/def_zone)
if(user == M)
return ..()
if(user.a_intent == I_HURT)
// This is being copypasted here because reagent_containers (WHY DOES FOOD DESCEND FROM THAT) overrides it completely.
// TODO: refactor all food paths to be less horrible and difficult to work with in this respect. ~Z
if(!istype(M) || (can_operate(M) && do_surgery(M,user,src))) return 0
user.lastattacked = M
M.lastattacker = user
user.attack_log += "\[[time_stamp()]\]<font color='red'> Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
var/hit = H.attacked_by(src, user, def_zone)
if(hit && hitsound)
playsound(loc, hitsound, 50, 1, -1)
return hit
else
if(attack_verb.len)
user.visible_message("<span class='danger'>[M] has been [pick(attack_verb)] with [src] by [user]!</span>")
else
user.visible_message("<span class='danger'>[M] has been attacked with [src] by [user]!</span>")
if (hitsound)
playsound(loc, hitsound, 50, 1, -1)
switch(damtype)
if("brute")
M.take_organ_damage(force)
if(prob(33))
var/turf/simulated/location = get_turf(M)
if(istype(location)) location.add_blood_floor(M)
if("fire")
if (!(COLD_RESISTANCE in M.mutations))
M.take_organ_damage(0, force)
M.updatehealth()
if(seed && seed.get_trait(TRAIT_STINGS))
if(!reagents || reagents.total_volume <= 0)
return
reagents.remove_any(rand(1,3))
seed.thrown_at(src,M)
sleep(-1)
if(!src)
return
if(prob(35))
if(user)
user << "<span class='danger'>\The [src] has fallen to bits.</span>"
user.drop_from_inventory(src)
qdel(src)
add_fingerprint(user)
return 1
else
..()
/obj/item/weapon/reagent_containers/food/snacks/grown/attack_self(mob/user as mob)
@@ -3,8 +3,15 @@
/proc/spacevine_infestation(var/potency_min=70, var/potency_max=100, var/maturation_min=5, var/maturation_max=15)
spawn() //to stop the secrets panel hanging
var/turf/T = pick_area_turf(/area/hallway, list(/proc/is_station_turf, /proc/not_turf_contains_dense_objects))
if(T)
var/list/turf/simulated/floor/turfs = list() //list of all the empty floor turfs in the hallway areas
for(var/areapath in typesof(/area/hallway))
var/area/A = locate(areapath)
for(var/turf/simulated/floor/F in A.contents)
if(turf_clear(F))
turfs += F
if(turfs.len) //Pick a turf to spawn at if we can
var/turf/simulated/floor/T = pick(turfs)
var/datum/seed/seed = plant_controller.create_random_seed(1)
seed.set_trait(TRAIT_SPREAD,2) // So it will function properly as vines.
seed.set_trait(TRAIT_POTENCY,rand(potency_min, potency_max)) // 70-100 potency will help guarantee a wide spread and powerful effects.
@@ -16,9 +23,9 @@
vine.mature_time = 0
vine.process()
log_and_message_admins_with_location("Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])", T.x, T.y, T.z)
message_admins("<span class='notice'>Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])</span>")
return
log_and_message_admins("<span class='notice'>Event: Spacevines failed to find a viable turf.</span>")
message_admins("<span class='notice'>Event: Spacevines failed to find a viable turf.</span>")
/obj/effect/dead_plant
anchored = 1
@@ -125,7 +132,7 @@
update_icon()
plant_controller.add_plant(src)
// Some plants eat through plating.
if(islist(seed.chems) && !isnull(seed.chems["pacid"]))
if(!isnull(seed.chems["pacid"]))
var/turf/T = get_turf(src)
T.ex_act(prob(80) ? 3 : 2)
@@ -181,12 +188,12 @@
icon_state = "[seed.get_trait(TRAIT_PLANT_ICON)]-[growth]"
if(growth>2 && growth == max_growth)
layer = (seed && seed.force_layer) ? seed.force_layer : 5
layer = 5
opacity = 1
if(islist(seed.chems) && !isnull(seed.chems["woodpulp"]))
if(!isnull(seed.chems["woodpulp"]))
density = 1
else
layer = (seed && seed.force_layer) ? seed.force_layer : 5
layer = 3
density = 0
/obj/effect/plant/proc/calc_dir()
@@ -48,6 +48,20 @@
toxicity = 8
pest_kill_str = 7
/obj/item/weapon/material/minihoe // -- Numbers
name = "mini hoe"
desc = "It's used for removing weeds or scratching your back."
icon = 'icons/obj/weapons.dmi'
icon_state = "hoe"
item_state = "hoe"
flags = CONDUCT | NOBLUDGEON
force = 5.0
throwforce = 7.0
w_class = 2.0
matter = list(DEFAULT_WALL_MATERIAL = 50)
attack_verb = list("slashed", "sliced", "cut", "clawed")
// *************************************
// Weedkiller defines for hydroponics
// *************************************
-1
View File
@@ -256,7 +256,6 @@
user.visible_message("<span class='notice'>You open up the book and show it to [M]. </span>", \
"<span class='notice'> [user] opens up a book and shows it to [M]. </span>")
M << browse("<TT><I>Penned by [author].</I></TT> <BR>" + "[dat]", "window=book")
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //to prevent spam
/*
+2 -3
View File
@@ -65,10 +65,9 @@
var/obj/item/stack/material/M = S
if(!istype(M) || material.name != M.material.name)
return 0
var/transfer = ..(S,tamount,1)
..(S,tamount,1)
if(src) update_strings()
if(M) M.update_strings()
return transfer
/obj/item/stack/material/attack_self(var/mob/user)
if(!material.build_windows(user, src))
@@ -208,4 +207,4 @@
desc = "This sheet is special platinum-glass alloy designed to withstand large temperatures. It is reinforced with few rods."
singular_name = "reinforced borosilicate glass sheet"
icon_state = "sheet-phoronrglass"
default_type = "reinforced borosilicate glass"
default_type = "reinforced borosilicate glass"
+2
View File
@@ -127,6 +127,8 @@ var/list/name_to_material
var/obj/item/stack/S = new rod_product(get_turf(user))
S.add_fingerprint(user)
S.add_to_stacks(user)
if(!(user.l_hand && user.r_hand))
user.put_in_hands(S)
/material/proc/build_wired_product(var/mob/user, var/obj/item/stack/used_stack, var/obj/item/stack/target_stack)
if(!wire_product)
+7 -10
View File
@@ -91,14 +91,11 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
/mob/dead/observer/Topic(href, href_list)
if (href_list["track"])
if(istype(href_list["track"],/mob))
var/mob/target = locate(href_list["track"]) in mob_list
if(target)
ManualFollow(target)
else
var/atom/target = locate(href_list["track"])
if(istype(target))
ManualFollow(target)
var/mob/target = locate(href_list["track"]) in mob_list
if(target)
ManualFollow(target)
/mob/dead/attackby(obj/item/W, mob/user)
if(istype(W,/obj/item/weapon/book/tome))
@@ -152,7 +149,7 @@ Works together with spawning an observer, noted above.
if(key)
var/mob/dead/observer/ghost = new(src) //Transfer safety to observer spawning proc.
ghost.can_reenter_corpse = can_reenter_corpse
ghost.timeofdeath = src.stat == DEAD ? src.timeofdeath : world.time
ghost.timeofdeath = src.timeofdeath //BS12 EDIT
ghost.key = key
if(ghost.client && !ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
@@ -323,7 +320,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(following && following == target)
return
following = target
src << "<span class='notice'>Now following \the [target]</span>"
src << "<span class='notice'>Now following [target]</span>"
if(ismob(target))
forceMove(get_turf(target))
var/mob/M = target
-6
View File
@@ -212,10 +212,4 @@
else
return ..()
/proc/transfer_languages(var/mob/source, var/mob/target, var/except_flags)
for(var/datum/language/L in source.languages)
if(L.flags & except_flags)
continue
target.add_language(L.name)
#undef SCRAMBLE_CACHE_LEN
+2
View File
@@ -123,3 +123,5 @@
/mob/living/bot/proc/explode()
qdel(src)
/mob/living/bot/attack_throat()
return
@@ -11,5 +11,4 @@
/mob/living/carbon/alien/larva/New()
..()
add_language("Xenomorph") //Bonus language.
internal_organs |= new /obj/item/organ/xenos/hivenode(src)
create_reagents(100)
internal_organs |= new /obj/item/organ/xenos/hivenode(src)
@@ -1,34 +1,12 @@
#define MIN_LARVA_BLOOD_DRINK 0.5
//Larvae regenerate health and nutrition from plasma and alien weeds.
/mob/living/carbon/alien/larva/handle_environment(var/datum/gas_mixture/environment)
if(!environment) return
var/turf/T = get_turf(src)
var/obj/effect/plant/plant = locate() in T
if(environment.gas["phoron"] > 0 || (plant && plant.seed.type == /datum/seed/xenomorph))
if(environment.gas["phoron"] > 0 || (T && locate(/obj/effect/alien/weeds) in T.contents))
update_progression()
adjustBruteLoss(-1)
adjustFireLoss(-1)
adjustToxLoss(-1)
adjustOxyLoss(-1)
// Maybe not the -best- place but it's semiappropriate and fitting.
// Drink the blood of your host!
/mob/living/carbon/alien/larva/handle_chemicals_in_body()
if(!loc)
return
if(!istype(loc, /obj/item/weapon/holder))
return
var/mob/living/carbon/human/M = loc.loc //ergh, replace with a flag sometime
if(!istype(M))
return
if(M.vessel.total_volume > 0)
M.vessel.trans_to(src,min(M.vessel.total_volume,MIN_LARVA_BLOOD_DRINK))
update_progression()
else
src << "<span class='danger'>This host is depleted of blood...</span>"
leave_host()
#undef MIN_LARVA_BLOOD_DRINK
adjustOxyLoss(-1)
@@ -1,111 +0,0 @@
/mob/living/carbon/alien/larva/proc/check_can_infest(var/mob/living/M)
if(!src)
return 0
if(!istype(loc, /turf))
src << "<span class='danger'>You cannot infest a target in your current position.</span>"
return 0
if(incapacitated())
src << "<span class='danger'>You cannot infest a target in your current state.</span>"
return 0
if(!M)
return 1
if(!M.lying)
src << "<span class='danger'>\The [M] is not prone.</span>"
return 0
if(!(src.Adjacent(M)))
src << "<span class='danger'>\The [M] is not in range.</span>"
return 0
return 1
/mob/living/carbon/alien/larva/verb/attach_host()
set name = "Attach to host"
set desc = "Burrow into a prone victim and begin drinking their blood."
set category = "Abilities"
if(!check_can_infest())
return
var/list/choices = list()
for(var/mob/living/carbon/human/H in view(1,src))
if(isxenomorph(H))
continue
if(src.Adjacent(H) && H.lying)
choices += H
if(!choices.len)
src << "<span class='danger'>There are no viable hosts within range.</span>"
return
var/mob/living/carbon/human/H = input(src,"Who do you wish to infest?") as null|anything in choices
if(!H || !src || !H.lying) return
visible_message("<span class='danger'>\The [src] begins questing blindly towards \the [H]'s warm flesh...</span>")
if(!do_after(src,30))
return
if(!check_can_infest(H))
return
var/obj/item/organ/external/E = pick(H.organs)
src << "<span class='danger'>You burrow deeply into \the [H]'s [E.name]!</span>"
var/obj/item/weapon/holder/holder = new (loc)
src.loc = holder
holder.name = src.name
E.embed(holder,0,"\The [src] burrows deeply into \the [H]'s [E.name]!")
/mob/living/carbon/alien/larva/verb/release_host()
set category = "Abilities"
set name = "Release Host"
set desc = "Release your host."
if(incapacitated())
src << "You cannot leave your host in your current state."
return
if(!loc || !loc.loc)
src << "You are not inside a host."
return
var/mob/living/carbon/human/H = loc.loc
if(!istype(H))
src << "You are not inside a host."
return
src << "<span class='danger'>You begin writhing your way free of \the [H]'s flesh...</span>"
if(!do_after(src, 30))
return
if(!H || !src)
return
leave_host()
/mob/living/carbon/alien/larva/proc/leave_host()
if(!loc || !loc.loc)
src << "You are not inside a host."
return
var/mob/living/carbon/human/H = loc.loc
if(!istype(H))
src << "You are not inside a host."
return
var/obj/item/weapon/holder/holder = loc
var/obj/item/organ/external/affected
if(istype(holder))
for(var/obj/item/organ/external/organ in H.organs) //Grab the organ holding the implant.
for(var/obj/item/O in organ.implants)
if(O == holder)
affected = organ
break
affected.implants -= holder
holder.loc = get_turf(holder)
else
src.loc = get_turf(src)
if(affected)
src << "<span class='danger'>You crawl out of \the [H]'s [affected.name] and plop to the ground.</span>"
else
src << "<span class='danger'>You plop to the ground.</span>"
+3 -6
View File
@@ -9,7 +9,8 @@
..()
if (stat != DEAD && can_progress())
if (stat != DEAD) //still breathing
// GROW!
update_progression()
blinded = null
@@ -17,10 +18,6 @@
//Status updates, death etc.
update_icons()
/mob/living/carbon/alien/proc/can_progress()
return 1
/mob/living/carbon/alien/handle_mutations_and_radiation()
// Currently both Dionaea and larvae like to eat radiation, so I'm defining the
@@ -161,7 +158,7 @@
adjustFireLoss((environment.temperature - (T0C+66))/5) // Might be too high, check in testing.
if (fire) fire.icon_state = "fire2"
if(prob(20))
src << "<span class='danger'>You feel a searing heat!</span>"
src << "\red You feel a searing heat!"
else
if (fire) fire.icon_state = "fire0"
@@ -1,7 +1,7 @@
/mob/living/carbon/alien/verb/evolve()
set name = "Moult"
set desc = "Moult your skin and become an adult."
set name = "Evolve"
set desc = "Evolve into your adult form."
set category = "Abilities"
if(stat != CONSCIOUS)
@@ -12,11 +12,11 @@
return
if(handcuffed || legcuffed)
src << "<span class='warning'>You cannot evolve when you are cuffed.</span>"
src << "\red You cannot evolve when you are cuffed."
return
if(amount_grown < max_grown)
src << "<span class='warning'>You are not fully grown.</span>"
src << "\red You are not fully grown."
return
// confirm_evolution() handles choices and other specific requirements.
@@ -27,7 +27,6 @@
var/mob/living/carbon/human/adult = new adult_form(get_turf(src))
adult.set_species(new_species)
show_evolution_blurb()
// TODO: drop a moulted skin. Ew.
if(mind)
mind.transfer_to(adult)
+4 -6
View File
@@ -54,7 +54,7 @@
breath = environment.remove_volume(volume_needed)
handle_chemical_smoke(environment) //handle chemical smoke while we're at it
if(breath && breath.total_moles)
if(breath)
//handle mask filtering
if(istype(wear_mask, /obj/item/clothing/mask) && breath)
var/obj/item/clothing/mask/M = wear_mask
@@ -65,15 +65,13 @@
//Handle possble chem smoke effect
/mob/living/carbon/proc/handle_chemical_smoke(var/datum/gas_mixture/environment)
if(species && environment.return_pressure() < species.breath_pressure/5)
return //pressure is too low to even breathe in.
if(wear_mask && (wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT))
if(wear_mask && (wear_mask.item_flags & BLOCK_GAS_SMOKE_EFFECT))
return
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
if(smoke.reagents.total_volume)
smoke.reagents.trans_to_mob(src, 5, CHEM_INGEST, copy = 1)
smoke.reagents.trans_to_mob(src, 5, CHEM_BLOOD, copy = 1)
smoke.reagents.trans_to_mob(src, 10, CHEM_INGEST, copy = 1)
//maybe check air pressure here or something to see if breathing in smoke is even possible.
// I dunno, maybe the reagents enter the blood stream through the lungs?
break // If they breathe in the nasty stuff once, no need to continue checking
@@ -1,98 +0,0 @@
//Called when the mob is hit with an item in combat.
/mob/living/carbon/resolve_item_attack(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
if(check_attack_throat(I, user))
return null
..()
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
if(!effective_force || blocked >= 2)
return 0
//Hulk modifier
if(HULK in user.mutations)
effective_force *= 2
//Apply weapon damage
var/weapon_sharp = is_sharp(I)
var/weapon_edge = has_edge(I)
if(prob(getarmor(hit_zone, "melee"))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
weapon_sharp = 0
weapon_edge = 0
apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
//Melee weapon embedded object code.
if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I))
var/damage = effective_force
if (blocked)
damage /= blocked+1
//blunt objects should really not be embedding in things unless a huge amount of force is involved
var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
//Sharp objects will always embed if they do enough damage.
if((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance)))
src.embed(I, hit_zone)
return 1
// Attacking someone with a weapon while they are neck-grabbed
/mob/living/carbon/proc/check_attack_throat(obj/item/W, mob/user)
if(user.a_intent == I_HURT)
for(var/obj/item/weapon/grab/G in src.grabbed_by)
if(G.assailant == user && G.state >= GRAB_NECK)
if(attack_throat(W, G, user))
return 1
return 0
// Knifing
/mob/living/carbon/proc/attack_throat(obj/item/W, obj/item/weapon/grab/G, mob/user)
if(!W.edge || !W.force || W.damtype != BRUTE)
return 0 //unsuitable weapon
user.visible_message("<span class='danger'>\The [user] begins to slit [src]'s throat with \the [W]!</span>")
user.next_move = world.time + 20 //also should prevent user from triggering this repeatedly
if(!do_after(user, 20))
return 0
if(!(G && G.assailant == user && G.affecting == src)) //check that we still have a grab
return 0
var/damage_mod = 1
//presumably, if they are wearing a helmet that stops pressure effects, then it probably covers the throat as well
var/obj/item/clothing/head/helmet = get_equipped_item(slot_head)
if(istype(helmet) && (helmet.body_parts_covered & HEAD) && (helmet.flags & STOPPRESSUREDAMAGE))
//we don't do an armor_check here because this is not an impact effect like a weapon swung with momentum, that either penetrates or glances off.
damage_mod = 1.0 - (helmet.armor["melee"]/100)
var/total_damage = 0
for(var/i in 1 to 3)
var/damage = min(W.force*1.5, 20)*damage_mod
apply_damage(damage, W.damtype, "head", 0, sharp=W.sharp, edge=W.edge)
total_damage += damage
var/oxyloss = total_damage
if(total_damage >= 40) //threshold to make someone pass out
oxyloss = 60 // Brain lacks oxygen immediately, pass out
adjustOxyLoss(min(oxyloss, 100 - getOxyLoss())) //don't put them over 100 oxyloss
if(total_damage)
if(oxyloss >= 40)
user.visible_message("<span class='danger'>\The [user] slit [src]'s throat open with \the [W]!</span>")
else
user.visible_message("<span class='danger'>\The [user] cut [src]'s neck with \the [W]!</span>")
if(W.hitsound)
playsound(loc, W.hitsound, 50, 1, -1)
G.last_action = world.time
flick(G.hud.icon_state, G.hud)
user.attack_log += "\[[time_stamp()]\]<font color='red'> Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
src.attack_log += "\[[time_stamp()]\]<font color='orange'> Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" )
return 1
+29 -7
View File
@@ -654,17 +654,38 @@
///eyecheck()
///Returns a number between -1 to 2
/mob/living/carbon/human/eyecheck()
var/number = 0
if(!species.has_organ["eyes"]) //No eyes, can't hurt them.
return FLASH_PROTECTION_MAJOR
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 FLASH_PROTECTION_MAJOR
return 2
else
return
return 2
return flash_protection
if(istype(src.head, /obj/item/clothing/head/welding))
if(!src.head:up)
number += 2
if(istype(back, /obj/item/weapon/rig))
var/obj/item/weapon/rig/O = back
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
number += 2
if(istype(src.head, /obj/item/clothing/head/helmet/space))
number += 2
if(istype(src.head, /obj/item/clothing/head/helmet/space/emergency))
number -= 2
if(istype(src.glasses, /obj/item/clothing/glasses/thermal))
number -= 1
if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses))
number += 1
if(istype(src.glasses, /obj/item/clothing/glasses/welding))
var/obj/item/clothing/glasses/welding/W = src.glasses
if(!W.up)
number += 2
return number
//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.
@@ -951,7 +972,7 @@
if(L && !L.is_bruised())
src.custom_pain("You feel a stabbing pain in your chest!", 1)
L.bruise()
L.damage = L.min_bruised_damage
/*
/mob/living/carbon/human/verb/simulate()
@@ -1261,10 +1282,11 @@
if(C.body_parts_covered & FEET)
feet_exposed = 0
flavor_text = ""
flavor_text = flavor_texts["general"]
flavor_text += "\n\n"
for (var/T in flavor_texts)
if(flavor_texts[T] && flavor_texts[T] != "")
if((T == "general") || (T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed))
if((T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed))
flavor_text += flavor_texts[T]
flavor_text += "\n\n"
if(!shrink)
@@ -296,6 +296,23 @@
updatehealth()
return 1
/mob/living/carbon/human/proc/attack_joint(var/obj/item/W, var/mob/living/user, var/def_zone)
if(!def_zone) def_zone = user.zone_sel.selecting
var/target_zone = get_zone_with_miss_chance(check_zone(def_zone), src)
if(user == src) // Attacking yourself can't miss
target_zone = user.zone_sel.selecting
if(!target_zone)
return null
var/obj/item/organ/external/organ = get_organ(check_zone(target_zone))
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1))
return null
var/dislocation_str
if(prob(W.force))
dislocation_str = "[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!"
organ.dislocate(1)
return dislocation_str
//Used to attack a joint through grabbing
/mob/living/carbon/human/proc/grab_joint(var/mob/living/user, var/def_zone)
var/has_grab = 0
@@ -16,14 +16,14 @@ emp_act
var/obj/item/organ/external/organ = get_organ()
//Shields
//Shields
var/shield_check = check_shields(P.damage, P, null, def_zone, "the [P.name]")
if(shield_check)
if(shield_check < 0)
return shield_check
else
P.on_hit(src, 2, def_zone)
return 2
return 2
//Shrapnel
if(P.can_embed())
@@ -145,77 +145,70 @@ emp_act
O.emp_act(severity)
..()
/mob/living/carbon/human/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
if(check_attack_throat(I, user))
return null
//Returns 1 if the attack hit, 0 if it missed.
/mob/living/carbon/human/proc/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone)
if(!I || !user) return 0
var/target_zone = def_zone? check_zone(def_zone) : get_zone_with_miss_chance(user.zone_sel.selecting, src)
if(user == src) // Attacking yourself can't miss
return target_zone
target_zone = user.zone_sel.selecting
if(!target_zone)
visible_message("<span class='danger'>[user] misses [src] with \the [I]!</span>")
return 1
var/hit_zone = get_zone_with_miss_chance(target_zone, src)
var/obj/item/organ/external/affecting = get_organ(target_zone)
if(!hit_zone)
visible_message("<span class='danger'>\The [user] misses [src] with \the [I]!</span>")
return null
if(check_shields(I.force, I, user, target_zone, "the [I.name]"))
return null
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if (!affecting || (affecting.status & ORGAN_DESTROYED) || affecting.is_stump())
user << "<span class='danger'>They are missing that limb!</span>"
return null
return
return hit_zone
var/effective_force = I.force
if(user.a_intent == "disarm") effective_force = round(I.force/2)
var/hit_area = affecting.name
/mob/living/carbon/human/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if(!affecting)
return //should be prevented by attacked_with_item() but for sanity.
visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] in the [affecting.name] with [I.name] by [user]!</span>")
var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
return blocked
/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if(!affecting)
if((user != src) && check_shields(effective_force, I, user, target_zone, "the [I.name]"))
return 0
// Handle striking to cripple.
if(user.a_intent == I_DISARM)
effective_force /= 2 //half the effective force
if(!..(I, effective_force, blocked, hit_zone))
return 0
attack_joint(affecting, I, blocked) //but can dislocate joints
else if(!..())
return 0
if(istype(I,/obj/item/weapon/card/emag))
if(!(affecting.status & ORGAN_ROBOT))
user << "\red That limb isn't robotic."
return
if(affecting.sabotaged)
user << "\red [src]'s [affecting.name] is already sabotaged!"
else
user << "\red You sneakily slide [I] into the dataport on [src]'s [affecting.name] and short out the safeties."
var/obj/item/weapon/card/emag/emag = I
emag.uses--
affecting.sabotaged = 1
return 1
if(effective_force > 10 || effective_force >= 5 && prob(33))
forcesay(hit_appends) //forcesay checks stat already
if(I.attack_verb.len)
visible_message("\red <B>[src] has been [pick(I.attack_verb)] in the [hit_area] with [I.name] by [user]!</B>")
else
visible_message("\red <B>[src] has been attacked in the [hit_area] with [I.name] by [user]!</B>")
if((I.damtype == BRUTE || I.damtype == HALLOSS) && prob(25 + (effective_force * 2)))
if(!stat)
if(headcheck(hit_zone))
//Harder to score a stun but if you do it lasts a bit longer
if(prob(effective_force))
visible_message("<span class='danger'>[src] [species.knockout_message]</span>")
apply_effect(20, PARALYZE, blocked)
else
//Easier to score a stun but lasts less time
if(prob(effective_force + 10))
visible_message("<span class='danger'>[src] has been knocked down!</span>")
apply_effect(6, WEAKEN, blocked)
//Apply blood
if(!(I.flags & NOBLOODY))
I.add_blood(src)
var/armor = run_armor_check(affecting, "melee", I.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].")
var/weapon_sharp = is_sharp(I)
var/weapon_edge = has_edge(I)
if ((weapon_sharp || weapon_edge) && prob(getarmor(target_zone, "melee")))
weapon_sharp = 0
weapon_edge = 0
if(armor >= 2) return 0
if(!effective_force) return 0
var/Iforce = effective_force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
apply_damage(effective_force, I.damtype, affecting, armor, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
var/bloody = 0
if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (effective_force * 2)))
I.add_blood(src) //Make the weapon bloody, not the person.
// if(user.hand) user.update_inv_l_hand() //updates the attacker's overlay for the (now bloodied) weapon
// else user.update_inv_r_hand() //removed because weapons don't have on-mob blood overlays
if(prob(33))
bloody = 1
var/turf/location = loc
if(istype(location, /turf/simulated))
location.add_blood(src)
@@ -225,7 +218,21 @@ emp_act
H.bloody_body(src)
H.bloody_hands(src)
switch(hit_zone)
if(!stat)
if(headcheck(hit_area))
//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>")
else
//Easier to score a stun but lasts less time
if(prob(effective_force + 10))
apply_effect(6, WEAKEN, armor)
visible_message("<span class='danger'>[src] has been knocked down!</span>")
//Apply blood
if(bloody)
switch(hit_area)
if("head")
if(wear_mask)
wear_mask.add_blood(src)
@@ -239,27 +246,22 @@ emp_act
if("chest")
bloody_body(src)
return 1
if(Iforce > 10 || Iforce >= 5 && prob(33))
forcesay(hit_appends) //forcesay checks stat already
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/blocked)
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 2)
return 0
if(prob(W.force / (blocked+1)))
visible_message("<span class='danger'>[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!</span>")
organ.dislocate(1)
return 1
return 0
//Melee weapon embedded object code.
if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I))
var/damage = effective_force
if (armor)
damage /= armor+1
/mob/living/carbon/human/emag_act(var/remaining_charges, mob/user, var/emag_source)
var/obj/item/organ/external/affecting = get_organ(user.zone_sel.selecting)
if(!affecting || !(affecting.status & ORGAN_ROBOT))
user << "<span class='warning'>That limb isn't robotic.</span>"
return -1
if(affecting.sabotaged)
user << "<span class='warning'>[src]'s [affecting.name] is already sabotaged!</span>"
return -1
user << "<span class='notice'>You sneakily slide [emag_source] into the dataport on [src]'s [affecting.name] and short out the safeties.</span>"
affecting.sabotaged = 1
//blunt objects should really not be embedding in things unless a huge amount of force is involved
var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
//Sharp objects will always embed if they do enough damage.
if((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance)))
affecting.embed(I)
return 1
//this proc handles being hit by a thrown atom
@@ -444,3 +446,4 @@ emp_act
perm += perm_by_part[part]
return perm
@@ -85,11 +85,3 @@
mob_bump_flag = HUMAN
mob_push_flags = ~HEAVY
mob_swap_flags = ~HEAVY
var/flash_protection = 0 // Total level of flash protection
var/equipment_tint_total = 0 // Total level of visualy impairing items
var/equipment_darkness_modifier // Darkvision modifier from equipped items
var/equipment_vision_flags // Extra vision flags from equipped items
var/equipment_see_invis // Max see invibility level granted by equipped items
var/equipment_prescription // Eye prescription granted by equipped items
var/list/equipment_overlays = list() // Extra overlays from equipped items
@@ -1,83 +0,0 @@
#define HUMAN_EATING_NO_ISSUE 0
#define HUMAN_EATING_NO_MOUTH 1
#define HUMAN_EATING_BLOCKED_MOUTH 2
#define add_clothing_protection(A) \
var/obj/item/clothing/C = A; \
flash_protection += C.flash_protection; \
equipment_tint_total += C.tint;
/mob/living/carbon/human/can_eat(var/food, var/feedback = 1)
var/list/status = can_eat_status()
if(status[0] == HUMAN_EATING_NO_ISSUE)
return 1
if(feedback)
if(status[0] == HUMAN_EATING_NO_MOUTH)
src << "Where do you intend to put \the [food]? You don't have a mouth!"
else if(status[0] == HUMAN_EATING_BLOCKED_MOUTH)
src << "<span class='warning'>\The [status[1]] is in the way!</span>"
return 0
/mob/living/carbon/human/can_force_feed(var/feeder, var/food, var/feedback = 1)
var/list/status = can_eat_status()
if(status[0] == HUMAN_EATING_NO_ISSUE)
return 1
if(feedback)
if(status[0] == HUMAN_EATING_NO_MOUTH)
feeder << "Where do you intend to put \the [food]? \The [src] doesn't have a mouth!"
else if(status[0] == HUMAN_EATING_BLOCKED_MOUTH)
feeder << "<span class='warning'>\The [status[1]] is in the way!</span>"
return 0
/mob/living/carbon/human/proc/can_eat_status()
if(!check_has_mouth())
return list(HUMAN_EATING_NO_MOUTH)
var/obj/item/blocked = check_mouth_coverage()
if(blocked)
return list(HUMAN_EATING_BLOCKED_MOUTH, blocked)
return list(HUMAN_EATING_NO_ISSUE)
#undef HUMAN_EATING_NO_ISSUE
#undef HUMAN_EATING_NO_MOUTH
#undef HUMAN_EATING_BLOCKED_MOUTH
/mob/living/carbon/human/proc/update_equipment_vision()
flash_protection = 0
equipment_tint_total = 0
equipment_see_invis = 0
equipment_vision_flags = 0
equipment_prescription = 0
equipment_darkness_modifier = 0
equipment_overlays.Cut()
if(istype(src.head, /obj/item/clothing/head))
add_clothing_protection(head)
if(istype(src.glasses, /obj/item/clothing/glasses))
process_glasses(glasses)
if(istype(src.wear_mask, /obj/item/clothing/mask))
add_clothing_protection(wear_mask)
if(istype(back,/obj/item/weapon/rig))
process_rig(back)
/mob/living/carbon/human/proc/process_glasses(var/obj/item/clothing/glasses/G)
if(G && G.active)
equipment_darkness_modifier += G.darkness_view
equipment_vision_flags |= G.vision_flags
equipment_prescription = equipment_prescription || G.prescription
if(G.overlay)
equipment_overlays |= G.overlay
if(G.see_invisible >= 0)
if(equipment_see_invis)
equipment_see_invis = min(equipment_see_invis, G.see_invisible)
else
equipment_see_invis = G.see_invisible
add_clothing_protection(G)
G.process_hud(src)
/mob/living/carbon/human/proc/process_rig(var/obj/item/weapon/rig/O)
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
if((O.offline && O.offline_vision_restriction == 2) || (!O.offline && O.vision_restriction == 2))
equipment_tint_total += TINT_BLIND
if(O.visor && O.visor.active && O.visor.vision && O.visor.vision.glasses && (!O.helmet || (head && O.helmet == head)))
process_glasses(O.visor.vision.glasses)
@@ -224,14 +224,11 @@
set name = "Split"
set desc = "Split your humanoid form into its constituent nymphs."
set category = "Abilities"
diona_split_into_nymphs(5) // Separate proc to void argments being supplied when used as a verb
/mob/living/carbon/human/proc/diona_split_into_nymphs(var/number_of_resulting_nymphs)
var/turf/T = get_turf(src)
var/mob/living/carbon/alien/diona/S = new(T)
S.set_dir(dir)
transfer_languages(src, S)
if(mind)
mind.transfer_to(S)
@@ -242,18 +239,20 @@
for(var/mob/living/carbon/alien/diona/D in src)
nymphs++
D.forceMove(T)
transfer_languages(src, D, WHITELISTED|RESTRICTED)
D.loc = T
D.set_dir(pick(NORTH, SOUTH, EAST, WEST))
if(nymphs < number_of_resulting_nymphs)
for(var/i in nymphs to (number_of_resulting_nymphs - 1))
if(nymphs < 5)
for(var/i in nymphs to 4)
var/mob/M = new /mob/living/carbon/alien/diona(T)
transfer_languages(src, M, WHITELISTED|RESTRICTED)
M.set_dir(pick(NORTH, SOUTH, EAST, WEST))
for(var/obj/item/W in src)
drop_from_inventory(W)
visible_message("<span class='warning'>\The [src] quivers slightly, then splits apart with a wet slithering noise.</span>")
qdel(src)
+191 -78
View File
@@ -41,6 +41,11 @@
if (transforming)
return
//Apparently, the person who wrote this code designed it so that
//blinded get reset each cycle and then get activated later in the
//code. Very ugly. I dont care. Moving this stuff here so its easy
//to find it.
blinded = null
fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it.
//TODO: seperate this out
@@ -148,26 +153,6 @@
return ONE_ATMOSPHERE + pressure_difference
/mob/living/carbon/human/handle_disabilities()
..()
//Vision
var/obj/item/organ/vision
if(species.vision_organ)
vision = internal_organs_by_name[species.vision_organ]
if(!vision) // Presumably if a species has no vision organs, they see via some other means.
eye_blind = 0
blinded = 0
eye_blurry = 0
else if(vision.is_broken()) // Vision organs cut out or broken? Permablind.
eye_blind = 1
blinded = 1
eye_blurry = 1
else
//blindness
if(!(sdisabilities & BLIND))
if(equipment_tint_total >= TINT_BLIND) // Covered eyes, heal faster
eye_blurry = max(eye_blurry-2, 0)
if (disabilities & EPILEPSY)
if ((prob(1) && paralysis < 1))
src << "\red You have a seizure!"
@@ -217,7 +202,7 @@
emote("drool")
*/
if(stat != DEAD)
if(stat != 2)
var/rn = rand(0, 200)
if(getBrainLoss() >= 5)
if(0 <= rn && rn <= 3)
@@ -357,28 +342,11 @@
internals.icon_state = "internal0"
return null
/mob/living/carbon/human/get_breath_from_environment(var/volume_needed=BREATH_VOLUME)
var/datum/gas_mixture/breath = ..()
if(breath)
//exposure to extreme pressures can rupture lungs
var/check_pressure = breath.return_pressure()
if(check_pressure < ONE_ATMOSPHERE / 5 || check_pressure > ONE_ATMOSPHERE * 5)
if(!is_lung_ruptured() && prob(5))
rupture_lung()
return breath
/mob/living/carbon/human/handle_breath(datum/gas_mixture/breath)
if(status_flags & GODMODE)
return
//exposure to extreme pressures can rupture lungs
if(breath && (breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5))
if(!is_lung_ruptured() && prob(5))
rupture_lung()
//check if we actually need to process breath
if(!breath || (breath.total_moles == 0) || suiciding)
failed_last_breath = 1
if(suiciding)
@@ -391,9 +359,10 @@
adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
oxygen_alert = max(oxygen_alert, 1)
return 0
var/safe_pressure_min = species.breath_pressure // Minimum safe partial pressure of breathable gas in kPa
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"])
@@ -985,11 +954,11 @@
for(var/atom/a in hallucinations)
qdel(a)
if(halloss > 100)
src << "<span class='warning'>[species.halloss_message_self]</span>"
src.visible_message("<B>[src]</B> [species.halloss_message].")
Paralyse(10)
setHalLoss(99)
if(halloss > 100)
src << "<span class='notice'>You're in too much pain to keep going...</span>"
src.visible_message("<B>[src]</B> slumps to the ground, too weak to continue fighting.")
Paralyse(10)
setHalLoss(99)
if(paralysis || sleeping)
blinded = 1
@@ -1021,12 +990,49 @@
if(!E.len)
embedded_flag = 0
//Eyes
//Check rig first because it's two-check and other checks will override it.
if(istype(back,/obj/item/weapon/rig))
var/obj/item/weapon/rig/O = back
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
if((O.offline && O.offline_vision_restriction == 2) || (!O.offline && O.vision_restriction == 2))
blinded = 1
// Check everything else.
//Periodically double-check embedded_flag
if(embedded_flag && !(life_tick % 10))
if(!embedded_needs_process())
embedded_flag = 0
//Vision
var/obj/item/organ/vision
if(species.vision_organ)
vision = internal_organs_by_name[species.vision_organ]
if(!vision) // Presumably if a species has no vision organs, they see via some other means.
eye_blind = 0
blinded = 0
eye_blurry = 0
else if(vision.is_broken()) // Vision organs cut out or broken? Permablind.
eye_blind = 1
blinded = 1
eye_blurry = 1
else
//blindness
if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
blinded = 1
else if(eye_blind) // Blindness, heals slowly over time
eye_blind = max(eye_blind-1,0)
blinded = 1
else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster
eye_blurry = max(eye_blurry-3, 0)
blinded = 1
//blurry sight
if(vision.is_bruised()) // Vision organs impaired? Permablurry.
eye_blurry = 1
if(eye_blurry) // Blurry eyes heal slowly
eye_blurry = max(eye_blurry-1, 0)
//Ears
if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own
@@ -1100,8 +1106,14 @@
// now handle what we see on our screen
if(!..())
return
if(!client)
return 0
for(var/image/hud in client.images)
if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe
client.images.Remove(hud)
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science)
if(damageoverlay.overlays)
damageoverlay.overlays = list()
@@ -1173,6 +1185,60 @@
I = overlays_cache[23]
damageoverlay.overlays += I
if( stat == DEAD )
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(healths) healths.icon_state = "health7" //DEAD healthmeter
if(client)
if(client.view != world.view) // If mob dies while zoomed in with device, unzoom them.
for(var/obj/item/item in contents)
if(item.zoom)
item.zoom()
break
else
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(seer==1)
var/obj/effect/rune/R = locate() in loc
if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"])
see_invisible = SEE_INVISIBLE_CULT
else
see_invisible = SEE_INVISIBLE_LIVING
seer = 0
else
sight = species.get_vision_flags(src)
see_in_dark = species.darksight
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING
var/tmp/glasses_processed = 0
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.visor)
if(!rig.helmet || (head && rig.helmet == head))
if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses)
glasses_processed = 1
process_glasses(rig.visor.vision.glasses)
if(glasses && !glasses_processed)
glasses_processed = 1
process_glasses(glasses)
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(!glasses_processed && (species.get_vision_flags(src) > 0))
sight |= species.get_vision_flags(src)
if(!seer && !glasses_processed)
see_invisible = SEE_INVISIBLE_LIVING
if(healths)
if (analgesic > 100)
healths.icon_state = "health_health_numb"
@@ -1191,6 +1257,8 @@
if(0 to 20) healths.icon_state = "health5"
else healths.icon_state = "health6"
if(!seer)
see_invisible = SEE_INVISIBLE_LIVING
if(nutrition_icon)
switch(nutrition)
if(450 to INFINITY) nutrition_icon.icon_state = "nutrition0"
@@ -1256,8 +1324,85 @@
bodytemp.icon_state = "temp-1"
else
bodytemp.icon_state = "temp0"
if(blind)
if(blinded) blind.layer = 18
else blind.layer = 0
if(disabilities & NEARSIGHTED) //this looks meh but saves a lot of memory by not requiring to add var/prescription
if(glasses) //to every /obj/item
var/obj/item/clothing/glasses/G = glasses
if(!G.prescription)
client.screen += global_hud.vimpaired
else
client.screen += global_hud.vimpaired
if(eye_blurry) client.screen += global_hud.blurry
if(druggy) client.screen += global_hud.druggy
if(config.welder_vision)
var/found_welder
if(species.short_sighted)
found_welder = 1
else
if(istype(glasses, /obj/item/clothing/glasses/welding))
var/obj/item/clothing/glasses/welding/O = glasses
if(!O.up)
found_welder = 1
if(!found_welder && istype(head, /obj/item/clothing/head/welding))
var/obj/item/clothing/head/welding/O = head
if(!O.up)
found_welder = 1
if(!found_welder && istype(back, /obj/item/weapon/rig))
var/obj/item/weapon/rig/O = back
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
if((O.offline && O.offline_vision_restriction == 1) || (!O.offline && O.vision_restriction == 1))
found_welder = 1
if(found_welder)
client.screen |= global_hud.darkMask
if(machine)
var/viewflags = machine.check_eye(src)
if(viewflags < 0)
reset_view(null, 0)
else if(viewflags)
sight |= viewflags
else if(eyeobj)
if(eyeobj.owner != src)
reset_view(null)
else
var/isRemoteObserve = 0
if((mRemote in mutations) && remoteview_target)
if(remoteview_target.stat==CONSCIOUS)
isRemoteObserve = 1
if(!isRemoteObserve && client && !client.adminobs)
remoteview_target = null
reset_view(null, 0)
return 1
/mob/living/carbon/human/proc/process_glasses(var/obj/item/clothing/glasses/G)
if(G && G.active)
see_in_dark += G.darkness_view
if(G.overlay)
client.screen |= G.overlay
if(G.vision_flags)
sight |= G.vision_flags
if(!druggy && !seer)
see_invisible = SEE_INVISIBLE_MINIMUM
if(G.see_invisible >= 0)
see_invisible = G.see_invisible
if(istype(G,/obj/item/clothing/glasses/night) && !seer)
see_invisible = SEE_INVISIBLE_MINIMUM
/* HUD shit goes here, as long as it doesn't modify sight flags */
// The purpose of this is to stop xray and w/e from preventing you from using huds -- Love, Doohl
var/obj/item/clothing/glasses/hud/O = G
if(istype(G, /obj/item/clothing/glasses/sunglasses/sechud))
var/obj/item/clothing/glasses/sunglasses/sechud/S = G
O = S.hud
if(istype(O))
O.process_hud(src)
if(!druggy && !seer) see_invisible = SEE_INVISIBLE_LIVING
/mob/living/carbon/human/handle_random_events()
if(in_stasis)
return
@@ -1580,37 +1725,5 @@
restore_blood()
..()
/mob/living/carbon/human/handle_vision()
if(client)
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science)
if(machine)
var/viewflags = machine.check_eye(src)
if(viewflags < 0)
reset_view(null, 0)
else if(viewflags)
sight |= viewflags
else if(eyeobj)
if(eyeobj.owner != src)
reset_view(null)
else
var/isRemoteObserve = 0
if((mRemote in mutations) && remoteview_target)
if(remoteview_target.stat==CONSCIOUS)
isRemoteObserve = 1
if(!isRemoteObserve && client && !client.adminobs)
remoteview_target = null
reset_view(null, 0)
update_equipment_vision()
species.handle_vision(src)
/mob/living/carbon/human/update_sight()
..()
if(stat == DEAD)
return
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS
@@ -20,7 +20,6 @@
var/prone_icon // If set, draws this from icobase when mob is prone.
var/eyes = "eyes_s" // Icon for eyes.
var/has_floating_eyes // Eyes will overlay over darkness (glow)
var/blood_color = "#A10808" // Red.
var/flesh_color = "#FFC896" // Pink.
var/base_color // Used by changelings. Should also be used for icon previes..
@@ -68,12 +67,9 @@
var/death_sound
var/death_message = "seizes up and falls limp, their eyes dead and lifeless..."
var/knockout_message = "has been knocked unconscious!"
var/halloss_message = "slumps to the ground, too weak to continue fighting."
var/halloss_message_self = "You're in too much pain to keep going..."
// Environment tolerance/life processes vars.
var/reagent_tag //Used for metabolizing reagents.
var/breath_pressure = 16 // Minimum partial pressure safe for breathing, kPa
var/breath_type = "oxygen" // Non-oxygen gas breathed, if any.
var/poison_type = "phoron" // Poisonous air.
var/exhale_type = "carbon_dioxide" // Exhaled gas type.
@@ -156,9 +152,6 @@
var/pass_flags = 0
/datum/species/proc/get_eyes(var/mob/living/carbon/human/H)
return
/datum/species/New()
if(hud_type)
hud = new hud_type()
@@ -337,42 +330,3 @@
/datum/species/proc/get_vision_flags(var/mob/living/carbon/human/H)
return vision_flags
/datum/species/proc/handle_vision(var/mob/living/carbon/human/H)
H.update_sight()
H.sight |= get_vision_flags(H)
H.sight |= H.equipment_vision_flags
if(H.stat == DEAD)
return 1
if(!H.druggy)
H.see_in_dark = (H.sight == SEE_TURFS|SEE_MOBS|SEE_OBJS) ? 8 : min(darksight + H.equipment_darkness_modifier, 8)
if(H.seer)
var/obj/effect/rune/R = locate() in H.loc
if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"])
H.see_invisible = SEE_INVISIBLE_CULT
if(H.see_invisible != SEE_INVISIBLE_CULT && H.equipment_see_invis)
H.see_invisible = min(H.see_invisible, H.equipment_see_invis)
if(H.equipment_tint_total >= TINT_BLIND)
H.eye_blind = max(H.eye_blind, 1)
if(H.blind)
H.blind.layer = (H.eye_blind ? 18 : 0)
if(!H.client)//no client, no screen to update
return 1
if(config.welder_vision)
if(short_sighted || (H.equipment_tint_total >= TINT_HEAVY))
H.client.screen += global_hud.darkMask
else if((!H.equipment_prescription && (H.disabilities & NEARSIGHTED)) || H.equipment_tint_total == TINT_MODERATE)
H.client.screen += global_hud.vimpaired
if(H.eye_blurry) H.client.screen += global_hud.blurry
if(H.druggy) H.client.screen += global_hud.druggy
for(var/overlay in H.equipment_overlays)
H.client.screen |= overlay
return 1
@@ -242,7 +242,19 @@
return ..()
/datum/species/diona/handle_death(var/mob/living/carbon/human/H)
H.diona_split_into_nymphs(0)
var/mob/living/carbon/alien/diona/S = new(get_turf(H))
if(H.mind)
H.mind.transfer_to(S)
for(var/mob/living/carbon/alien/diona/D in H.contents)
if(D.client)
D.loc = H.loc
else
qdel(D)
H.visible_message("<span class='danger'>[H] splits apart with a wet slithering noise!</span>")
/datum/species/machine
name = "Machine"
@@ -269,8 +281,6 @@
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!"
halloss_message = "encounters a hardware fault and suddenly reboots."
halloss_message_self = "ERROR: Unrecoverable machine check exception.<BR>System halted, rebooting..."
warning_low_pressure = 50
hazard_low_pressure = 0
@@ -0,0 +1,159 @@
// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability
// It functions almost identically (see code/datums/diseases/alien_embryo.dm)
/obj/item/alien_embryo
name = "alien embryo"
desc = "All slimy and yuck."
icon = 'icons/mob/alien.dmi'
icon_state = "larva0_dead"
var/mob/living/affected_mob
var/stage = 0
/obj/item/alien_embryo/New()
if(istype(loc, /mob/living))
affected_mob = loc
processing_objects.Add(src)
spawn(0)
AddInfectionImages(affected_mob)
else
qdel(src)
/obj/item/alien_embryo/Destroy()
if(affected_mob)
affected_mob.status_flags &= ~(XENO_HOST)
spawn(0)
RemoveInfectionImages(affected_mob)
..()
/obj/item/alien_embryo/process()
if(!affected_mob) return
if(loc != affected_mob)
affected_mob.status_flags &= ~(XENO_HOST)
processing_objects.Remove(src)
spawn(0)
RemoveInfectionImages(affected_mob)
affected_mob = null
return
if(stage < 5 && prob(3))
stage++
spawn(0)
RefreshInfectionImage(affected_mob)
switch(stage)
if(2, 3)
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "\red Your throat feels sore."
if(prob(1))
affected_mob << "\red Mucous runs down the back of your throat."
if(4)
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(2))
affected_mob << "\red Your muscles ache."
if(prob(20))
affected_mob.take_organ_damage(1)
if(prob(2))
affected_mob << "\red Your stomach hurts."
if(prob(20))
affected_mob.adjustToxLoss(1)
affected_mob.updatehealth()
if(5)
affected_mob << "\red You feel something tearing its way out of your stomach..."
affected_mob.adjustToxLoss(10)
affected_mob.updatehealth()
if(prob(50))
AttemptGrow()
/obj/item/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1)
var/list/candidates = get_alien_candidates()
var/picked = null
// To stop clientless larva, we will check that our host has a client
// if we find no ghosts to become the alien. If the host has a client
// he will become the alien but if he doesn't then we will set the stage
// to 2, so we don't do a process heavy check everytime.
if(candidates.len)
picked = pick(candidates)
else if(affected_mob.client)
picked = affected_mob.key
else
stage = 4 // Let's try again later.
return
if(affected_mob.lying)
affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_lie")
else
affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_stand")
spawn(6)
var/mob/living/carbon/alien/larva/new_xeno = new(affected_mob.loc)
new_xeno.key = picked
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention
if(gib_on_success)
affected_mob.gib()
qdel(src)
/*----------------------------------------
Proc: RefreshInfectionImage()
Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens.
----------------------------------------*/
/obj/item/alien_embryo/proc/RefreshInfectionImage()
for(var/mob/living/carbon/alien in player_list)
if(!locate(/obj/item/organ/xenos/hivenode) in alien.internal_organs)
continue
if(alien.client)
for(var/image/I in alien.client.images)
if(dd_hasprefix_case(I.icon_state, "infected"))
qdel(I)
for(var/mob/living/L in mob_list)
if(iscorgi(L) || iscarbon(L))
if(L.status_flags & XENO_HOST)
var/I = image('icons/mob/alien.dmi', loc = L, icon_state = "infected[stage]")
alien.client.images += I
/*----------------------------------------
Proc: AddInfectionImages(C)
Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C.
----------------------------------------*/
/obj/item/alien_embryo/proc/AddInfectionImages(var/mob/living/C)
if(C)
for(var/mob/living/carbon/alien in player_list)
if(!locate(/obj/item/organ/xenos/hivenode) in alien.internal_organs)
continue
if(alien.client)
if(C.status_flags & XENO_HOST)
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]")
alien.client.images += I
/*----------------------------------------
Proc: RemoveInfectionImage(C)
Des: Removes the alien infection image from all aliens in the world located in passed mob (C).
----------------------------------------*/
/obj/item/alien_embryo/proc/RemoveInfectionImages(var/mob/living/C)
if(C)
for(var/mob/living/carbon/alien in player_list)
if(!locate(/obj/item/organ/xenos/hivenode) in alien.internal_organs)
continue
if(alien.client)
for(var/image/I in alien.client.images)
if(I.loc == C)
if(dd_hasprefix_case(I.icon_state, "infected"))
qdel(I)
@@ -32,11 +32,10 @@ var/const/MAX_ACTIVE_TIME = 400
..()
/obj/item/clothing/mask/facehugger/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
. = ..()
/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob)
..()
user.drop_from_inventory(src)
if(hit_zone == "head")
Attach(target)
Attach(M)
/obj/item/clothing/mask/facehugger/New()
if(config.aliens_allowed)
@@ -88,13 +88,13 @@
verbs -= /mob/living/carbon/human/proc/lay_egg
return
if(locate(/obj/structure/alien/egg) in get_turf(src))
if(locate(/obj/effect/alien/egg) in get_turf(src))
src << "There's already an egg here."
return
if(check_alien_ability(75,1,"egg sac"))
visible_message("<span class='alium'><B>[src] has laid an egg!</B></span>")
new /obj/structure/alien/egg(loc)
new /obj/effect/alien/egg(loc)
return
@@ -121,7 +121,7 @@
if(check_alien_ability(50,1,"resin spinner"))
visible_message("<span class='alium'><B>[src] has planted some alien weeds!</B></span>")
new /obj/structure/alien/node(loc)
new /obj/effect/alien/weeds/node(loc)
return
/mob/living/carbon/human/proc/corrosive_acid(O as obj|turf in oview(1)) //If they right click to corrode, an error will flash if its an invalid target./N
@@ -154,7 +154,7 @@
return
if(check_alien_ability(200,0,"acid gland"))
new /obj/effect/acid(get_turf(O), O)
new /obj/effect/alien/acid(get_turf(O), O)
visible_message("<span class='alium'><B>[src] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!</B></span>")
return
@@ -199,7 +199,7 @@
/mob/living/carbon/human/proc/resin() // -- TLE
set name = "Secrete Resin (75)"
set desc = "Secrete tough, malleable resin."
set desc = "Secrete tough malleable resin."
set category = "Abilities"
var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin door","resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist
@@ -214,51 +214,9 @@
if("resin door")
new /obj/structure/simple_door/resin(loc)
if("resin wall")
new /obj/structure/alien/resin/wall(loc)
new /obj/effect/alien/resin/wall(loc)
if("resin membrane")
new /obj/structure/alien/resin/membrane(loc)
new /obj/effect/alien/resin/membrane(loc)
if("resin nest")
new /obj/structure/bed/nest(loc)
return
mob/living/carbon/human/proc/xeno_infest(mob/living/carbon/human/M as mob in oview())
set name = "Infest (500)"
set desc = "Link a victim to the hivemind."
set category = "Abilities"
if(!M.Adjacent(src))
src << "<span class='warning'>They are too far away.</span>"
return
if(!M.mind)
src << "<span class='warning'>This mindless flesh adds nothing to the hive.</span>"
return
if(M.species.get_bodytype() == "Xenomorph" || !isnull(M.internal_organs_by_name["hive node"]))
src << "<span class='warning'>They are already part of the hive.</span>"
return
var/obj/item/organ/affecting = M.get_organ("chest")
if(!affecting || (affecting.status & ORGAN_ROBOT))
src << "<span class='warning'>This form is not compatible with our physiology.</span>"
return
src.visible_message("<span class='danger'>\The [src] crouches over \the [M], extending a hideous protuberance from its head!</span>")
if(!do_after(src, 150))
return
if(!M || !M.Adjacent(src))
src << "<span class='warning'>They are too far away.</span>"
return
if(M.species.get_bodytype() == "Xenomorph" || !isnull(M.internal_organs_by_name["hive node"]) || !affecting || (affecting.status & ORGAN_ROBOT))
return
if(!check_alien_ability(500,1,"egg sac"))
return
src.visible_message("<span class='danger'>\The [src] regurgitates something into \the [M]'s torso!</span>")
M << "<span class='danger'>A hideous lump of alien mass strains your ribcage as it settles within!</span>"
var/obj/item/organ/xenos/hivenode/node = new(affecting)
node.replaced(M,affecting)
return
@@ -15,8 +15,8 @@
eyes = "blank_eyes"
brute_mod = 0.25 // Hardened carapace.
burn_mod = 1.1 // Weak to fire.
brute_mod = 0.5 // Hardened carapace.
burn_mod = 2 // Weak to fire.
warning_low_pressure = 50
hazard_low_pressure = -1
@@ -98,11 +98,11 @@
var/datum/gas_mixture/environment = T.return_air()
if(!environment) return
var/obj/effect/plant/plant = locate() in T
if((environment.gas["phoron"] > 0 || (plant && plant.seed && plant.seed.name == "xenomorph")) && !regenerate(H))
var/obj/item/organ/xenos/plasmavessel/P = H.internal_organs_by_name["plasma vessel"]
P.stored_plasma += weeds_plasma_rate
P.stored_plasma = min(max(P.stored_plasma,0),P.max_plasma)
if(environment.gas["phoron"] > 0 || locate(/obj/effect/alien/weeds) in T)
if(!regenerate(H))
var/obj/item/organ/xenos/plasmavessel/P = H.internal_organs_by_name["plasma vessel"]
P.stored_plasma += weeds_plasma_rate
P.stored_plasma = min(max(P.stored_plasma,0),P.max_plasma)
..()
/datum/species/xenos/proc/regenerate(var/mob/living/carbon/human/H)
@@ -140,6 +140,14 @@
return 0
/datum/species/xenos/handle_login_special(var/mob/living/carbon/human/H)
H.AddInfectionImages()
..()
/datum/species/xenos/handle_logout_special(var/mob/living/carbon/human/H)
H.RemoveInfectionImages()
..()
/datum/species/xenos/drone
name = "Xenomorph Drone"
caste_name = "drone"
@@ -270,8 +278,7 @@
/mob/living/carbon/human/proc/transfer_plasma,
/mob/living/carbon/human/proc/corrosive_acid,
/mob/living/carbon/human/proc/neurotoxin,
/mob/living/carbon/human/proc/resin,
/mob/living/carbon/human/proc/xeno_infest
/mob/living/carbon/human/proc/resin
)
/datum/species/xenos/queen/handle_login_special(var/mob/living/carbon/human/H)
@@ -22,3 +22,28 @@ proc/create_new_xenomorph(var/alien_caste,var/target)
/mob/living/carbon/human/xqueen/New(var/new_loc)
h_style = "Bald"
..(new_loc, "Xenomorph Queen")
// I feel like we should generalize/condense down all the various icon-rendering antag procs.
/*----------------------------------------
Proc: AddInfectionImages()
Des: Gives the client of the alien an image on each infected mob.
----------------------------------------*/
/mob/living/carbon/human/proc/AddInfectionImages()
if (client)
for (var/mob/living/C in mob_list)
if(C.status_flags & XENO_HOST)
var/obj/item/alien_embryo/A = locate() in C
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]")
client.images += I
return
/*----------------------------------------
Proc: RemoveInfectionImages()
Des: Removes all infected images from the alien.
----------------------------------------*/
/mob/living/carbon/human/proc/RemoveInfectionImages()
if (client)
for(var/image/I in client.images)
if(dd_hasprefix_case(I.icon_state, "infected"))
qdel(I)
return
@@ -32,9 +32,6 @@
/datum/unarmed_attack/proc/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armour,var/attack_damage,var/zone)
if(target.stat == DEAD)
return
var/stun_chance = rand(0, 100)
if(attack_damage >= 5 && armour < 2 && !(target == user) && stun_chance <= attack_damage * 5) // 25% standard chance
@@ -236,4 +233,4 @@
switch(attack_damage)
if(1 to 4) user.visible_message("<span class='danger'>[pick("[user] stomped on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!</span>")
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/
@@ -163,8 +163,6 @@ Please contact me on #coderbus IRC. ~Carn x
icon = stand_icon
for(var/image/I in overlays_standing)
overlays += I
if(species.has_floating_eyes)
overlays |= species.get_eyes(src)
if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone.
var/matrix/M = matrix()
@@ -339,7 +337,7 @@ var/global/list/damage_icon_parts = list()
if(undershirt && species.appearance_flags & HAS_UNDERWEAR)
stand_icon.Blend(new /icon('icons/mob/human.dmi', undershirt), ICON_OVERLAY)
if(socks && species.appearance_flags & HAS_UNDERWEAR)
if(socks && species.flags & HAS_UNDERWEAR)
stand_icon.Blend(new /icon('icons/mob/human.dmi', socks), ICON_OVERLAY)
if(update_icons)
@@ -281,3 +281,87 @@
/mob/living/carbon/slime/has_eyes()
return 0
//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them////////////////////////
/*
// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere
/obj/item/slime_core
name = "slime extract"
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
icon = 'icons/mob/slimes.dmi'
icon_state = "slime extract"
force = 1.0
w_class = 1.0
throwforce = 1.0
throw_speed = 2
throw_range = 6
origin_tech = list(TECH_BIO = 4)
var/POWERFLAG = 0 // sshhhhhhh
var/Flush = 30
var/Uses = 5 // uses before it goes inert
/obj/item/slime_core/New()
..()
create_reagents(100)
POWERFLAG = rand(1,10)
Uses = rand(7, 25)
//flags |= NOREACT
/*
spawn()
Life()
proc/Life()
while(src)
sleep(25)
Flush--
if(Flush <= 0)
reagents.clear_reagents()
Flush = 30
*/
/obj/item/weapon/reagent_containers/food/snacks/egg/slime
name = "slime egg"
desc = "A small, gelatinous egg."
icon = 'icons/mob/mob.dmi'
icon_state = "slime egg-growing"
bitesize = 12
origin_tech = list(TECH_BIO = 4)
var/grown = 0
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/New()
..()
reagents.add_reagent("nutriment", 4)
reagents.add_reagent("slimejelly", 1)
spawn(rand(1200,1500))//the egg takes a while to "ripen"
Grow()
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow()
grown = 1
icon_state = "slime egg-grown"
processing_objects.Add(src)
return
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch()
processing_objects.Remove(src)
var/turf/T = get_turf(src)
src.visible_message("<span class='warning'> The [name] pulsates and quivers!</span>")
spawn(rand(50,100))
src.visible_message("<span class='warning'> The [name] bursts open!</span>")
new/mob/living/carbon/slime(T)
qdel(src)
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process()
var/turf/location = get_turf(src)
var/datum/gas_mixture/environment = location.return_air()
if (environment.phoron > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch
src.Hatch()
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype( W, /obj/item/weapon/pen/crayon ))
return
else
..()
*/
+7 -43
View File
@@ -126,60 +126,24 @@
adjustEarDamage(-0.05,-1)
//this handles hud updates. Calls update_vision() and handle_hud_icons()
/mob/living/proc/handle_regular_hud_updates()
if(!client) return 0
/mob/living/handle_regular_hud_updates()
if(!client)
return 0
..()
handle_hud_icons()
handle_vision()
handle_hud_icons()
return 1
/mob/living/proc/handle_vision()
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science)
update_sight()
if(stat == DEAD)
return
if(blind)
if(eye_blind)
blind.layer = 18
else
blind.layer = 0
if (disabilities & NEARSIGHTED)
client.screen += global_hud.vimpaired
if (eye_blurry)
client.screen += global_hud.blurry
if (druggy)
client.screen += global_hud.druggy
if(machine)
var/viewflags = machine.check_eye(src)
if(viewflags < 0)
reset_view(null, 0)
else if(viewflags)
sight |= viewflags
else if(eyeobj && eyeobj.owner != src)
reset_view(null)
else
if(!client.adminobs)
reset_view(null)
return
/mob/living/proc/update_sight()
if(stat == DEAD)
sight |= SEE_TURFS
sight |= SEE_MOBS
sight |= SEE_OBJS
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
else
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_in_dark = 2
see_invisible = SEE_INVISIBLE_LIVING
return
/mob/living/proc/handle_hud_icons()
handle_hud_icons_health()
handle_hud_glasses()
return
/mob/living/proc/handle_hud_icons_health()
+51 -36
View File
@@ -111,42 +111,6 @@
O.emp_act(severity)
..()
/mob/living/proc/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
return target_zone
//Called when the mob is hit with an item in combat. Returns the blocked result
/mob/living/proc/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] with [I.name] by [user]!</span>")
var/blocked = run_armor_check(hit_zone, "melee")
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too
var/turf/simulated/location = get_turf(src)
if(istype(location)) location.add_blood_floor(src)
return blocked
//returns 0 if the effects failed to apply for some reason, 1 otherwise.
/mob/living/proc/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
if(!effective_force || blocked >= 2)
return 0
//Hulk modifier
if(HULK in user.mutations)
effective_force *= 2
//Apply weapon damage
var/weapon_sharp = is_sharp(I)
var/weapon_edge = has_edge(I)
if(prob(max(getarmor(hit_zone, "melee") - I.armor_penetration, 0))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
weapon_sharp = 0
weapon_edge = 0
apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
return 1
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve
if(istype(AM,/obj/))
@@ -374,3 +338,54 @@
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
//hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1)
client.screen += hud_used.hide_actions_toggle
//If simple_animals are ever moved under carbon, then this can probably be moved to carbon as well
/mob/living/proc/attack_throat(obj/item/W, obj/item/weapon/grab/G, mob/user)
// Knifing
if(!W.edge || !W.force || W.damtype != BRUTE) return //unsuitable weapon
user.visible_message("<span class='danger'>\The [user] begins to slit [src]'s throat with \the [W]!</span>")
user.next_move = world.time + 20 //also should prevent user from triggering this repeatedly
if(!do_after(user, 20))
return
if(!(G && G.assailant == user && G.affecting == src)) //check that we still have a grab
return
var/damage_mod = 1
//presumably, if they are wearing a helmet that stops pressure effects, then it probably covers the throat as well
var/obj/item/clothing/head/helmet = get_equipped_item(slot_head)
if(istype(helmet) && (helmet.body_parts_covered & HEAD) && (helmet.item_flags & STOPPRESSUREDAMAGE))
//we don't do an armor_check here because this is not an impact effect like a weapon swung with momentum, that either penetrates or glances off.
damage_mod = 1.0 - (helmet.armor["melee"]/100)
var/total_damage = 0
for(var/i in 1 to 3)
var/damage = min(W.force*1.5, 20)*damage_mod
apply_damage(damage, W.damtype, "head", 0, sharp=W.sharp, edge=W.edge)
total_damage += damage
var/oxyloss = total_damage
if(total_damage >= 40) //threshold to make someone pass out
oxyloss = 60 // Brain lacks oxygen immediately, pass out
adjustOxyLoss(min(oxyloss, 100 - getOxyLoss())) //don't put them over 100 oxyloss
if(total_damage)
if(oxyloss >= 40)
user.visible_message("<span class='danger'>\The [user] slit [src]'s throat open with \the [W]!</span>")
else
user.visible_message("<span class='danger'>\The [user] cut [src]'s neck with \the [W]!</span>")
if(W.hitsound)
playsound(loc, W.hitsound, 50, 1, -1)
G.last_action = world.time
flick(G.hud.icon_state, G.hud)
user.attack_log += "\[[time_stamp()]\]<font color='red'> Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
src.attack_log += "\[[time_stamp()]\]<font color='orange'> Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" )
return
+8 -12
View File
@@ -12,7 +12,7 @@
/mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg)
laws_sanity_check()
laws.set_zeroth_law(law, law_borg)
log_law("has given [src] the zeroth law: '[law]'[law_borg ? " / '[law_borg]'" : ""]")
log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]")
/mob/living/silicon/robot/set_zeroth_law(var/law, var/law_borg)
..()
@@ -22,40 +22,40 @@
/mob/living/silicon/proc/add_ion_law(var/law)
laws_sanity_check()
laws.add_ion_law(law)
log_law("has given [src] the ion law: [law]")
log_and_message_admins("has given [src] the ion law: [law]")
/mob/living/silicon/proc/add_inherent_law(var/law)
laws_sanity_check()
laws.add_inherent_law(law)
log_law("has given [src] the inherent law: [law]")
log_and_message_admins("has given [src] the inherent law: [law]")
/mob/living/silicon/proc/add_supplied_law(var/number, var/law)
laws_sanity_check()
laws.add_supplied_law(number, law)
log_law("has given [src] the supplied law: [law]")
log_and_message_admins("has given [src] the supplied law: [law]")
/mob/living/silicon/proc/delete_law(var/datum/ai_law/law)
laws_sanity_check()
laws.delete_law(law)
log_law("has deleted a law belonging to [src]: [law.law]")
log_and_message_admins("has deleted a law belonging to [src]: [law.law]")
/mob/living/silicon/proc/clear_inherent_laws(var/silent = 0)
laws_sanity_check()
laws.clear_inherent_laws()
if(!silent)
log_law("cleared the inherent laws of [src]")
log_and_message_admins("cleared the inherent laws of [src]")
/mob/living/silicon/proc/clear_ion_laws(var/silent = 0)
laws_sanity_check()
laws.clear_ion_laws()
if(!silent)
log_law("cleared the ion laws of [src]")
log_and_message_admins("cleared the ion laws of [src]")
/mob/living/silicon/proc/clear_supplied_laws(var/silent = 0)
laws_sanity_check()
laws.clear_supplied_laws()
if(!silent)
log_law("cleared the supplied laws of [src]")
log_and_message_admins("cleared the supplied laws of [src]")
/mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws)
var/prefix = ""
@@ -103,7 +103,3 @@
/mob/living/silicon/proc/lawsync()
laws_sanity_check()
laws.sort_laws()
/mob/living/silicon/proc/log_law(var/law_message)
log_and_message_admins(law_message)
lawchanges += "[worldtime2text()] - [usr ? "[key_name(usr)]" : "EVENT"] [law_message]"
@@ -91,15 +91,6 @@ var/global/list/robot_modules = list(
return
/obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R, var/rate)
var/obj/item/device/flash/F = locate() in src.modules
if(F)
if(F.broken)
F.broken = 0
F.times_used = 0
F.icon_state = "flash"
else if(F.times_used)
F.times_used--
if(!synths || !synths.len)
return
@@ -280,6 +271,7 @@ var/global/list/robot_modules = list(
..()
/obj/item/weapon/robot_module/medical/crisis/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules
if(S.mode == 2)
S.reagents.clear_reagents()
@@ -431,7 +423,13 @@ var/global/list/robot_modules = list(
..()
/obj/item/weapon/robot_module/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
..()
var/obj/item/device/flash/F = locate() in src.modules
if(F.broken)
F.broken = 0
F.times_used = 0
F.icon_state = "flash"
else if(F.times_used)
F.times_used--
var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in src.modules
if(T.power_supply.charge < T.power_supply.maxcharge)
T.power_supply.give(T.charge_cost * amount)
@@ -464,7 +462,6 @@ var/global/list/robot_modules = list(
..()
/obj/item/weapon/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
..()
var/obj/item/device/lightreplacer/LR = locate() in src.modules
LR.Charge(R, amount)
if(src.emag)
@@ -547,7 +544,6 @@ var/global/list/robot_modules = list(
..()
/obj/item/weapon/robot_module/general/butler/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
..()
var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules
E.reagents.add_reagent("enzyme", 2 * amount)
if(src.emag)
+21 -36
View File
@@ -68,46 +68,31 @@
if (!message)
return
var/obj/machinery/hologram/holopad/H = src.holo
if(H && H.masters[src])//If there is a hologram and its master is the user.
var/obj/machinery/hologram/holopad/T = src.holo
if(T && T.masters[src])//If there is a hologram and its master is the user.
//Human-like, sorta, heard by those who understand humans.
var/rendered_a
//Speach distorted, heard by those who do not understand AIs.
var/message_stars = stars(message)
var/rendered_b
// AI can hear their own message, this formats it for them.
if(speaking)
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [speaking.format_message(message, verb)]</span></i>"
rendered_a = "<span class='game say'><span class='name'>[name]</span> [speaking.format_message(message, verb)]</span>"
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [speaking.format_message(message_stars, verb)]</span>"
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [speaking.format_message(message, verb)]</span></i>"//The AI can "hear" its own message.
else
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [verb], <span class='message'><span class='body'>\"[message]\"</span></span></span></i>"
//This is so pAI's and people inside lockers/boxes,etc can hear the AI Holopad, the alternative being recursion through contents.
//This is much faster.
var/list/listening = list()
var/list/listening_obj = list()
var/turf/T = get_turf(H)
if(T)
var/list/hear = hear(7, T)
var/list/hearturfs = list()
for(var/I in hear)
if(istype(I, /mob/))
var/mob/M = I
listening += M
hearturfs += M.locs[1]
for(var/obj/O in M.contents)
listening_obj |= O
else if(istype(I, /obj/))
var/obj/O = I
hearturfs += O.locs[1]
listening_obj |= O
for(var/mob/M in player_list)
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
M.hear_say(message,verb,speaking,null,null, src)
continue
if(M.loc && M.locs[1] in hearturfs)
M.hear_say(message,verb,speaking,null,null, src)
rendered_a = "<span class='game say'><span class='name'>[name]</span> [verb], <span class='message'>\"[message]\"</span></span>"
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [verb], <span class='message'>\"[message_stars]\"</span></span>"
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [verb], <span class='message'><span class='body'>\"[message]\"</span></span></span></i>"//The AI can "hear" its own message.
for(var/mob/M in hearers(T.loc))//The location is the object, default distance.
if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to.
M.show_message(rendered_a, 2)
else//If they do not.
M.show_message(rendered_b, 2)
/*Radios "filter out" this conversation channel so we don't need to account for them.
This is another way of saying that we won't bother dealing with them.*/
else
src << "No holopad connected."
return 0
@@ -132,6 +132,9 @@
updatehealth()
return 1*/
/mob/living/silicon/attack_throat()
return
/proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai)
if(!istype(bot) || !istype(ai))
return 0
@@ -22,6 +22,7 @@
var/obj/item/inventory_head
var/obj/item/inventory_back
var/facehugger
//IAN! SQUEEEEEEEEE~
/mob/living/simple_animal/corgi/Ian
@@ -122,6 +123,13 @@
var/icon/back_icon = image('icons/mob/corgi_back.dmi',back_icon_state)
if(back_icon)
overlays += back_icon
if(facehugger)
if(istype(src, /mob/living/simple_animal/corgi/puppy))
overlays += image('icons/mob/mask.dmi',"facehugger_corgipuppy")
else
overlays += image('icons/mob/mask.dmi',"facehugger_corgi")
return
@@ -14,11 +14,6 @@
emote_see = list("jiggles", "bounces in place")
var/colour = "grey"
/mob/living/simple_animal/slime/can_force_feed(var/feeder, var/food, var/feedback)
if(feedback)
feeder << "Where do you intend to put \the [food]? \The [src] doesn't have a mouth!"
return 0
/mob/living/simple_animal/adultslime
name = "pet slime"
desc = "A lovable, domesticated slime."
@@ -130,7 +130,7 @@
return 0
else
O.attack(src, user, user.zone_sel.selecting)
attacked_with_item(O, user)
/mob/living/simple_animal/spiderbot/emag_act(var/remaining_charges, var/mob/user)
if (emagged)
@@ -286,28 +286,28 @@
if(istype(O, /obj/item/weapon/material/knife) || istype(O, /obj/item/weapon/material/knife/butch))
harvest(user)
else
if(!O.force)
visible_message("<span class='notice'>[user] gently taps [src] with \the [O].</span>")
else
O.attack(src, user, user.zone_sel.selecting)
attacked_with_item(O, user)
/mob/living/simple_animal/hit_with_weapon(obj/item/O, mob/living/user, var/effective_force, var/hit_zone)
//TODO: refactor mob attackby(), attacked_by(), and friends.
/mob/living/simple_animal/proc/attacked_with_item(var/obj/item/O, var/mob/user)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if(!O.force)
visible_message("<span class='notice'>[user] gently taps [src] with \the [O].</span>")
return
if(O.force > resistance)
var/damage = O.force
if (O.damtype == HALLOSS)
damage = 0
if(supernatural && istype(O,/obj/item/weapon/nullrod))
damage *= 2
purge = 3
adjustBruteLoss(damage)
else
usr << "<span class='danger'>This weapon is ineffective, it does no damage.</span>"
visible_message("<span class='danger'>\The [src] has been attacked with \the [O] by [user].</span>")
if(O.force <= resistance)
user << "<span class='danger'>This weapon is ineffective, it does no damage.</span>"
return 2
var/damage = O.force
if (O.damtype == HALLOSS)
damage = 0
if(supernatural && istype(O,/obj/item/weapon/nullrod))
damage *= 2
purge = 3
adjustBruteLoss(damage)
return 0
user.do_attack_animation(src)
/mob/living/simple_animal/movement_delay()
var/tally = 0 //Incase I need to add stuff other than "speed" later
-6
View File
@@ -498,12 +498,6 @@ proc/is_blind(A)
/mob/proc/is_client_active(var/active = 1)
return client && client.inactivity < active MINUTES
/mob/proc/can_eat()
return 1
/mob/proc/can_force_feed()
return 1
#define SAFE_PERP -50
/mob/living/proc/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
if(stat == DEAD)
+3 -3
View File
@@ -289,7 +289,7 @@
proc/AttemptLateSpawn(rank,var/spawning_at)
if(src != usr)
if (src != usr)
return 0
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
usr << "\red The round is either not ready, or has already finished..."
@@ -323,7 +323,7 @@
character.loc = C.loc
AnnounceCyborg(character, rank, "has been downloaded to the empty core in \the [character.loc.loc]")
ticker.mode.handle_latejoin(character)
ticker.mode.latespawn(character)
qdel(C)
qdel(src)
@@ -338,7 +338,7 @@
character.buckled.loc = character.loc
character.buckled.set_dir(character.dir)
ticker.mode.handle_latejoin(character)
ticker.mode.latespawn(character)
if(character.mind.assigned_role != "Cyborg")
data_core.manifest_inject(character)
@@ -1,7 +1,11 @@
datum/preferences
//The mob should have a gender you want before running this proc. Will run fine without H
proc/randomize_appearance_for(var/mob/living/carbon/human/H)
gender = pick(MALE, FEMALE)
if(H)
if(H.gender == MALE)
gender = MALE
else
gender = FEMALE
s_tone = random_skin_tone()
h_style = random_hair_style(gender, species)
f_style = random_facial_hair_style(gender, species)
@@ -211,18 +215,18 @@ datum/preferences
preview_icon.Blend(temp, ICON_OVERLAY)
// Skin color
if(current_species && (current_species.appearance_flags & HAS_SKIN_COLOR))
if(current_species && (current_species.flags & HAS_SKIN_COLOR))
preview_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
// Skin tone
if(current_species && (current_species.appearance_flags & HAS_SKIN_TONE))
if(current_species && (current_species.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")
if ((current_species && (current_species.appearance_flags & HAS_EYE_COLOR)))
if ((current_species && (current_species.flags & HAS_EYE_COLOR)))
eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD)
var/datum/sprite_accessory/hair_style = hair_styles_list[h_style]
@@ -238,16 +242,15 @@ datum/preferences
eyes_s.Blend(facial_s, ICON_OVERLAY)
var/icon/underwear_s = null
if(underwear && current_species.appearance_flags & HAS_UNDERWEAR)
// if(underwear)
if(underwear && current_species.flags & HAS_UNDERWEAR)
underwear_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = underwear)
var/icon/undershirt_s = null
if(undershirt && current_species.appearance_flags & HAS_UNDERWEAR)
if(undershirt && current_species.flags & HAS_UNDERWEAR)
undershirt_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = undershirt)
var/icon/socks_s = null
if(socks && current_species.appearance_flags & HAS_UNDERWEAR)
if(socks && current_species.flags & HAS_UNDERWEAR)
socks_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = socks)
var/icon/clothes_s = null
+24
View File
@@ -161,6 +161,30 @@
qdel(src)
return O
//human -> alien
/mob/living/carbon/human/proc/Alienize()
if (transforming)
return
for(var/obj/item/W in src)
drop_from_inventory(W)
regenerate_icons()
transforming = 1
canmove = 0
icon = null
invisibility = 101
for(var/t in organs)
qdel(t)
var/alien_caste = pick("Hunter","Sentinel","Drone")
var/mob/living/carbon/human/new_xeno = create_new_xenomorph(alien_caste,loc)
new_xeno.a_intent = I_HURT
new_xeno.key = key
new_xeno << "<B>You are now an alien.</B>"
qdel(src)
return
/mob/living/carbon/human/proc/slimeize(adult as num, reproduce as num)
if (transforming)
return
@@ -33,7 +33,7 @@
return 1
if(href_list["skin_tone"])
if(can_change_skin_tone())
var/new_s_tone = input(usr, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", -owner.s_tone + 35) as num|null
var/new_s_tone = input(usr, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", owner.s_tone) as num|null
if(isnum(new_s_tone) && can_still_topic(state))
new_s_tone = 35 - max(min( round(new_s_tone), 220),1)
return owner.change_skin_tone(new_s_tone)
-3
View File
@@ -240,9 +240,6 @@ var/list/organ_cache = list()
if(parent && !silent)
owner.custom_pain("Something inside your [parent.name] hurts a lot.", 1)
/obj/item/organ/proc/bruise()
damage = max(damage, min_bruised_damage)
/obj/item/organ/proc/robotize() //Being used to make robutt hearts, etc
robotic = 2
src.status &= ~ORGAN_BROKEN
+10 -37
View File
@@ -807,46 +807,15 @@ Note that amputating the affected organ does in fact remove the infection from t
"\The [holder.legcuffed.name] falls off you.")
holder.drop_from_inventory(holder.legcuffed)
// checks if all wounds on the organ are bandaged
/obj/item/organ/external/proc/is_bandaged()
for(var/datum/wound/W in wounds)
if(W.internal) continue
if(!W.bandaged)
return 0
return 1
// checks if all wounds on the organ are salved
/obj/item/organ/external/proc/is_salved()
for(var/datum/wound/W in wounds)
if(W.internal) continue
if(!W.salved)
return 0
return 1
// checks if all wounds on the organ are disinfected
/obj/item/organ/external/proc/is_disinfected()
for(var/datum/wound/W in wounds)
if(W.internal) continue
if(!W.disinfected)
return 0
return 1
/obj/item/organ/external/proc/bandage()
var/rval = 0
status &= ~ORGAN_BLEEDING
src.status &= ~ORGAN_BLEEDING
for(var/datum/wound/W in wounds)
if(W.internal) continue
rval |= !W.bandaged
W.bandaged = 1
return rval
/obj/item/organ/external/proc/salve()
var/rval = 0
for(var/datum/wound/W in wounds)
rval |= !W.salved
W.salved = 1
return rval
/obj/item/organ/external/proc/disinfect()
var/rval = 0
for(var/datum/wound/W in wounds)
@@ -865,6 +834,13 @@ Note that amputating the affected organ does in fact remove the infection from t
W.clamped = 1
return rval
/obj/item/organ/external/proc/salve()
var/rval = 0
for(var/datum/wound/W in wounds)
rval |= !W.salved
W.salved = 1
return rval
/obj/item/organ/external/proc/fracture()
if(status & ORGAN_ROBOT)
return //ORGAN_BROKEN doesn't have the same meaning for robot limbs
@@ -963,14 +939,11 @@ Note that amputating the affected organ does in fact remove the infection from t
/obj/item/organ/external/proc/is_malfunctioning()
return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam))
/obj/item/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0, var/supplied_message)
/obj/item/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0)
if(!owner || loc != owner)
return
if(!silent)
if(supplied_message)
owner.visible_message("<span class='danger'>[supplied_message]</span>")
else
owner.visible_message("<span class='danger'>\The [W] sticks in the wound!</span>")
owner.visible_message("<span class='danger'>\The [W] sticks in the wound!</span>")
implants += W
owner.embedded_flag = 1
owner.verbs += /mob/proc/yank_out_object
+5 -22
View File
@@ -38,32 +38,15 @@
icon_state = "xgibtorso"
organ_tag = "acid gland"
/obj/item/organ/xenos/resinspinner
name = "resin spinner"
parent_organ = "head"
icon_state = "xgibmid2"
organ_tag = "resin spinner"
/obj/item/organ/xenos/hivenode
name = "hive node"
parent_organ = "chest"
icon_state = "xgibmid2"
organ_tag = "hive node"
/obj/item/organ/xenos/hivenode/removed(var/mob/living/user)
if(owner && ishuman(owner))
var/mob/living/carbon/human/H = owner
H << "<span class='alium'>You feel your connection to the hivemind fray and fade away...</span>"
H.remove_language("Hivemind")
if(H.mind && H.species.get_bodytype() != "Xenomorph")
xenomorphs.remove_antagonist(H.mind)
..(user)
/obj/item/organ/xenos/resinspinner
name = "resin spinner"
parent_organ = "head"
icon_state = "xgibmid2"
organ_tag = "resin spinner"
/obj/item/organ/xenos/hivenode/replaced(var/mob/living/carbon/human/target,var/obj/item/organ/external/affected)
..(target, affected)
if(owner && ishuman(owner))
var/mob/living/carbon/human/H = owner
H.add_language("Hivemind")
if(H.mind && H.species.get_bodytype() != "Xenomorph")
H << "<span class='alium'>You feel a sense of pressure as a vast intelligence meshes with your thoughts...</span>"
xenomorphs.add_antagonist_mind(H.mind,1, xenomorphs.faction_role_text, xenomorphs.faction_welcome)
+4 -13
View File
@@ -140,15 +140,6 @@
return 0
proc/bandage()
bandaged = 1
proc/salve()
salved = 1
proc/disinfect()
disinfected = 1
// heal the given amount of damage, and if the given amount of damage was more
// than what needed to be healed, return how much heal was left
// set @heals_internal to also heal internal organ damage
@@ -327,15 +318,15 @@ datum/wound/cut/massive
/datum/wound/lost_limb/New(var/obj/item/organ/external/lost_limb, var/losstype, var/clean)
var/damage_amt = lost_limb.max_damage
if(clean) damage_amt /= 2
switch(losstype)
if(DROPLIMB_EDGE, DROPLIMB_BLUNT)
damage_type = CUT
max_bleeding_stage = 3 //clotted stump and above can bleed.
stages = list(
"ripped stump" = damage_amt*1.3,
"bloody stump" = damage_amt,
"clotted stump" = damage_amt*0.5,
"bloody stump" = damage_amt,
"clotted stump" = damage_amt*0.5,
"scarred stump" = 0
)
if(DROPLIMB_BURN)
@@ -346,7 +337,7 @@ datum/wound/cut/massive
"scarred stump" = damage_amt*0.5,
"scarred stump" = 0
)
..(damage_amt)
/datum/wound/lost_limb/can_merge(var/datum/wound/other)
-5
View File
@@ -171,11 +171,6 @@
brightness_power = 2
brightness_color = "#da0205"
/obj/machinery/light/small/red
brightness_range = 5
brightness_power = 1
brightness_color = "#da0205"
/obj/machinery/light/spot
name = "spotlight"
fitting = "large tube"
+2 -1
View File
@@ -348,8 +348,9 @@ var/list/solars_list = list()
/obj/machinery/power/solar_control/initialize()
..()
if(!connect_to_network()) return
if(!powernet) return
set_panels(cdir)
connect_to_network()
/obj/machinery/power/solar_control/update_icon()
if(stat & BROKEN)
+1 -1
View File
@@ -189,7 +189,7 @@
update_held_icon()
//update timing
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
user.setClickCooldown(4)
user.setMoveCooldown(move_delay)
next_fire_time = world.time + fire_delay
@@ -136,7 +136,6 @@
/obj/item/projectile/bullet/pistol/rubber //"rubber" bullets
name = "rubber bullet"
check_armour = "melee"
damage = 10
agony = 40
embed = 0
@@ -151,7 +150,6 @@
/obj/item/projectile/bullet/shotgun/beanbag //because beanbags are not bullets
name = "beanbag"
check_armour = "melee"
damage = 20
agony = 60
embed = 0
@@ -236,4 +234,4 @@
/obj/item/projectile/bullet/pistol/cap/process()
loc = null
qdel(src)
qdel(src)
@@ -22,13 +22,13 @@
//blind adjacent people
for (var/mob/living/carbon/M in viewers(T, flash_range))
if(M.eyecheck() < FLASH_PROTECTION_MODERATE)
if(M.eyecheck() < 1)
flick("e_flash", M.flash)
//snap pop
playsound(src, 'sound/effects/snap.ogg', 50, 1)
src.visible_message("<span class='warning'>\The [src] explodes in a bright flash!</span>")
new /obj/effect/decal/cleanable/ash(src.loc) //always use src.loc so that ash doesn't end up inside windows
new /obj/effect/effect/sparks(T)
new /obj/effect/effect/smoke/illumination(T, brightness=max(flash_range*2, brightness), lifetime=light_duration)
+7 -7
View File
@@ -304,7 +304,7 @@
trans_to(target, amount, multiplier, copy)
/datum/reagents/proc/trans_id_to(var/atom/target, var/id, var/amount = 1)
if (!target || !target.reagents || !target.simulated)
if (!target || !target.reagents)
return
amount = min(amount, get_reagent_amount(id))
@@ -333,7 +333,7 @@
return
/datum/reagents/proc/touch_mob(var/mob/target)
if(!target || !istype(target) || !target.simulated)
if(!target || !istype(target))
return
for(var/datum/reagent/current in reagent_list)
@@ -342,7 +342,7 @@
update_total()
/datum/reagents/proc/touch_turf(var/turf/target)
if(!target || !istype(target) || !target.simulated)
if(!target || !istype(target))
return
for(var/datum/reagent/current in reagent_list)
@@ -351,7 +351,7 @@
update_total()
/datum/reagents/proc/touch_obj(var/obj/target)
if(!target || !istype(target) || !target.simulated)
if(!target || !istype(target))
return
for(var/datum/reagent/current in reagent_list)
@@ -370,7 +370,7 @@
return trans_to_mob(target, amount, CHEM_TOUCH, perm, copy)
/datum/reagents/proc/trans_to_mob(var/mob/target, var/amount = 1, var/type = CHEM_BLOOD, var/multiplier = 1, var/copy = 0) // Transfer after checking into which holder...
if(!target || !istype(target) || !target.simulated)
if(!target || !istype(target))
return
if(iscarbon(target))
var/mob/living/carbon/C = target
@@ -389,7 +389,7 @@
R.touch_mob(target)
/datum/reagents/proc/trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Turfs don't have any reagents (at least, for now). Just touch it.
if(!target || !target.simulated)
if(!target)
return
var/datum/reagents/R = new /datum/reagents(amount * multiplier)
@@ -398,7 +398,7 @@
return
/datum/reagents/proc/trans_to_obj(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Objects may or may not; if they do, it's probably a beaker or something and we need to transfer properly; otherwise, just touch.
if(!target || !target.simulated)
if(!target)
return
if(!target.reagents)
+17 -11
View File
@@ -72,8 +72,13 @@
return
/obj/machinery/chem_master/Topic(href, href_list)
if(..())
return 1
if(stat & (BROKEN|NOPOWER)) return
if(usr.stat || usr.restrained()) return
if(!in_range(src, usr)) return
src.add_fingerprint(usr)
usr.set_machine(src)
if (href_list["ejectp"])
if(loaded_pill_bottle)
@@ -223,7 +228,7 @@
return src.attack_hand(user)
/obj/machinery/chem_master/attack_hand(mob/user as mob)
if(inoperable())
if(stat & BROKEN)
return
user.set_machine(src)
if(!(user.client in has_sprites))
@@ -332,8 +337,11 @@
/obj/machinery/computer/pandemic/Topic(href, href_list)
if(..())
return 1
if(stat & (NOPOWER|BROKEN)) return
if(usr.stat || usr.restrained()) return
if(!in_range(src, usr)) return
usr.set_machine(src)
if(!beaker) return
if (href_list["create_vaccine"])
@@ -641,12 +649,10 @@
return 0
/obj/machinery/reagentgrinder/attack_hand(mob/user as mob)
user.set_machine(src)
interact(user)
/obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu
if(inoperable())
return
user.set_machine(src)
var/is_chamber_empty = 0
var/is_beaker_ready = 0
var/processing_chamber = ""
@@ -693,8 +699,8 @@
/obj/machinery/reagentgrinder/Topic(href, href_list)
if(..())
return 1
return
usr.set_machine(src)
switch(href_list["action"])
if ("grind")
grind()
@@ -703,7 +709,7 @@
if ("detach")
detach()
src.updateUsrDialog()
return 1
return
/obj/machinery/reagentgrinder/proc/detach()
@@ -226,10 +226,6 @@
description = "This is what makes chilis hot."
reagent_state = LIQUID
color = "#B31008"
var/agony_dose = 5
var/agony_amount = 2
var/discomfort_message = "<span class='danger'>Your insides feel uncomfortably hot!</span>"
var/slime_temp_adj = 10
/datum/reagent/capsaicin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA)
@@ -243,82 +239,82 @@
var/mob/living/carbon/human/H = M
if(H.species && (H.species.flags & (NO_PAIN)))
return
if(dose < agony_dose)
if(prob(5) || dose == metabolism) //dose == metabolism is a very hacky way of forcing the message the first time this procs
M << discomfort_message
else
M.apply_effect(agony_amount, AGONY, 0)
if(dose < 5 && (dose == metabolism || prob(5)))
M << "<span class='danger'>Your insides feel uncomfortably hot!</span>"
if(dose >= 5)
M.apply_effect(2, AGONY, 0)
if(prob(5))
M.custom_emote(2, "[pick("dry heaves!","coughs!","splutters!")]")
M << "<span class='danger'>You feel like your insides are burning!</span>"
M.visible_message("<span class='warning'>[M] [pick("dry heaves!","coughs!","splutters!")]</span>", "<span class='danger'>You feel like your insides are burning!</span>")
if(istype(M, /mob/living/carbon/slime))
M.bodytemperature += rand(0, 15) + slime_temp_adj
M.bodytemperature += rand(10, 25)
holder.remove_reagent("frostoil", 5)
/datum/reagent/capsaicin/condensed
/datum/reagent/condensedcapsaicin
name = "Condensed Capsaicin"
id = "condensedcapsaicin"
description = "A chemical agent used for self-defense and in police work."
reagent_state = LIQUID
touch_met = 50 // Get rid of it quickly
color = "#B31008"
agony_dose = 0.5
agony_amount = 4
discomfort_message = "<span class='danger'>You feel like your insides are burning!</span>"
slime_temp_adj = 15
/datum/reagent/capsaicin/condensed/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
/datum/reagent/condensedcapsaicin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA)
return
M.adjustToxLoss(0.5 * removed)
/datum/reagent/condensedcapsaicin/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
var/eyes_covered = 0
var/mouth_covered = 0
var/no_pain = 0
var/obj/item/eye_protection = null
var/obj/item/face_protection = null
var/list/protection
var/obj/item/safe_thing = null
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
protection = list(H.head, H.glasses, H.wear_mask)
if(H.species && (H.species.flags & NO_PAIN))
no_pain = 1 //TODO: living-level can_feel_pain() proc
else
protection = list(M.wear_mask)
for(var/obj/item/I in protection)
if(I)
if(I.body_parts_covered & EYES)
return
if(H.head)
if(H.head.body_parts_covered & EYES)
eyes_covered = 1
eye_protection = I.name
if((I.body_parts_covered & FACE) && !(I.item_flags & FLEXIBLEMATERIAL))
safe_thing = H.head
if((H.head.body_parts_covered & FACE) && !(H.head.item_flags & FLEXIBLEMATERIAL))
mouth_covered = 1
face_protection = I.name
var/message = null
if(eyes_covered)
if(!mouth_covered)
message = "<span class='warning'>Your [eye_protection] protects your eyes from the pepperspray!</span>"
else
message = "<span class='warning'>The pepperspray gets in your eyes!</span>"
if(mouth_covered)
M.eye_blurry = max(M.eye_blurry, 15)
M.eye_blind = max(M.eye_blind, 5)
else
M.eye_blurry = max(M.eye_blurry, 25)
M.eye_blind = max(M.eye_blind, 10)
if(mouth_covered)
if(!message)
message = "<span class='warning'>Your [face_protection] protects you from the pepperspray!</span>"
else if(!no_pain)
message = "<span class='danger'>Your face and throat burn!</span>"
if(prob(25))
M.custom_emote(2, "[pick("coughs!","coughs hysterically!","splutters!")]")
safe_thing = H.head
if(H.wear_mask)
if(!eyes_covered && H.wear_mask.body_parts_covered & EYES)
eyes_covered = 1
safe_thing = H.wear_mask
if(!mouth_covered && (H.wear_mask.body_parts_covered & FACE) && !(H.wear_mask.item_flags & FLEXIBLEMATERIAL))
mouth_covered = 1
safe_thing = H.wear_mask
if(H.glasses && H.glasses.body_parts_covered & EYES)
if(!eyes_covered)
eyes_covered = 1
if(!safe_thing)
safe_thing = H.glasses
if(eyes_covered && mouth_covered)
M << "<span class='warning'>Your [safe_thing] protects you from the pepperspray!</span>"
return
else if(eyes_covered)
M << "<span class='warning'>Your [safe_thing] protect you from most of the pepperspray!</span>"
M.eye_blurry = max(M.eye_blurry, 15)
M.eye_blind = max(M.eye_blind, 5)
M.Stun(5)
M.Weaken(5)
return
else if (mouth_covered) // Mouth cover is better than eye cover
M << "<span class='warning'>Your [safe_thing] protects your face from the pepperspray!</span>"
M.eye_blurry = max(M.eye_blurry, 5)
return
else // Oh dear :D
M << "<span class='warning'>You're sprayed directly in the eyes with pepperspray!</span>"
M.eye_blurry = max(M.eye_blurry, 25)
M.eye_blind = max(M.eye_blind, 10)
M.Stun(5)
M.Weaken(5)
return
/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.species && (H.species.flags & (NO_PAIN)))
return
if(dose == metabolism)
M << "<span class='danger'>You feel like your insides are burning!</span>"
@@ -177,7 +177,11 @@
W.visible_message("<span class='notice'>The fungi are completely dissolved by the solution!</span>")
/datum/reagent/toxin/plantbgone/touch_obj(var/obj/O, var/volume)
if(istype(O, /obj/effect/plant))
if(istype(O, /obj/effect/alien/weeds/))
var/obj/effect/alien/weeds/alien_weeds = O
alien_weeds.health -= rand(15, 35)
alien_weeds.healthcheck()
else if(istype(O, /obj/effect/plant))
qdel(O)
/datum/reagent/toxin/plantbgone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
+1 -1
View File
@@ -1094,7 +1094,7 @@
var/list/borks = typesof(/obj/item/weapon/reagent_containers/food/snacks) - /obj/item/weapon/reagent_containers/food/snacks
playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1)
for(var/mob/living/carbon/human/M in viewers(get_turf(holder.my_atom), null))
if(M.eyecheck() < FLASH_PROTECTION_MODERATE)
if(M.eyecheck() <= 0)
flick("e_flash", M.flash)
for(var/i = 1, i <= 4 + rand(1,2), i++)
@@ -113,6 +113,9 @@
return ..()
/obj/machinery/chemical_dispenser/cartridge/ui_interact(mob/user, ui_key = "main",var/datum/nanoui/ui = null, var/force_open = 1)
if(stat & (BROKEN|NOPOWER)) return
if(user.stat || user.restrained()) return
// this is the data which will be sent to the ui
var/data[0]
data["amount"] = amount
@@ -145,8 +148,8 @@
ui.open()
/obj/machinery/chemical_dispenser/cartridge/Topic(href, href_list)
if(..())
return 1
if(stat & (NOPOWER|BROKEN))
return 0 // don't update UIs attached to this object
if(href_list["amount"])
amount = round(text2num(href_list["amount"]), 1) // round to nearest 1
@@ -168,7 +171,9 @@
return 1 // update UIs attached to this object
/obj/machinery/chemical_dispenser/cartridge/attack_ai(mob/user as mob)
ui_interact(user)
src.attack_hand(user)
/obj/machinery/chemical_dispenser/cartridge/attack_hand(mob/user as mob)
if(stat & BROKEN)
return
ui_interact(user)
+5 -2
View File
@@ -25,6 +25,11 @@
/obj/item/weapon/reagent_containers/attack_self(mob/user as mob)
return
/obj/item/weapon/reagent_containers/attack(mob/M as mob, mob/user as mob, def_zone)
if(can_operate(M))//Checks if mob is lying down on table for surgery
if(do_surgery(M, user, src))
return
/obj/item/weapon/reagent_containers/afterattack(obj/target, mob/user, flag)
return
@@ -101,7 +106,6 @@
user << "<span class='warning'>\The [blocked] is in the way!</span>"
return
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //puts a limit on how fast people can eat/drink things
self_feed_message(user)
reagents.trans_to_mob(user, amount_per_transfer_from_this, CHEM_INGEST)
feed_sound(user)
@@ -119,7 +123,6 @@
other_feed_message_start(user, target)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if(!do_mob(user, target))
return
@@ -25,10 +25,7 @@
if(standard_feed_mob(user, M))
return
afterattack(var/obj/target, var/mob/user, var/proximity)
if(!proximity)
return
afterattack(var/obj/target, var/mob/user, var/flag)
if(standard_dispenser_refill(user, target))
return
if(standard_pour_into(user, target))
@@ -23,9 +23,6 @@
flags |= OPENCONTAINER
attack(mob/M as mob, mob/user as mob, def_zone)
if(force && !(flags & NOBLUDGEON) && user.a_intent == I_HURT)
return ..()
if(standard_feed_mob(user, M))
return
@@ -96,6 +93,10 @@
volume = 150
flags = CONDUCT | OPENCONTAINER
/obj/item/weapon/reagent_containers/food/drinks/golden_cup/tournament_26_06_2011
desc = "A golden cup. It will be presented to a winner of tournament 26 june and name of the winner will be graved on it."
///////////////////////////////////////////////Drinks
//Notes by Darem: Drinks are simply containers that start preloaded. Unlike condiments, the contents can be ingested directly
// rather then having to add it to something else first. They should only contain liquids. They have a default container size of 50.

Some files were not shown because too many files have changed in this diff Show More