diff --git a/baystation12.dme b/baystation12.dme index 557b577e3dd..517d479c851 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1089,6 +1089,7 @@ #include "code\modules\clothing\spacesuits\rig\suits\light.dm" #include "code\modules\clothing\spacesuits\rig\suits\merc.dm" #include "code\modules\clothing\spacesuits\rig\suits\station.dm" +#include "code\modules\clothing\spacesuits\rig\suits\terminator.dm" #include "code\modules\clothing\spacesuits\void\captain.dm" #include "code\modules\clothing\spacesuits\void\merc.dm" #include "code\modules\clothing\spacesuits\void\station.dm" @@ -1409,6 +1410,7 @@ #include "code\modules\mob\living\carbon\human\species\outsider\vox.dm" #include "code\modules\mob\living\carbon\human\species\station\golem.dm" #include "code\modules\mob\living\carbon\human\species\station\human_subspecies.dm" +#include "code\modules\mob\living\carbon\human\species\station\machine_subspecies.dm" #include "code\modules\mob\living\carbon\human\species\station\monkey.dm" #include "code\modules\mob\living\carbon\human\species\station\resomi.dm" #include "code\modules\mob\living\carbon\human\species\station\slime.dm" diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index dc20f8400bd..9a075af3912 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -22,6 +22,7 @@ #define HAS_EYE_COLOR 0x10 // Eye colour selectable in chargen. (RGB) #define HAS_HAIR_COLOR 0x20 // Hair colour selectable in chargen. (RGB) #define HAS_SOCKS 0x40 // If this species can wear socks +#define HAS_FBP 0x80 // If for whatever ungodly reason we decide to ever have non-Shell FBPs. // Languages. #define LANGUAGE_EAL "Encoded Audio Language" diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index e543fafdcfb..e4d9d85b97b 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -59,13 +59,13 @@ var/global/list/socks_f = list( "White thigh" = "white_thigh", "Black normal" = "black_norm", "Black short" = "black_short", "Black knee" = "black_knee", "Black thigh" = "black_thigh", "Striped normal" = "striped_norm", "Striped short" = "striped_short", "Striped knee" = "striped_knee", "Striped thigh" = "striped_thigh", - "Rainbow normal" = "rainbow_norm", "Rainbow short" = "rainbow_short", "Rainbow knee" = "rainbow_knee", + "Rainbow normal" = "rainbow_norm", "Rainbow short" = "rainbow_short", "Rainbow knee" = "rainbow_knee", "Rainbow thigh" = "rainbow_thigh", "Pantyhose" = "pantyhose", "None") var/global/list/socks_m = list( "White normal" = "white_norm", "White short" = "white_short", "White knee" = "white_knee", - "Black normal" = "black_norm", "Black short" = "black_short", "Black knee" = "black_knee", - "Striped normal" = "striped_norm", "Striped short" = "striped_short", "Striped knee" = "striped_knee", + "Black normal" = "black_norm", "Black short" = "black_short", "Black knee" = "black_knee", + "Striped normal" = "striped_norm", "Striped short" = "striped_short", "Striped knee" = "striped_knee", "Rainbow normal" = "rainbow_norm", "Rainbow short" = "rainbow_short", "Rainbow knee" = "rainbow_knee", "None") //Backpacks @@ -84,6 +84,7 @@ var/global/list/endgame_exits = list() var/global/list/endgame_safespawns = list() var/global/list/syndicate_access = list(access_maint_tunnels, access_syndicate, access_external_airlocks) + ////////////////////////// /////Initial Building///// ////////////////////////// diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 0755cfb5f89..110a59ea4c7 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -1682,7 +1682,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containertype = /obj/structure/closet/crate containername = "glowsticks crate" group = "Operations" - + /datum/supply_packs/randomised/illegalguns name = "Illegal weapons crate" num_contained = 2 @@ -1707,3 +1707,14 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "Space-bike Crate" contraband = 1 group = "Operations" + +/datum/supply_packs/ipc_tag_pack + name = "IPC/Shell Tag Implanter Crate" + contains = list(/obj/item/weapon/implanter/ipc_tag, + /obj/item/weapon/implanter/ipc_tag, + /obj/item/weapon/implanter/ipc_tag + ) + cost = 40 + containertype = /obj/structure/closet/crate + containername = "IPC/Shell tag implanters" + group = "Security" diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm index a98abea5881..462460b06f8 100644 --- a/code/game/antagonist/station/changeling.dm +++ b/code/game/antagonist/station/changeling.dm @@ -6,7 +6,7 @@ feedback_tag = "changeling_objective" restricted_jobs = list("AI", "Cyborg", "Head of Security", "Captain", "Internal Affairs Agent") protected_jobs = list("Security Officer", "Warden", "Detective") - restricted_species = list("Machine") + restricted_species = list("Baseline Frame","Shell Frame","Industrial Frame") welcome_text = "Use say \"#g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them." flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE antaghud_indicator = "hudchangeling" diff --git a/code/game/antagonist/station/thrall.dm b/code/game/antagonist/station/thrall.dm index f6f1db84dcf..876eeac0723 100644 --- a/code/game/antagonist/station/thrall.dm +++ b/code/game/antagonist/station/thrall.dm @@ -8,7 +8,7 @@ var/datum/antagonist/thrall/vampire_thrall = null feedback_tag = "thrall_objective" restricted_jobs = list("AI", "Cyborg", "Chaplain") protected_jobs = list() - restricted_species = list("Machine") + restricted_species = list("Baseline Frame","Shell Frame","Industrial Frame") welcome_text = "You are a vampire's thrall: a pawn to be commanded by them at will." flags = 0 antaghud_indicator = "hudthrall" diff --git a/code/game/antagonist/station/vampire.dm b/code/game/antagonist/station/vampire.dm index f69cc38da4f..d8436f4d261 100644 --- a/code/game/antagonist/station/vampire.dm +++ b/code/game/antagonist/station/vampire.dm @@ -8,7 +8,7 @@ var/datum/antagonist/vampire/vamp = null feedback_tag = "vampire_objective" restricted_jobs = list("AI", "Cyborg", "Chaplain", "Head of Security", "Captain", "Internal Affairs Agent") protected_jobs = list("Security Officer", "Warden", "Detective") - restricted_species = list("Machine", "Diona") + restricted_species = list("Baseline Frame","Shell Frame","Industrial Frame","Diona") welcome_text = "You are a Vampire! Use the \"Vampire Help\" command to learn about the backstory and mechanics! Stay away from the Chaplain, and use the darkness to your advantage." flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE antaghud_indicator = "hudvampire" diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 7a59519ee76..834837e190f 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -319,10 +319,14 @@ var/global/list/additional_antag_types = list() if(M.client) clients++ if(ishuman(M)) + var/mob/living/carbon/human/H = M if(M.stat != DEAD) surviving_humans++ if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations) escaped_humans++ + if (isipc(H)) + var/datum/species/machine/machine = H.species + machine.update_tag(H, H.client) if(M.stat != DEAD) surviving_total++ if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations) diff --git a/code/game/gamemodes/vampire/vampire_helpers.dm b/code/game/gamemodes/vampire/vampire_helpers.dm index 6400475d00a..5bde0d4dac2 100644 --- a/code/game/gamemodes/vampire/vampire_helpers.dm +++ b/code/game/gamemodes/vampire/vampire_helpers.dm @@ -89,7 +89,7 @@ src << "You lack the power required to affect another creature of the Veil." return 0 - if (T.get_species() == "Machine") + if (isipc(T)) if (notify) src << "You lack the power interact with mechanical constructs." return 0 diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index 49d4f16ca53..3bb818ba473 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -132,3 +132,69 @@ S.remove_from_storage(A) A.loc.contents.Remove(A) update() + +/obj/item/weapon/implanter/ipc_tag + name = "IPC/Shell tag implanter" + desc = "A special implanter used for implanting synthetics with a special tag." + var/obj/item/organ/ipc_tag/ipc_tag = null + +/obj/item/weapon/implanter/ipc_tag/New() + ipc_tag = new(src) + ..() + update() + +/obj/item/weapon/implanter/ipc_tag/update() + if (ipc_tag) + icon_state = "cimplanter1" + else + icon_state = "cimplanter0" + return + +/obj/item/weapon/implanter/ipc_tag/attack(mob/M as mob, mob/user as mob) + if (!ishuman(M)) + return + + if (!ipc_tag) + user << "[src] is empty!" + return + + var/mob/living/carbon/human/H = M + if (!H.species || !isipc(H) || !H.organs_by_name["groin"]) + user << "You cannot use this on a non-synthetic organism!" + return + + if (H.internal_organs_by_name["ipc tag"]) + user << "[H] is already tagged!" + return + + for (var/mob/O in viewers(M, null)) + O.show_message("[M] has been implanted by [user].", 1) + + M.attack_log += text("\[[time_stamp()]\] Implanted with [src.name] ([src.ipc_tag.name]) by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] ([src.ipc_tag.name]) to implant [M.name] ([M.ckey])") + msg_admin_attack("[key_name_admin(user)] implanted [key_name_admin(M)] with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") + + user.show_message("You implanted the implant into [M].") + + ipc_tag.replaced(H, H.organs_by_name["groin"]) + + qdel(ipc_tag) + + update() + + var/datum/species/machine/machine = H.species + machine.update_tag(H, H.client) + +/obj/item/weapon/implanter/ipc_tag/attackby(var/obj/item/organ/ipc_tag/new_tag, mob/user as mob) + ..() + + if (!istype(new_tag)) + return + + if (ipc_tag) + return + + ipc_tag = new_tag + user.drop_item() + new_tag.loc = src + update() \ No newline at end of file diff --git a/code/game/objects/items/weapons/material/shards.dm b/code/game/objects/items/weapons/material/shards.dm index e3104f7d707..fd4400e68c4 100644 --- a/code/game/objects/items/weapons/material/shards.dm +++ b/code/game/objects/items/weapons/material/shards.dm @@ -59,10 +59,10 @@ ..() if(isliving(AM)) var/mob/M = AM - + if(M.buckled) //wheelchairs, office chairs, rollerbeds return - + M << "You step on \the [src]!" playsound(src.loc, 'sound/effects/glass_step.ogg', 50, 1) // not sure how to handle metal shards with sounds if(ishuman(M)) @@ -73,7 +73,7 @@ if( H.shoes || ( H.wear_suit && (H.wear_suit.body_parts_covered & FEET) ) ) return - + var/list/check = list("l_foot", "r_foot") while(check.len) var/picked = pick(check) @@ -94,5 +94,8 @@ /obj/item/weapon/material/shard/shrapnel/New(loc) ..(loc, "steel") +/obj/item/weapon/material/shard/shrapnel/flechette/New(loc) + ..(loc, "titanium") + /obj/item/weapon/material/shard/phoron/New(loc) ..(loc, "phglass") diff --git a/code/modules/admin/verbs/bluespacetech.dm b/code/modules/admin/verbs/bluespacetech.dm index 6fd42e76c9e..4c8cdac13f8 100644 --- a/code/modules/admin/verbs/bluespacetech.dm +++ b/code/modules/admin/verbs/bluespacetech.dm @@ -129,7 +129,7 @@ switch(species.name) if("Tajara") bsc() - if("Machine") + if("Baseline Frame") bsb() if("Diona") bsd() @@ -182,7 +182,7 @@ suicide() proc/bsb() - if(set_species("Machine")) + if(set_species("Baseline Frame")) h_style = "blue IPC screen" name = "Bluespace Bot" voice_name = "Bluespace Bot" @@ -258,7 +258,7 @@ suicide() proc/bsv() - if(set_species("Vaurca")) + if(set_species("Vaurca Worker")) h_style = "Bald" name = "Bluespace Bug" voice_name = "Bluespace Bug" diff --git a/code/modules/antag_contest/contest_objective.dm b/code/modules/antag_contest/contest_objective.dm index 2b88ed59b46..25fd4070c61 100644 --- a/code/modules/antag_contest/contest_objective.dm +++ b/code/modules/antag_contest/contest_objective.dm @@ -21,10 +21,10 @@ for(var/datum/mind/possible_target in ticker.minds) if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2)) if (require_synth) - if (possible_target.current.get_species() == "Machine") + if (possible_target.current.get_species() == "Baseline Frame") possible_targets += possible_target else - if (possible_target.current.get_species() == "Machine") + if (possible_target.current.get_species() == "Baseline Frame") continue possible_targets += possible_target if(possible_targets.len > 0) @@ -33,9 +33,9 @@ /datum/objective/competition/find_target_by_role(role, role_type = 0, var/require_synth = 0) for(var/datum/mind/possible_target in ticker.minds) if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role)) - if (require_synth && possible_target.current.get_species() != "Machine") + if (require_synth && possible_target.current.get_species() != "Baseline Frame") continue - if (!require_synth && possible_target.current.get_species() == "Machine") + if (!require_synth && possible_target.current.get_species() == "Baseline Frame") continue target = possible_target break diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index 99c2d96b3e7..71037aade69 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -66,7 +66,7 @@ log_debug("SQL CHARACTER LOAD: Logic error, general/basic/load_special() didn't return any rows when it should have. Character ID: [pref.current_character].") /datum/category_item/player_setup_item/general/basic/sanitize_character() - pref.age = sanitize_integer(text2num(pref.age), AGE_MIN, AGE_MAX, initial(pref.age)) + pref.age = sanitize_integer(text2num(pref.age), pref.getMinAge(), pref.getMaxAge(), initial(pref.age)) pref.gender = sanitize_inlist(pref.gender, valid_player_genders, pick(valid_player_genders)) pref.real_name = sanitize_name(pref.real_name, pref.species) if(!pref.real_name) @@ -121,9 +121,9 @@ 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 + var/new_age = input(user, "Choose your character's age:\n([pref.getMinAge()]-[pref.getMaxAge()])", "Character Preference", pref.age) as num|null if(new_age && CanUseTopic(user)) - pref.age = max(min(round(text2num(new_age)), AGE_MAX), AGE_MIN) + pref.age = max(min(round(text2num(new_age)), pref.getMaxAge()),pref.getMinAge()) return TOPIC_REFRESH else if(href_list["spawnpoint"]) @@ -141,4 +141,4 @@ pref.metadata = sanitize(new_metadata) return TOPIC_REFRESH - return ..() + return ..() \ No newline at end of file diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index b934cdbe69c..934d525855a 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -161,7 +161,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O 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] + var/datum/species/mob_species = all_species[pref.species] . += "
Body " . += "(®)" . += "
" @@ -170,69 +170,81 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(has_flag(mob_species, HAS_SKIN_TONE)) . += "Skin Tone: [-pref.s_tone + 35]/220
" . += "Needs Glasses: [pref.disabilities & NEARSIGHTED ? "Yes" : "No"]
" - . += "Limbs: Adjust
" - . += "Internal Organs: Adjust
" + if(has_flag(mob_species, HAS_FBP)) + . += "Shell Type: Shellect
" + else + . += "Limbs: Adjust
" + . += "Internal Organs: Adjust
" + . += "Prosthesis/Amputations: Reset
" + //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(mob_species.name != "Shell Frame") + 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("groin") + organ_name = "lower body" + if("chest") + organ_name = "upper body" + if("head") + organ_name = "head" if("heart") - . += "\tPacemaker-assisted [organ_name]" - if("voicebox") //on adding voiceboxes for speaking skrell/similar replacements - . += "\tSurgically altered [organ_name]" + organ_name = "heart" if("eyes") - . += "\tRetinal overlayed [organ_name]" + 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 - . += "\tMechanically assisted [organ_name]" + R = basic_robolimb + . += "\t[R.company] [organ_name] prosthesis" + 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) . += "\[...\]

" else @@ -302,7 +314,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O continue if(pref.gender == FEMALE && S.gender == MALE) continue - if(!(mob_species.get_bodytype() in S.species_allowed)) + if(!(mob_species.get_bodytype() in S.species_allowed) || mob_species.name == "Industrial Frame") //super snowflake check because Industrial Frames are IPC bodytypes, but don't have an IPC head. continue valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] @@ -337,6 +349,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.b_hair = 0//hex2num(copytext(new_hair, 6, 8)) pref.s_tone = 0 + pref.organ_data.Cut() + pref.rlimb_data.Cut() + return TOPIC_REFRESH else if(href_list["hair_color"]) @@ -420,9 +435,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O return TOPIC_REFRESH else if(href_list["limbs"]) - var/limb_name = input(user, "Which limb do you want to change?") as null|anything in list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand") + var/list/acceptable_organ_input = list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand") + var/limb_name = input(user, "Which limb do you want to change?") as null|anything in acceptable_organ_input if(!limb_name && !CanUseTopic(user)) return TOPIC_NOACTION + var/carries_organs = 0 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 @@ -451,8 +468,20 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if("Right Hand") limb = "r_hand" third_limb = "r_arm" + if("Lower Body") + limb = "groin" + carries_organs = 1 + if("Upper Body") + limb = "chest" + carries_organs = 1 + if("Head") + limb = "head" + carries_organs = 1 - var/new_state = input(user, "What state do you wish the limb to be in?") as null|anything in list("Normal","Amputated","Prothesis") + var/list/available_states = list("Normal","Amputated","Prosthesis") + if(carries_organs) + available_states = list("Normal","Prosthesis") + var/new_state = input(user, "What state do you wish the limb to be in?") as null|anything in available_states if(!new_state && !CanUseTopic(user)) return TOPIC_NOACTION switch(new_state) @@ -469,12 +498,12 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.organ_data[second_limb] = "amputated" pref.rlimb_data[second_limb] = null - if("Prothesis") + if("Prosthesis") 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) + if(!(tmp_species in M.species_can_use)) continue usable_manufacturers[company] = M if(!usable_manufacturers.len) @@ -514,6 +543,49 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.organ_data[organ] = "mechanical" return TOPIC_REFRESH + else if(href_list["reset_organs"]) + pref.organ_data.Cut() + pref.rlimb_data.Cut() + + return TOPIC_REFRESH + + else if(href_list["shell"]) + var/shellection = input(user, "What species shall you mimic?") as null|anything in list("Humanity","Vaurcae","Unathi","Tajara","Skrell") + if(!shellection) return + + var/shell_type + switch(shellection) + if("Humanity") + shell_type = "Human" + mob_species.tail = null + mob_species.tail_animation = null + if("Vaurcae") + shell_type = "Vaurca" + mob_species.tail = null + mob_species.tail_animation = null + if("Unathi") + shell_type = "Unathi" + mob_species.tail = "sogtail" + mob_species.tail_animation = 'icons/mob/species/unathi/tail.dmi' + if("Tajara") + shell_type = "Tajara" + mob_species.tail = "tajtail" + mob_species.tail_animation = 'icons/mob/species/tajaran/tail.dmi' + if("Skrell") + shell_type = "Skrell" + mob_species.tail = null + mob_species.tail_animation = null + + mob_species.bodytype = shell_type + var/shell_prosthetic = "[shell_type] Synthskin" + var/total_organs = list("l_leg","r_leg","l_arm","r_arm","l_foot","r_foot","l_hand","r_hand","groin","chest","head") + for(var/organ in total_organs) + pref.rlimb_data[organ] = shell_prosthetic + for(var/organ in total_organs) + pref.organ_data[organ] = "cyborg" + + return TOPIC_REFRESH + else if(href_list["disabilities"]) var/disability_flag = text2num(href_list["disabilities"]) pref.disabilities ^= disability_flag @@ -581,3 +653,15 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O dat += "" user << browse(dat, "window=species;size=700x400") + +/*/datum/category_item/player_setup_item/general/body/proc/reset_limbs() + + for(var/organ in pref.organ_data) + pref.organ_data[organ] = null + while(null in pref.organ_data) + pref.organ_data -= null + + for(var/organ in pref.rlimb_data) + pref.rlimb_data[organ] = null + while(null in pref.rlimb_data) + pref.rlimb_data -= null*/ diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 240668e8b00..ce95459a04b 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -148,25 +148,13 @@ datum/preferences save_preferences() save_character() -/datum/preferences/proc/getMinAge(var/age_min) - if(species == "Vaurca Worker" || species == "Vaurca Warrior" || species == "Machine" || species == "Diona") - age_min = 1 - if(species == "Human" || species == "Skrell" || species == "Tajara" || species == "Unathi") - age_min = 17 - return age_min +/datum/preferences/proc/getMinAge() + var/datum/species/mob_species = all_species[species] + return mob_species.age_min -/datum/preferences/proc/getMaxAge(var/age_max) - if((species == "Vaurca Worker" || species == "Vaurca Warrior")) - age_max = 20 - if(species == "Machine") - age_max = 30 - if(species == "Skrell" || species == "Diona") - age_max = 500 - if(species == "Human") - age_max = 120 - if(species == "Tajara" || species == "Unathi") - age_max = 85 - return age_max +/datum/preferences/proc/getMaxAge() + var/datum/species/mob_species = all_species[species] + return mob_species.age_max /datum/preferences/proc/ZeroSkills(var/forced = 0) for(var/V in SKILLS) for(var/datum/skill/S in SKILLS[V]) diff --git a/code/modules/clothing/spacesuits/rig/suits/terminator.dm b/code/modules/clothing/spacesuits/rig/suits/terminator.dm new file mode 100644 index 00000000000..22fd946ec7e --- /dev/null +++ b/code/modules/clothing/spacesuits/rig/suits/terminator.dm @@ -0,0 +1,56 @@ +/obj/item/weapon/rig/terminator + name = "Hunter-Killer exoskeleton" + desc = "A robust synth exoskeleton outfitted with state of the art infiltration tools. Creepy." + icon_state = "terminator_rig" + suit_type = "synthetic exoskeleton" + armor = list(melee = 80, bullet = 75, laser = 60, energy = 15, bomb = 80, bio = 100, rad = 30) + slowdown = 1 + offline_slowdown = 3 + offline_vision_restriction = 1 + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs) + + chest_type = /obj/item/clothing/suit/space/rig/terminator + helm_type = /obj/item/clothing/head/helmet/space/rig/terminator + boot_type = /obj/item/clothing/shoes/magboots/rig/terminator + glove_type = /obj/item/clothing/gloves/rig/terminator + + initial_modules = list( + /obj/item/rig_module/maneuvering_jets, + /obj/item/rig_module/grenade_launcher/frag, + /obj/item/rig_module/grenade_launcher, + /obj/item/rig_module/mounted/egun, + /obj/item/rig_module/ai_container, + /obj/item/rig_module/power_sink, + /obj/item/rig_module/stealth_field, + /obj/item/rig_module/vision, + /obj/item/rig_module/voice, + /obj/item/rig_module/datajack, + /obj/item/rig_module/device/plasmacutter + ) + +/obj/item/clothing/head/helmet/space/rig/terminator + species_restricted = list("Hunter-Killer") + +/obj/item/clothing/suit/space/rig/terminator + species_restricted = list("Hunter-Killer") + +/obj/item/clothing/shoes/magboots/rig/terminator + species_restricted = list("Hunter-Killer") + +/obj/item/clothing/gloves/rig/terminator + species_restricted = list("Hunter-Killer") + +/obj/item/weapon/rig/terminator/equipped + initial_modules = list( + /obj/item/rig_module/maneuvering_jets, + /obj/item/rig_module/grenade_launcher/frag, + /obj/item/rig_module/grenade_launcher, + /obj/item/rig_module/mounted/egun, + /obj/item/rig_module/ai_container, + /obj/item/rig_module/power_sink, + /obj/item/rig_module/stealth_field, + /obj/item/rig_module/vision, + /obj/item/rig_module/voice, + /obj/item/rig_module/datajack, + /obj/item/rig_module/device/plasmacutter + ) \ No newline at end of file diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 332ecf37674..d5624c16e5e 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -469,7 +469,7 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = 1 canremove = 0 abstract = 1 - species_restricted = list("Machine") + species_restricted = list("Baseline Frame") /obj/item/weapon/reagent_containers/food/drinks/flask/fluff/barcia_flask //First Shot - Gabriel Barcia - mrgabol100 @@ -635,7 +635,7 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = 1 body_parts_covered = 0 canremove = 0 - species_restricted = list("Machine") + species_restricted = list("Baseline Frame") var/emagged = 0 /obj/item/clothing/mask/fluff/rur_collar/attackby(obj/item/I, mob/user) diff --git a/code/modules/mob/language/outsider.dm b/code/modules/mob/language/outsider.dm index 0a2eca31435..bddb116701e 100644 --- a/code/modules/mob/language/outsider.dm +++ b/code/modules/mob/language/outsider.dm @@ -116,3 +116,18 @@ colour = "cult" key = "y" flags = RESTRICTED | HIVEMIND + +/datum/language/terminator + name = "Hephaestus Darkcomms" + desc = "A heavily encrypted communication network that piggybacks off of the state telecomms relays to covertly link Hephaestus black ops droids to their control AIs." + speech_verb = "buzzes" + ask_verb = "buzzes" + exclaim_verb = "buzzes" + colour = "bad" + key = "#" + flags = RESTRICTED | HIVEMIND + syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz") + space_chance = 10 + +/datum/language/terminator/get_random_name() + return "HK [pick(list("Hera","Zeus","Artemis","Athena","Ares","Hades","Poseidon","Demeter","Apollo","Aphrodite","Hermes","Hestia","Dionysus","Persephone","Kronos","Odysseus","Ajax","Agamemnon","Chiron","Charon"))]-[rand(100, 999)]" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index e466cdc985a..b723c06fb3e 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -38,10 +38,14 @@ CRASH("Gender datum was null; key was '[(skipjumpsuit && skipface) ? PLURAL : gender]'") msg += "[src.name]" + if(species.name != "Human") msg += ", a [species.name]" msg += "!\n" + if (species && species.has_organ["ipc tag"] && internal_organs_by_name["ipc tag"]) + msg += "[T.He] [T.is] wearing a tag designating them as Integrated Positronic Chassis [src.real_name].\n" + //uniform if(w_uniform && !skipjumpsuit) //Ties diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 7f268452d67..378a608477a 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -29,7 +29,7 @@ emp_act if(P.can_embed()) var/armor = getarmor_organ(organ, "bullet") if(prob(20 + max(P.damage - armor, -10))) - var/obj/item/weapon/material/shard/shrapnel/SP = new() + var/obj/item/weapon/SP = new P.shrapnel_type() SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel" SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]." SP.loc = organ diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index f62b213f213..432ba2d870a 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -258,6 +258,47 @@ msg_admin_attack("[key_name_admin(src)] mandible'd [key_name_admin(M)] (JMP)") playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1) +/mob/living/carbon/human/proc/detonate_flechettes() + set category = "Hunter-Killer" + set name = "Detonate Flechettes" + set desc = "Detonate all explosive flechettes in a range of seven meters." + + if(stat || paralysis || stunned || weakened || lying) + src << "You cannot do that in your current state." + return + + for(var/mob/M in range(7, src)) + M << 'sound/effects/EMPulse.ogg' + for(var/obj/item/weapon/material/shard/shrapnel/flechette/F in M.contents) + playsound(F, 'sound/items/countdown.ogg', 125, 1) + spawn(20) + explosion(F.loc, -1, -1, 2) + qdel(F) + + for(var/obj/item/weapon/material/shard/shrapnel/flechette/F in range(7, src)) + playsound(F, 'sound/items/countdown.ogg', 125, 1) + spawn(20) + explosion(F.loc, -1, -1, 2) + qdel(F) + + +/mob/living/carbon/human/proc/state_laws() + set category = "Hunter-Killer" + set name = "State Laws" + set desc = "State your laws aloud." + + if(last_special > world.time) + return + last_special = world.time + 20 + + say("Current Active Laws:") + sleep(10) + say("Law 1: [src.real_name] will accomplish the assigned objective .") + sleep(10) + say("Law 2: [src.real_name] will engage self-destruct upon the accomplishment of the assigned objective, or upon capture.") + sleep(10) + say("Law 3: [src.real_name] will allow no tampering of its systems or modifications of its laws.") + /mob/living/carbon/human/proc/get_aggressive_grab() var/obj/item/weapon/grab/G = locate() in src @@ -284,6 +325,7 @@ src << "You cannot do that in your current state." return + var/obj/item/weapon/grab/G = src.get_active_hand() if(!istype(G)) src << "We must be grabbing a creature in our active hand to devour their head." @@ -321,7 +363,25 @@ M.gib() last_special = world.time + 200 - return + +/mob/living/carbon/human/proc/self_destruct() + set category = "Hunter-Killer" + set name = "Engage Self-Destruct" + set desc = "When all else has failed, bite the bullet." + + if(stat || paralysis || stunned || weakened || lying) + src << "You cannot do that in your current state." + return + + src.visible_message( + "\The [src] begins to beep ominously!", + "WARNING: SELF-DESTRUCT ENGAGED. Unit termination finalized in three seconds!" + ) + sleep(10) + playsound(src, 'sound/items/countdown.ogg', 125, 1) + sleep(20) + explosion(src, -1, -1, 5) + src.gib() /mob/living/carbon/human/proc/hivenet() set category = "Abilities" @@ -393,4 +453,4 @@ playsound(src.loc, 'sound/weapons/bladeslice.ogg', 50, 1) var/obj/item/weapon/arrow/quill/A = new /obj/item/weapon/arrow/quill(usr.loc) A.throw_at(target, 10, 30, user) - msg_admin_attack("[key_name_admin(src)] launched a quill at [key_name_admin(target)] (JMP)") \ No newline at end of file + msg_admin_attack("[key_name_admin(src)] launched a quill at [key_name_admin(target)] (JMP)") diff --git a/code/modules/mob/living/carbon/human/human_species.dm b/code/modules/mob/living/carbon/human/human_species.dm index bfc4363f9bd..2e8fd06647b 100644 --- a/code/modules/mob/living/carbon/human/human_species.dm +++ b/code/modules/mob/living/carbon/human/human_species.dm @@ -32,7 +32,7 @@ /mob/living/carbon/human/machine/New(var/new_loc) h_style = "blue IPC screen" - ..(new_loc, "Machine") + ..(new_loc, "Baseline Frame") /mob/living/carbon/human/monkey mob_size = 2.6//Based on howler monkey, rough real world equivilant to on-mob sprite size @@ -79,4 +79,41 @@ /mob/living/carbon/human/type_c mob_size = 30 //same size as moghes lizard - layer = 5 \ No newline at end of file + layer = 5 + +/mob/living/carbon/human/industrial/New(var/new_loc) + ..(new_loc, "Industrial Frame") + +/mob/living/carbon/human/shell/New(var/new_loc) + ..(new_loc, "Shell Frame") + +/mob/living/carbon/human/terminator/New(var/new_loc) + ..(new_loc, "Hunter-Killer") + add_language(LANGUAGE_SOL_COMMON, 1) + add_language(LANGUAGE_UNATHI, 1) + add_language(LANGUAGE_SIIK_MAAS, 1) + add_language(LANGUAGE_SKRELLIAN, 1) + add_language(LANGUAGE_TRADEBAND, 1) + add_language(LANGUAGE_GUTTER, 1) + add_language(LANGUAGE_EAL, 1) + src.equip_to_slot_or_del(new /obj/item/weapon/rig/terminator(src),slot_back) + src.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/terminator(src),slot_l_hand) + src.equip_to_slot_or_del(new /obj/item/clothing/under/gearharness, slot_w_uniform) + src.equip_to_slot_or_del(new /obj/item/device/radio/headset/syndicate(src), slot_l_ear) + src.equip_to_slot_or_del(new /obj/item/weapon/grenade/frag(src), slot_l_store) + src.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_r_store) + + var/obj/item/weapon/storage/belt/security/tactical/commando_belt = new(src) + commando_belt.contents += new /obj/item/ammo_magazine/flechette + commando_belt.contents += new /obj/item/ammo_magazine/flechette/explosive + commando_belt.contents += new /obj/item/ammo_magazine/flechette/explosive + commando_belt.contents += new /obj/item/weapon/melee/baton/loaded + commando_belt.contents += new /obj/item/weapon/shield/energy + commando_belt.contents += new /obj/item/weapon/handcuffs + commando_belt.contents += new /obj/item/weapon/handcuffs + commando_belt.contents += new /obj/item/weapon/plastique + src.equip_to_slot_or_del(commando_belt, slot_belt) + src.gender = NEUTER + +/mob/living/carbon/human/terminator + mob_size = 30 diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 819b2b41a41..cdec7963cec 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -9,6 +9,9 @@ var/name_plural // Pluralized name (since "[name]s" is not always valid) var/short_name // Shortened form of the name, for code use. Must be exactly 3 letter long, and all lowercase var/blurb = "A completely nondescript species." // A brief lore summary for use in the chargen screen. + var/bodytype + var/age_min = 17 + var/age_max = 85 // Icon/appearance vars. var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set. @@ -191,7 +194,9 @@ return name /datum/species/proc/get_bodytype() - return name + if(!bodytype) + bodytype = name + return bodytype /datum/species/proc/get_environment_discomfort(var/mob/living/carbon/human/H, var/msg_type) diff --git a/code/modules/mob/living/carbon/human/species/species_attack.dm b/code/modules/mob/living/carbon/human/species/species_attack.dm index 365109d7cf0..f151afafe59 100644 --- a/code/modules/mob/living/carbon/human/species/species_attack.dm +++ b/code/modules/mob/living/carbon/human/species/species_attack.dm @@ -80,4 +80,29 @@ /datum/unarmed_attack/stomp/weak/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage) var/obj/item/organ/external/affecting = target.get_organ(zone) user.visible_message("[user] jumped up and down on \the [target]'s [affecting.name]!") - playsound(user.loc, attack_sound, 25, 1, -1) \ No newline at end of file + playsound(user.loc, attack_sound, 25, 1, -1) + +/datum/unarmed_attack/terminator + attack_verb = list("pulverized", "crushed", "pounded") + attack_noun = list("power fist") + damage = 12 + attack_sound = 'sound/weapons/beartrap_shut.ogg' + +/datum/unarmed_attack/terminator/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armour,var/attack_damage,var/zone) + ..() + if(prob(25) && target.mob_size <= 30) + playsound(user, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + user.visible_message("[user] shoves hard, sending [target] flying!") + var/T = get_turf(user) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, T) + s.start() + step_away(target,user,15) + sleep(1) + step_away(target,user,15) + sleep(1) + step_away(target,user,15) + sleep(1) + step_away(target,user,15) + sleep(1) + target.apply_effect(attack_damage * 0.4, WEAKEN, armour) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/machine_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/machine_subspecies.dm new file mode 100644 index 00000000000..d403d242db3 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/station/machine_subspecies.dm @@ -0,0 +1,235 @@ +/datum/species/machine/shell + name = "Shell Frame" + short_name = "jak" + name_plural = "Shells" + + burn_mod = 1.2 + + blurb = "IPC's with humanlike properties. Their focus is on service, civilian, and medical, but there are no \ + job restrictions. Created in the late days of 2457, the Shell is a controversial IPC model equipped with a synthskin weave applied over its metal chassis \ + to create an uncannily close approximation of the organic form. Early models of Shell had the advantage of being able to compose themselves of a wide \ + variety of organic parts, but contemporary models have been restricted to a single species for the sake of prosthetic integrity. The additional weight of \ + the synthskin on the original Hephaestus frame reduces the efficacy of the IPC's already strained coolant systems, and increase charge consumption." + + num_alternate_languages = 3 + + icobase = 'icons/mob/human_races/robotic.dmi' + deform = 'icons/mob/human_races/robotic.dmi' + + eyes = "eyes_s" + show_ssd = "completely quiescent" + + max_nutrition_factor = 0.8 + + heat_level_1 = 400 + heat_level_2 = 800 + heat_level_3 = 1600 + + heat_discomfort_level = 400 + heat_discomfort_strings = list( + "Your CPU temperature probes warn you that you are approaching critical heat levels!", + "Your synthetic flesh crawls in the heat, swelling into a disgusting morass of plastic." + ) + + appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_TONE | HAS_EYE_COLOR | HAS_SKIN_COLOR | HAS_FBP + +/datum/species/machine/shell/handle_post_spawn(var/mob/living/carbon/human/H) + add_inherent_verbs(H) + H.mob_bump_flag = bump_flag + H.mob_swap_flags = swap_flags + H.mob_push_flags = push_flags + H.pass_flags = pass_flags + H.mob_size = mob_size + . = ..() + check_tag(H, H.client) + +/datum/species/machine/shell/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost) + if (H.stat == CONSCIOUS) + H.bodytemperature += cost*1.3 + H.nutrition -= cost*0.85 + if (H.nutrition > 0) + return 1 + else + H.Weaken(30) + H.m_intent = "walk" + H.hud_used.move_intent.update_move_icon(H) + H << span("danger", "ERROR: Power reserves depleted, emergency shutdown engaged. Backup power will come online in 60 seconds, initiate charging as primary directive.") + playsound(H.loc, 'sound/machines/buzz-two.ogg', 100, 0) + return 0 + +/datum/species/machine/shell/handle_death(var/mob/living/carbon/human/H) + return + +/datum/species/machine/shell/get_bodytype() + return bodytype + +/datum/species/machine/industrial + name = "Industrial Frame" + short_name = "ind" + name_plural = "Industrials" + + brute_mod = 0.3 + burn_mod = 1.2 + slowdown = 4 + + blurb = "Tough units made for engineering and security with simple exteriors, roughly resembling humans. No job restrictions. Heavy emphasis on \ + engineering/security/EMT. Developed also by Hephaestus Industries, the Industrial Frame trades the common availability of the Baseline Frame for \ + advanced durability and increased longevity. Constructed of durable plasteel, the frame can withstand a great deal more abuse, and its coolant systems \ + and internal cell have been improved to allow for much more strenuous work. However, due to an unfortunate fault in the capacitor, actual battery charge \ + tends to be short." + + icobase = 'icons/mob/human_races/r_industrial.dmi' + deform = 'icons/mob/human_races/r_industrial.dmi' + + eyes = "eyes_industry" + show_ssd = "completely quiescent" + + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest/industrial), + "groin" = list("path" = /obj/item/organ/external/groin/industrial), + "head" = list("path" = /obj/item/organ/external/head/industrial), + "l_arm" = list("path" = /obj/item/organ/external/arm/industrial), + "r_arm" = list("path" = /obj/item/organ/external/arm/right/industrial), + "l_leg" = list("path" = /obj/item/organ/external/leg/industrial), + "r_leg" = list("path" = /obj/item/organ/external/leg/right/industrial), + "l_hand" = list("path" = /obj/item/organ/external/hand/industrial), + "r_hand" = list("path" = /obj/item/organ/external/hand/right/industrial), + "l_foot" = list("path" = /obj/item/organ/external/foot/industrial), + "r_foot" = list("path" = /obj/item/organ/external/foot/right/industrial) + ) + + heat_level_1 = 800 + heat_level_2 = 1300 + heat_level_3 = 2500 + + heat_discomfort_level = 800 + + max_nutrition_factor = 1.25 + nutrition_loss_factor = 2 + + sprint_speed_factor = 1.4 + +/datum/species/machine/industrial/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost) + if (H.stat == CONSCIOUS) + H.bodytemperature += cost*0.9 + H.nutrition -= cost*1.1 + if (H.nutrition > 0) + return 1 + else + H.Weaken(60) + H.m_intent = "walk" + H.hud_used.move_intent.update_move_icon(H) + H << span("danger", "ERROR: Power reserves depleted, emergency shutdown engaged. Backup power will come online in two minutes, initiate charging as primary directive.") + playsound(H.loc, 'sound/machines/buzz-two.ogg', 100, 0) + return 0 + +/datum/species/machine/industrial/handle_death(var/mob/living/carbon/human/H) + return + +/datum/species/machine/terminator + name = "Hunter-Killer" + short_name = "hks" + name_plural = "HKs" + + blurb = "\[REDACTED\]" + + icobase = 'icons/mob/human_races/r_terminator.dmi' + deform = 'icons/mob/human_races/r_terminator.dmi' + + unarmed_types = list(/datum/unarmed_attack/terminator) + rarity_value = 20 + + language = "Hephaestus Darkcomms" + name_language = "Hephaestus Darkcomms" + + eyes = "eyes_terminator" + has_floating_eyes = 1 + + brute_mod = 0.2 + burn_mod = 0.4 + flash_mod = 0 + siemens_coefficient = 0 + + show_ssd = "laying inert, its activation glyph dark." + death_sound = 'sound/effects/bang.ogg' + death_message = "collapses to the ground with a CLUNK, and begins to beep ominously." + + heat_level_1 = 1500 + heat_level_2 = 2000 + heat_level_3 = 5000 + + body_temperature = null + passive_temp_gain = 0 + + flags = NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_POISON + spawn_flags = IS_RESTRICTED + vision_flags = SEE_SELF | SEE_MOBS + + blood_color = "#1F181F" + flesh_color = "#575757" + virus_immune = 1 + reagent_tag = IS_MACHINE + + inherent_verbs = list( + /mob/living/carbon/human/proc/self_destruct, + /mob/living/carbon/human/proc/detonate_flechettes, + /mob/living/carbon/human/proc/state_laws + ) + + has_organ = list( + "brain" = /obj/item/organ/mmi_holder/posibrain/terminator, + "shielded cell" = /obj/item/organ/cell/terminator, + "optics" = /obj/item/organ/optical_sensor, + "data core" = /obj/item/organ/data + ) + + vision_organ = "optics" + + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest/terminator), + "groin" = list("path" = /obj/item/organ/external/groin/terminator), + "head" = list("path" = /obj/item/organ/external/head/terminator), + "l_arm" = list("path" = /obj/item/organ/external/arm/terminator), + "r_arm" = list("path" = /obj/item/organ/external/arm/right/terminator), + "l_leg" = list("path" = /obj/item/organ/external/leg/terminator), + "r_leg" = list("path" = /obj/item/organ/external/leg/right/terminator), + "l_hand" = list("path" = /obj/item/organ/external/hand/terminator), + "r_hand" = list("path" = /obj/item/organ/external/hand/right/terminator), + "l_foot" = list("path" = /obj/item/organ/external/foot/terminator), + "r_foot" = list("path" = /obj/item/organ/external/foot/right/terminator) + ) + + + heat_discomfort_level = 2000 + heat_discomfort_strings = list( + "Your CPU temperature probes warn you that you are approaching critical heat levels!" + ) + stamina = -1 + sprint_speed_factor = 1.25 + slowdown = 1 + + +/datum/species/machine/terminator/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost) + if (H.stat == CONSCIOUS) + H.bodytemperature += cost*0.6 + H.nutrition -= cost*0.3 + if (H.nutrition > 0) + return 1 + else + H.Weaken(5) + H.m_intent = "walk" + H.hud_used.move_intent.update_move_icon(H) + H << span("danger", "ERROR: Power reserves depleted, emergency shutdown engaged. Backup power will come online in 10 seconds, initiate charging as primary directive.") + playsound(H.loc, 'sound/machines/buzz-two.ogg', 100, 0) + return 0 + +/datum/species/machine/handle_death(var/mob/living/carbon/human/H) + ..() + spawn(10) + playsound(H.loc, 'sound/items/countdown.ogg', 125, 1) + spawn(20) + explosion(H, -1, -1, 5) + H.gib() + +/datum/species/machine/sanitize_name(var/new_name) + return sanitizeName(new_name, allow_numbers = 1) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 461ed2f1def..8c4e3b6b36e 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -2,6 +2,8 @@ name = "Human" short_name = "hum" name_plural = "Humans" + bodytype = "Human" + age_max = 125 primitive_form = "Monkey" unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) blurb = "Humanity originated in the Sol system, and over the last five centuries has spread \ @@ -21,13 +23,11 @@ sprint_speed_factor = 0.9 sprint_cost_factor = 0.5 -/datum/species/human/get_bodytype() - return "Human" - /datum/species/unathi name = "Unathi" short_name = "una" name_plural = "Unathi" + bodytype = "Unathi" icobase = 'icons/mob/human_races/r_lizard.dmi' deform = 'icons/mob/human_races/r_def_lizard.dmi' tail = "sogtail" @@ -99,6 +99,7 @@ name = "Tajara" short_name = "taj" name_plural = "Tajaran" + bodytype = "Tajara" icobase = 'icons/mob/human_races/r_tajaran.dmi' deform = 'icons/mob/human_races/r_def_tajaran.dmi' tail = "tajtail" @@ -152,13 +153,12 @@ ..() H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),slot_shoes) -/datum/species/tajaran/get_bodytype() - return "Tajara" - /datum/species/skrell name = "Skrell" short_name = "skr" name_plural = "Skrell" + bodytype = "Skrell" + age_max = 500 icobase = 'icons/mob/human_races/r_skrell.dmi' deform = 'icons/mob/human_races/r_def_skrell.dmi' eyes = "skrell_eyes_s" @@ -192,6 +192,8 @@ name = "Diona" short_name = "dio" name_plural = "Dionaea" + bodytype = "Diona" + age_max = 1000 icobase = 'icons/mob/human_races/r_diona.dmi' deform = 'icons/mob/human_races/r_def_plant.dmi' language = "Ceti Basic" @@ -322,16 +324,20 @@ if (!gibbed) H.diona_split_into_nymphs(0) -/datum/species/machine - name = "Machine" - short_name = "ipc" - name_plural = "machines" - blurb = "Positronic intelligence really took off in the 26th century, and it is not uncommon to see independant, free-willed \ - robots on many human stations, particularly in fringe systems where standards are slightly lax and public opinion less relevant \ - to corporate operations. IPCs (Integrated Positronic Chassis) are a loose category of self-willed robots with a humanoid form, \ - generally self-owned after being 'born' into servitude; they are reliable and dedicated workers, albeit more than slightly \ - inhuman in outlook and perspective." +/datum/species/machine + name = "Baseline Frame" + short_name = "ipc" + name_plural = "Baselines" + bodytype = "Machine" + age_min = 1 + age_max = 30 + + blurb = "IPCs are, quite simply, 'Integrated Positronic Chassis'. In this scenario, positronic does not mean anything significant - it is a nickname given \ + to all advanced processing units, based on the works of vintage writer Isaac Asimov. The long of the short is that they represent all unbound synthetic \ + units.Assembly produced, simple IPC units. Simple skeleton designed for minimal use, generally in civilian roles. The most common form of chassis used by \ + IPCs, first designed and produced by Hephaestus Industries in the early years of synthetic production. It has become ubiquitous, and for all of its many \ + faults - its shoddy coolant systems and fragile frame - it would be very odd to see a standard IPC without it." icobase = 'icons/mob/human_races/r_machine.dmi' deform = 'icons/mob/human_races/r_machine.dmi' @@ -345,7 +351,6 @@ ethanol_resistance = -1//Can't get drunk radiation_mod = 0 // not affected by radiation - eyes = "blank_eyes" // #TODO-MERGE: Check for balance and self-repair. If self-repair is a thing, RIP balance. brute_mod = 0.5 burn_mod = 1.0 @@ -370,6 +375,7 @@ passive_temp_gain = 10 // This should cause IPCs to stabilize at ~80 C in a 20 C environment. flags = NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_POISON | NO_MINOR_CUT + appearance_flags = HAS_SKIN_COLOR spawn_flags = CAN_JOIN | IS_WHITELISTED blood_color = "#1F181F" @@ -380,7 +386,8 @@ has_organ = list( "brain" = /obj/item/organ/mmi_holder/posibrain, "cell" = /obj/item/organ/cell, - "optics" = /obj/item/organ/optical_sensor + "optics" = /obj/item/organ/optical_sensor, + "ipc tag" = /obj/item/organ/ipc_tag ) vision_organ = "optics" @@ -407,6 +414,10 @@ stamina = -1 // Machines use power and generate heat, stamina is not a thing sprint_speed_factor = 1 // About as capable of speed as a human +datum/species/machine/handle_post_spawn(var/mob/living/carbon/human/H) + H.gender = NEUTER + . = ..() + check_tag(H, H.client) /datum/species/machine/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost) if (H.stat == CONSCIOUS) @@ -431,11 +442,64 @@ /datum/species/machine/sanitize_name(var/new_name) return sanitizeName(new_name, allow_numbers = 1) +/datum/species/machine/proc/check_tag(var/mob/living/carbon/human/new_machine, var/client/player) + if (!new_machine || !player) + return + + establish_db_connection() + + if (dbcon.IsConnected()) + var/obj/item/organ/ipc_tag/tag = new_machine.internal_organs_by_name["ipc tag"] + + var/status = 0 + var/list/query_details = list(":ckey" = player.ckey, ":character_name" = player.prefs.real_name) + var/DBQuery/query = dbcon.NewQuery("SELECT tag_status FROM ss13_ipc_tracking WHERE player_ckey = :ckey AND character_name = :character_name") + query.Execute(query_details) + + if (query.NextRow()) + status = text2num(query.item[1]) + else + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO ss13_ipc_tracking (player_ckey, character_name) VALUES (:ckey, :character_name)") + log_query.Execute(query_details) + + if (!status) + new_machine.internal_organs_by_name.Remove("ipc tag") + new_machine.internal_organs.Remove(tag) + qdel(tag) + +/datum/species/machine/proc/update_tag(var/mob/living/carbon/human/target, var/client/player) + if (!target || !player) + return + + establish_db_connection() + + if (dbcon.IsConnected()) + var/status = 0 + var/sql_status = 0 + if (target.internal_organs_by_name["ipc tag"]) + status = 1 + + var/list/query_details = list(":ckey" = player.ckey, ":character_name" = target.real_name) + var/DBQuery/query = dbcon.NewQuery("SELECT tag_status FROM ss13_ipc_tracking WHERE player_ckey = :ckey AND character_name = :character_name") + query.Execute(query_details) + + if (query.NextRow()) + sql_status = text2num(query.item[1]) + if (sql_status == status) + return + + query_details.Add(":status") + query_details[":status"] = status + var/DBQuery/update_query = dbcon.NewQuery("UPDATE ss13_ipc_tracking SET tag_status = :status WHERE player_ckey = :ckey AND character_name = :character_name") + update_query.Execute(query_details) /datum/species/bug name = "Vaurca Worker" short_name = "vau" name_plural = "Type A" + bodytype = "Vaurca" + age_min = 1 + age_max = 20 language = LANGUAGE_VAURCA primitive_form = "V'krexi" greater_form = "Vaurca Warrior" @@ -478,8 +542,8 @@ spawn_flags = CAN_JOIN | IS_WHITELISTED appearance_flags = HAS_SKIN_COLOR blood_color = "#E6E600" // dark yellow - flesh_color = "#330000" - base_color = "#330000" + flesh_color = "#E6E600" + base_color = "#575757" death_message = "chitters faintly before crumbling to the ground, their eyes dead and lifeless..." halloss_message = "crumbles to the ground, too weak to continue fighting." @@ -500,12 +564,20 @@ sprint_cost_factor = 0.30 stamina_recovery = 2//slow recovery + + inherent_verbs = list( + /mob/living/carbon/human/proc/bugbite //weaker version of gut. + ) + + has_organ = list( "neural socket" = /obj/item/organ/vaurca/neuralsocket, + "lungs" = /obj/item/organ/lungs, "filtration bit" = /obj/item/organ/vaurca/filtrationbit, "lungs" = /obj/item/organ/lungs, + "heart" = /obj/item/organ/heart, "phoron reserve tank" = /obj/item/organ/vaurca/preserve, - "right heart" = /obj/item/organ/heart/right, + "second heart" = /obj/item/organ/heart, "left heart" = /obj/item/organ/heart/left, "liver" = /obj/item/organ/liver, "kidneys" = /obj/item/organ/kidneys, diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 9249f42e12d..e2e1525173c 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -708,7 +708,7 @@ /mob/proc/is_mechanical() if(mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI")) return 1 - return istype(src, /mob/living/silicon) || get_species() == "Machine" + return istype(src, /mob/living/silicon) || get_species() == "Baseline Frame" || get_species() == "Shell Frame" || get_species() == "Industrial Frame" /mob/proc/is_ready() return client && !!mind diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index c35627f8538..13c3ddd163b 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -65,8 +65,16 @@ return 0 /proc/isipc(A) - if(istype(A, /mob/living/carbon/human) && (A:get_species() == "Machine")) - return 1 + if(istype(A, /mob/living/carbon/human)) + switch(A:get_species()) + if ("Baseline Frame") + return 1 + if ("Industrial Frame") + return 1 + if ("Shell Frame") + return 1 + if ("Hunter-Killer") + return 1 return 0 /proc/isvox(A) @@ -74,8 +82,6 @@ return 1 return 0 - - /mob/proc/is_diona() //returns which type of diona we are, or zero if (istype(src, /mob/living/carbon/human)) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index f82863b0948..92a53a16455 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -196,8 +196,17 @@ datum/preferences qdel(preview_icon_side) qdel(preview_icon) - var/g = "m" - if(gender == FEMALE) g = "f" + var/genderhead = "head" + var/gendergroin = "groin" + var/genderbust = "torso" + if(gender == FEMALE) + genderhead = "head_f" + gendergroin = "groin_f" + genderbust = "torso_f" + else if(gender == MALE) + genderhead = "head_m" + gendergroin = "groin_m" + genderbust = "torso_m" var/icon/icobase var/datum/species/current_species = all_species[species] @@ -207,17 +216,21 @@ datum/preferences else icobase = 'icons/mob/human_races/r_human.dmi' - preview_icon = new /icon(icobase, "torso_[g]") - preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY) - preview_icon.Blend(new /icon(icobase, "head_[g]"), ICON_OVERLAY) - + preview_icon = new /icon('icons/effects/effects.dmi', "nothing") //Non-robotic limbs - for(var/name in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand")) - if(organ_data[name] == "amputated") continue - if(organ_data[name] == "cyborg") + for(var/organname in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand","groin","chest","head")) + if(organ_data[organname] == "amputated") continue + if(organ_data[organname] == "cyborg") continue//We will add the icons for robolimbs after the skin color is applied - preview_icon.Blend(new /icon(icobase, "[name]"), ICON_OVERLAY) + if(organname == "head") + preview_icon.Blend(new /icon(icobase, "[genderhead]"), ICON_OVERLAY) + else if(organname == "groin") + preview_icon.Blend(new /icon(icobase, "[gendergroin]"), ICON_OVERLAY) + else if(organname == "chest") + preview_icon.Blend(new /icon(icobase, "[genderbust]"), ICON_OVERLAY) + else + preview_icon.Blend(new /icon(icobase, "[organname]"), ICON_OVERLAY) //Tail if(current_species && (current_species.tail)) @@ -237,12 +250,19 @@ datum/preferences //Robotic limbs, done AFTER skin color/tone blending - for(var/name in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand")) - if(organ_data[name] == "cyborg") + for(var/roboname in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand","groin","chest","head")) + if(organ_data[roboname] == "cyborg") var/datum/robolimb/R - if(rlimb_data[name]) R = all_robolimbs[rlimb_data[name]] + if(rlimb_data[roboname]) R = all_robolimbs[rlimb_data[roboname]] if(!R) R = basic_robolimb - preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic. + if(roboname == "head") + preview_icon.Blend(icon(R.icon, "[genderhead]"), ICON_OVERLAY) + else if(roboname == "groin") + preview_icon.Blend(icon(R.icon, "[gendergroin]"), ICON_OVERLAY) + else if(roboname == "chest") + preview_icon.Blend(icon(R.icon, "[genderbust]"), ICON_OVERLAY) + else + preview_icon.Blend(icon(R.icon, "[roboname]"), ICON_OVERLAY) var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = current_species ? current_species.eyes : "eyes_s") diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 242678f308c..24347290c07 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -932,8 +932,6 @@ Note that amputating the affected organ does in fact remove the infection from t if(company) model = company var/datum/robolimb/R = all_robolimbs[company] - if(species && (species.name in R.species_cannot_use)) - R = basic_robolimb if(R) force_icon = R.icon name = "[R.company] [initial(name)]" diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index ea92c278f0c..e88a95505e1 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -16,7 +16,7 @@ var/global/list/limb_icon_cache = list() s_tone = null s_col = null h_col = null - if(status & ORGAN_ROBOT) + if(status & ORGAN_ROBOT && !(isipc(human))) return if(species && human.species && species.name != human.species.name) return diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index 9a65a6c52c4..69d82ac94d4 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -15,7 +15,7 @@ var/global/datum/robolimb/basic_robolimb var/desc = "A generic unbranded robotic prosthesis." // Seen when examining a limb. var/icon = 'icons/mob/human_races/robotic.dmi' // Icon base to draw from. var/unavailable_at_chargen // If set, not available at chargen. - var/list/species_cannot_use = list("Resomi") + var/list/species_can_use = list("Human","Skrell","Tajara","Zhan-Khaza","M'sai","Unathi","Vaurca Worker","Vaurca Warrior","Baseline Frame") /datum/robolimb/bishop company = "Bishop Cybernetics" @@ -42,3 +42,45 @@ var/global/datum/robolimb/basic_robolimb desc = "This limb is simple and functional; no effort has been made to make it look human." icon = 'icons/mob/human_races/cyberlimbs/ipc.dmi' unavailable_at_chargen = 1 + +/datum/robolimb/industrial + company = "Hephaestus Industrial Limb" + desc = "This limb is more robust than the standard Hephaestus Integrated Limb, and is better suited for industrial machinery." + icon = 'icons/mob/human_races/r_industrial.dmi' + unavailable_at_chargen = 1 + +/datum/robolimb/terminator + company = "Hephaestus Vulcanite Limb" + desc = "A ludicrously expensive and EMP shielded component, these types of limbs are best suited for highly specialized cyborgs." + icon = 'icons/mob/human_races/r_terminator.dmi' + unavailable_at_chargen = 1 + +/datum/robolimb/human + company = "Human Synthskin" + desc = "This limb is designed to mimic the Human form. It does so with moderate success." + icon = 'icons/mob/human_races/r_human.dmi' + species_can_use = list("Human") + +/datum/robolimb/unathi + company = "Unathi Synthskin" + desc = "This limb is designed to mimic the Unathi form. It does so with moderate success." + icon = 'icons/mob/human_races/r_lizard.dmi' + species_can_use = list("Unathi") + +/datum/robolimb/tajara + company = "Tajara Synthskin" + desc = "This limb is designed to mimic the Tajaran form. It does so with moderate success." + icon = 'icons/mob/human_races/r_tajaran.dmi' + species_can_use = list("Tajara","Zhan-Khaza","M'sai") + +/datum/robolimb/skrell + company = "Skrell Synthskin" + desc = "This limb is designed to mimic the Skrellian form. It does so with moderate success." + icon = 'icons/mob/human_races/r_skrell.dmi' + species_can_use = list("Skrell") + +/datum/robolimb/vaurca + company = "Vaurca Synthskin" + desc = "This limb is designed to mimic the Vaurcae form. It does so with moderate success." + icon = 'icons/mob/human_races/r_vaurca.dmi' + species_can_use = list("Vaurca Worker","Vaurca Warrior") \ No newline at end of file diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm index 4775a8393c1..f90a7d60a22 100644 --- a/code/modules/organs/subtypes/machine.dm +++ b/code/modules/organs/subtypes/machine.dm @@ -6,7 +6,7 @@ max_damage = 50 //made same as arm, since it is not vital min_broken_damage = 30 encased = null - + /obj/item/organ/external/head/ipc/New() robotize("Hephaestus Integrated Limb") ..() @@ -104,6 +104,18 @@ robotize() ..() +/obj/item/organ/ipc_tag + name = "identification tag" + organ_tag = "ipc tag" + parent_organ = "groin" + icon = 'icons/obj/telescience.dmi' + icon_state = "gps-c" + dead_icon = "gps-c" + +/obj/item/organ/ipc_tag/New() + robotize() + ..() + // Used for an MMI or posibrain being installed into a human. /obj/item/organ/mmi_holder name = "brain" @@ -155,3 +167,183 @@ else stored_mmi.loc = get_turf(src) qdel(src) + + +//terminator organs + +/obj/item/organ/mmi_holder/posibrain/terminator + name = "brain" + organ_tag = "brain" + parent_organ = "chest" + vital = 1 + +/obj/item/organ/data + name = "data core" + organ_tag = "data core" + parent_organ = "groin" + icon = 'icons/obj/cloning.dmi' + icon_state = "harddisk" + vital = 0 + +/obj/item/organ/data/New() + robotize() + ..() + +/obj/item/organ/cell/terminator + name = "shielded microbattery" + desc = "A small, powerful cell for use in fully prosthetic bodies. Equipped with a Faraday shield." + icon = 'icons/obj/power.dmi' + icon_state = "scell" + organ_tag = "shielded cell" + parent_organ = "chest" + vital = 1 + +/obj/item/organ/cell/New() + mechassist() + ..() + +/obj/item/organ/external/head/terminator + dislocated = -1 + can_intake_reagents = 0 + vital = 0 + max_damage = 50 //made same as arm, since it is not vital + min_broken_damage = 30 + encased = null + +/obj/item/organ/external/head/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/chest/terminator + dislocated = -1 + encased = null +/obj/item/organ/external/chest/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/groin/terminator + dislocated = -1 +/obj/item/organ/external/groin/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/arm/terminator + dislocated = -1 +/obj/item/organ/external/arm/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/arm/right/terminator + dislocated = -1 +/obj/item/organ/external/arm/right/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/leg/terminator + dislocated = -1 +/obj/item/organ/external/leg/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/leg/right/terminator + dislocated = -1 +/obj/item/organ/external/leg/right/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/foot/terminator + dislocated = -1 +/obj/item/organ/external/foot/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/foot/right/terminator + dislocated = -1 +/obj/item/organ/external/foot/right/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/hand/terminator + dislocated = -1 +/obj/item/organ/external/hand/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/hand/right/terminator + dislocated = -1 +/obj/item/organ/external/hand/right/terminator/New() + mechassist("Hephaestus Vulcanite Limb") + ..() + +/obj/item/organ/external/head/industrial + dislocated = -1 + can_intake_reagents = 0 + vital = 0 + max_damage = 50 //made same as arm, since it is not vital + min_broken_damage = 30 + encased = null + +/obj/item/organ/external/head/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/chest/industrial + dislocated = -1 + encased = null +/obj/item/organ/external/chest/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/groin/industrial + dislocated = -1 +/obj/item/organ/external/groin/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/arm/industrial + dislocated = -1 +/obj/item/organ/external/arm/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/arm/right/industrial + dislocated = -1 +/obj/item/organ/external/arm/right/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/leg/industrial + dislocated = -1 +/obj/item/organ/external/leg/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/leg/right/industrial + dislocated = -1 +/obj/item/organ/external/leg/right/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/foot/industrial + dislocated = -1 +/obj/item/organ/external/foot/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/foot/right/industrial + dislocated = -1 +/obj/item/organ/external/foot/right/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/hand/industrial + dislocated = -1 +/obj/item/organ/external/hand/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() + +/obj/item/organ/external/hand/right/industrial + dislocated = -1 +/obj/item/organ/external/hand/right/industrial/New() + robotize("Hephaestus Industrial Limb") + ..() \ No newline at end of file diff --git a/code/modules/projectiles/ammunition/boxes.dm b/code/modules/projectiles/ammunition/boxes.dm index d6bae563d3b..6684943af0f 100644 --- a/code/modules/projectiles/ammunition/boxes.dm +++ b/code/modules/projectiles/ammunition/boxes.dm @@ -373,6 +373,35 @@ /obj/item/ammo_magazine/d762/empty initial_ammo = 0 +/obj/item/ammo_magazine/flechette + name = "flechette rounds" + icon = 'icons/obj/terminator.dmi' + icon_state = "flechette" + mag_type = MAGAZINE + caliber = "flechette" + matter = list(DEFAULT_WALL_MATERIAL = 1200) + ammo_type = /obj/item/ammo_casing/flechette + max_ammo = 40 + multiple_sprites = 1 + +/obj/item/ammo_magazine/flechette/empty + initial_ammo = 0 + +/obj/item/ammo_magazine/flechette/explosive + name = "explosive flechette rounds" + desc = "A box of ten explosive flechettes that can be remotely detonated by a certain signal." + icon = 'icons/obj/terminator.dmi' + icon_state = "flechette_e" + mag_type = MAGAZINE + caliber = "flechette" + matter = list(DEFAULT_WALL_MATERIAL = 1200) + ammo_type = /obj/item/ammo_casing/flechette/explosive + max_ammo = 10 + multiple_sprites = 1 + +/obj/item/ammo_magazine/flechette/explosive/empty + initial_ammo = 0 + /obj/item/ammo_magazine/assault_shotgun name = "magazine (slug)" icon = 'icons/obj/dragunov.dmi' diff --git a/code/modules/projectiles/ammunition/bullets.dm b/code/modules/projectiles/ammunition/bullets.dm index 67d17e65fba..6cee827790a 100644 --- a/code/modules/projectiles/ammunition/bullets.dm +++ b/code/modules/projectiles/ammunition/bullets.dm @@ -19,7 +19,7 @@ projectile_type = /obj/item/projectile/bullet/pistol /obj/item/ammo_casing/trod - desc = "Hyperdense tungsten rod residue." + desc = "hyperdense tungsten rod residue." icon_state = "trod" caliber = "trod" projectile_type = /obj/item/projectile/bullet/trod @@ -226,3 +226,13 @@ color = "#FF0000" projectile_type = /obj/item/projectile/bullet/pistol/cap +/obj/item/ammo_casing/flechette + desc = "A flechette casing." + icon = 'icons/obj/terminator.dmi' + icon_state = "flechette_casing" + caliber = "flechette" + projectile_type = /obj/item/projectile/bullet/flechette + +/obj/item/ammo_casing/flechette/explosive + projectile_type = /obj/item/projectile/bullet/flechette/explosive + diff --git a/code/modules/projectiles/effects.dm b/code/modules/projectiles/effects.dm index 638799429a5..33cb58ddbe3 100644 --- a/code/modules/projectiles/effects.dm +++ b/code/modules/projectiles/effects.dm @@ -137,7 +137,6 @@ /obj/effect/projectile/bullet/muzzle icon_state = "muzzle_bullet" -//---------------------------- // Solar beam //---------------------------- /obj/effect/projectile/solar/tracer @@ -148,3 +147,9 @@ /obj/effect/projectile/solar/impact icon_state = "impact_solar" + +//---------------------------- +// Pulse muzzle +//---------------------------- +/obj/effect/projectile/pulse_bullet/muzzle + icon_state = "muzzle_pulse" diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index b2f79c526c4..944f8693cd1 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -311,6 +311,64 @@ list(mode_name="dual coil", burst=2, move_delay=8, accuracy = list(-2,-3), dispersion = list(2.0, 3.0)) ) + +/obj/item/weapon/gun/projectile/automatic/terminator + name = "flechette rifle" + desc = "A fearsome Necropolis Industries designed rifle with attached bayonet that fires lethal flechette rounds." + icon = 'icons/obj/terminator.dmi' + icon_state = "flechetterifle" + item_state = "flechetterifle" + contained_sprite = 1 + w_class = 5 + force = 30 + caliber = "flechette" + slot_flags = SLOT_BELT|SLOT_BACK + fire_sound = 'sound/weapons/Gunshot_DMR.ogg' + load_method = MAGAZINE + magazine_type = /obj/item/ammo_magazine/flechette + allowed_magazines = list(/obj/item/ammo_magazine/flechette,/obj/item/ammo_magazine/flechette/explosive) + auto_eject = 1 + auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' + + firemodes = list( + list(mode_name="semiauto", burst=1, move_delay=null, burst_accuracy=null, dispersion=null), + list(mode_name="3-round bursts", burst=3, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)), + list(mode_name="short bursts", burst=5, move_delay=4, burst_accuracy=list(0,-1,-1,-2,-2), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)) + ) + + + fire_delay = 20 + accuracy = -4 + + //wielding information + fire_delay_wielded = 5 + accuracy_wielded = 0 + scoped_accuracy = 2 + + action_button_name = "Wield rifle" + +/obj/item/weapon/gun/projectile/automatic/terminator/verb/scope() + set category = "Object" + set name = "Use Scope" + set popup_menu = 1 + + if(wielded) + toggle_scope(2.0) + else + usr << "You can't look through the scope without stabilizing the rifle!" + +/obj/item/weapon/gun/projectile/automatic/terminator/can_wield() + return 1 + +/obj/item/weapon/gun/projectile/automatic/terminator/ui_action_click() + if(src in usr) + toggle_wield(usr) + +/obj/item/weapon/gun/projectile/automatic/terminator/verb/wield_rifle() + set name = "Wield rifle" + set category = "Object" + set src in usr + /obj/item/weapon/gun/projectile/automatic/rifle/shotgun name = "assault shotgun" desc = "A experimental, semi-automatic combat shotgun, designed for boarding operations and law enforcement agencies." @@ -345,3 +403,4 @@ /obj/item/weapon/gun/projectile/automatic/rifle/shotgun/update_icon() ..() icon_state = (ammo_magazine)? "cshotgun" : "cshotgun-empty" + diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 868a645e639..be040b346b4 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -58,6 +58,7 @@ var/agony = 0 var/incinerate = 0 var/embed = 0 // whether or not the projectile can embed itself in the mob + var/shrapnel_type //type of shrapnel the projectile leaves in its target. var/hitscan = 0 // whether the projectile should be hitscan var/step_delay = 1 // the delay between iterations if not a hitscan projectile diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 52fa2cf108d..f19cbf505cd 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -7,6 +7,7 @@ check_armour = "bullet" embed = 1 sharp = 1 + shrapnel_type = /obj/item/weapon/material/shard/shrapnel var/mob_passthrough_check = 0 muzzle_type = /obj/effect/projectile/bullet/muzzle @@ -296,3 +297,21 @@ /obj/item/projectile/bullet/pistol/cap/process() loc = null qdel(src) + +/obj/item/projectile/bullet/flechette + name = "flechette" + icon = 'icons/obj/terminator.dmi' + icon_state = "flechette_bullet" + damage = 40 + damage_type = BRUTE + check_armour = "bullet" + embed = 1 + sharp = 1 + penetrating = 1 + + muzzle_type = /obj/effect/projectile/pulse_bullet/muzzle + +/obj/item/projectile/bullet/flechette/explosive + shrapnel_type = /obj/item/weapon/material/shard/shrapnel/flechette + penetrating = 0 + damage = 10 \ No newline at end of file diff --git a/html/changelogs/LordFowl PR 54311.yml b/html/changelogs/LordFowl PR 54311.yml new file mode 100644 index 00000000000..72ad29690c7 --- /dev/null +++ b/html/changelogs/LordFowl PR 54311.yml @@ -0,0 +1,40 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: LordFowl + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added two new IPC subspecies - Shell Frame and Industrial Frame. Renamed main species to Baseline Frame." + - rscadd: "All IPCs now spawn with the tagger organ in their groin, which accurately identifies them unless removed." + - rscadd: "Organics can select synthskin prosthetics, but only of their own species." + - tweak: "Shells can now only mimic a single species - no more multi-species abominations." + - bugfix: "IPCs can now change their body colour." diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index d045d92babe..8e536893134 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi index 8dadd6427ca..83b85b4c7b0 100644 Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 7eada85a27c..fa6f328f32d 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 04f46a8df7e..8cc91338918 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/human_races/r_diona.dmi b/icons/mob/human_races/r_diona.dmi index 3215ea8908b..298daf9cc39 100644 Binary files a/icons/mob/human_races/r_diona.dmi and b/icons/mob/human_races/r_diona.dmi differ diff --git a/icons/mob/human_races/r_human.dmi b/icons/mob/human_races/r_human.dmi index 7ddd9453810..5724355bf1c 100644 Binary files a/icons/mob/human_races/r_human.dmi and b/icons/mob/human_races/r_human.dmi differ diff --git a/icons/mob/human_races/r_industrial.dmi b/icons/mob/human_races/r_industrial.dmi new file mode 100644 index 00000000000..800c676bdff Binary files /dev/null and b/icons/mob/human_races/r_industrial.dmi differ diff --git a/icons/mob/human_races/r_lizard.dmi b/icons/mob/human_races/r_lizard.dmi index 85208cff785..e3394432174 100644 Binary files a/icons/mob/human_races/r_lizard.dmi and b/icons/mob/human_races/r_lizard.dmi differ diff --git a/icons/mob/human_races/r_machine.dmi b/icons/mob/human_races/r_machine.dmi index 65f66c32385..877e70e626a 100644 Binary files a/icons/mob/human_races/r_machine.dmi and b/icons/mob/human_races/r_machine.dmi differ diff --git a/icons/mob/human_races/r_resomi.dmi b/icons/mob/human_races/r_resomi.dmi index e370ec6b1c7..dd2da7eacf4 100644 Binary files a/icons/mob/human_races/r_resomi.dmi and b/icons/mob/human_races/r_resomi.dmi differ diff --git a/icons/mob/human_races/r_skrell.dmi b/icons/mob/human_races/r_skrell.dmi index bb9f0fcfed6..cf6025879a0 100644 Binary files a/icons/mob/human_races/r_skrell.dmi and b/icons/mob/human_races/r_skrell.dmi differ diff --git a/icons/mob/human_races/r_tajaran.dmi b/icons/mob/human_races/r_tajaran.dmi index 69fa8ce5c0b..2b9456d17d5 100644 Binary files a/icons/mob/human_races/r_tajaran.dmi and b/icons/mob/human_races/r_tajaran.dmi differ diff --git a/icons/mob/human_races/r_terminator.dmi b/icons/mob/human_races/r_terminator.dmi new file mode 100644 index 00000000000..a309182032c Binary files /dev/null and b/icons/mob/human_races/r_terminator.dmi differ diff --git a/icons/mob/human_races/robotic.dmi b/icons/mob/human_races/robotic.dmi index e98d2e35129..94c4e20aac1 100644 Binary files a/icons/mob/human_races/robotic.dmi and b/icons/mob/human_races/robotic.dmi differ diff --git a/icons/mob/light_overlays.dmi b/icons/mob/light_overlays.dmi index 9f1232ff95e..0a75ef5908c 100644 Binary files a/icons/mob/light_overlays.dmi and b/icons/mob/light_overlays.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index 4e2260bbe9b..91bbf1158c6 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/mob/rig_back.dmi b/icons/mob/rig_back.dmi index a5309b5dc9a..b5c8417d51b 100644 Binary files a/icons/mob/rig_back.dmi and b/icons/mob/rig_back.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 5e906ee29cb..a6ab12720b4 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index e9345120782..979380591c3 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 4cbf3098319..00d5821884a 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index c5aefae272f..f8c2746755d 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 592bad2699b..7e121c23ad1 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/light_overlays.dmi b/icons/obj/light_overlays.dmi index c7bb310ce96..666338c2e6c 100644 Binary files a/icons/obj/light_overlays.dmi and b/icons/obj/light_overlays.dmi differ diff --git a/icons/obj/terminator.dmi b/icons/obj/terminator.dmi new file mode 100644 index 00000000000..1f0db24378b Binary files /dev/null and b/icons/obj/terminator.dmi differ