diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 1048aaa5c861..e44755574eea 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -35,6 +35,7 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/squid_face, GLOB.squid_face_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/ipc_screens, GLOB.ipc_screens_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/ipc_antennas, GLOB.ipc_antennas_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/ipc_tail, GLOB.ipc_tail_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/ipc_chassis, GLOB.ipc_chassis_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_markings, GLOB.moth_markings_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/spider_legs, GLOB.spider_legs_list) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 8838ba324530..fdeadc13b61a 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -72,6 +72,8 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/ipc_screens, GLOB.ipc_screens_list) if(!GLOB.ipc_antennas_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/ipc_antennas, GLOB.ipc_antennas_list) + if(!GLOB.ipc_tail_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/ipc_antennas, GLOB.ipc_tail_list) if(!GLOB.ipc_chassis_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/ipc_chassis, GLOB.ipc_chassis_list) if(!GLOB.spider_legs_list.len) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index aca090086487..479e43e34543 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -39,6 +39,7 @@ GLOBAL_LIST_EMPTY(moth_markings_list) GLOBAL_LIST_EMPTY(squid_face_list) GLOBAL_LIST_EMPTY(ipc_screens_list) GLOBAL_LIST_EMPTY(ipc_antennas_list) +GLOBAL_LIST_EMPTY(ipc_tail_list) GLOBAL_LIST_EMPTY(ipc_chassis_list) GLOBAL_LIST_INIT(ipc_brain_list, list("Posibrain", "Man-Machine Interface")) GLOBAL_LIST_EMPTY(spider_legs_list) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index e73a186087f3..3fa8bfc5266b 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -112,6 +112,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) "squid_face" = "Squidward", "ipc_screen" = "Blue", "ipc_antenna" = "None", + "ipc_tail" = "None", "ipc_chassis" = "Morpheus Cyberkinetics (Custom)", "ipc_brain" = "Posibrain", "kepori_feathers" = "Plain", @@ -675,6 +676,19 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "" mutant_category = 0 + if("ipc_tail" in pref_species.default_features) + if(!mutant_category) + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Tail Style

" + + dat += "[features["ipc_tail"]]
" + + mutant_category++ + if(mutant_category >= MAX_MUTANT_ROWS) + dat += "" + mutant_category = 0 + if("ipc_chassis" in pref_species.default_features) if(!mutant_category) dat += APPEARANCE_CATEGORY_COLUMN @@ -1913,6 +1927,14 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_ipc_antenna) features["ipc_antenna"] = new_ipc_antenna + if("ipc_tail") + var/new_ipc_tail + + new_ipc_tail = input(user, "Choose your character's tail:", "Character Preference") as null|anything in GLOB.ipc_tail_list + + if(new_ipc_tail) + features["ipc_tail"] = new_ipc_tail + if("ipc_chassis") var/new_ipc_chassis diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 7800a7b57f33..0b95e291b794 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -431,6 +431,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car READ_FILE(S["feature_squid_face"], features["squid_face"]) READ_FILE(S["feature_ipc_screen"], features["ipc_screen"]) READ_FILE(S["feature_ipc_antenna"], features["ipc_antenna"]) + READ_FILE(S["feature_ipc_tail"], features["ipc_tail"]) READ_FILE(S["feature_ipc_chassis"], features["ipc_chassis"]) READ_FILE(S["feature_ipc_brain"], features["ipc_brain"]) READ_FILE(S["feature_kepori_feathers"], features["kepori_feathers"]) @@ -541,6 +542,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car features["squid_face"] = sanitize_inlist(features["squid_face"], GLOB.squid_face_list, "Squidward") features["ipc_screen"] = sanitize_inlist(features["ipc_screen"], GLOB.ipc_screens_list) features["ipc_antenna"] = sanitize_inlist(features["ipc_antenna"], GLOB.ipc_antennas_list) + features["ipc_tail"] = sanitize_inlist(features["ipc_tail"], GLOB.ipc_tail_list) features["ipc_chassis"] = sanitize_inlist(features["ipc_chassis"], GLOB.ipc_chassis_list) features["ipc_brain"] = sanitize_inlist(features["ipc_brain"], GLOB.ipc_brain_list) features["kepori_feathers"] = sanitize_inlist(features["kepori_feathers"], GLOB.kepori_feathers_list, "Plain") @@ -618,6 +620,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_squid_face"] , features["squid_face"]) WRITE_FILE(S["feature_ipc_screen"] , features["ipc_screen"]) WRITE_FILE(S["feature_ipc_antenna"] , features["ipc_antenna"]) + WRITE_FILE(S["feature_ipc_tail"] , features["ipc_tail"]) WRITE_FILE(S["feature_ipc_chassis"] , features["ipc_chassis"]) WRITE_FILE(S["feature_ipc_brain"] , features["ipc_brain"]) WRITE_FILE(S["feature_kepori_feathers"] , features["kepori_feathers"]) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ipc.dm b/code/modules/mob/dead/new_player/sprite_accessories/ipc.dm index 20f2fe732d31..b13b8f96a51e 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/ipc.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/ipc.dm @@ -236,12 +236,71 @@ name = "Right Angle" icon_state = "rangle" +/datum/sprite_accessory/ipc_antennas/sprinter + name = "Sprinter Tail" + icon_state = "sprinter" + +/datum/sprite_accessory/ipc_antennas/simple + name = "Synth Simple" + icon_state = "simple_synth" + +/datum/sprite_accessory/ipc_antennas/short + name = "Synth Short" + icon_state = "short_synth" + +/datum/sprite_accessory/ipc_antennas/curled + name = "Synth Curled" + icon_state = "curled_synth" + +/datum/sprite_accessory/ipc_antennas/ram //remade + name = "Synth Ram" + icon_state = "ram_synth" + +// Start tails + +/datum/sprite_accessory/ipc_tail + icon = 'icons/mob/ipc_accessories.dmi' + color_src = MUTCOLORS + +/datum/sprite_accessory/ipc_tail/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/ipc_tail/lizard + name = "Synthetic Sarathi" + icon_state = "synth" + +/datum/sprite_accessory/ipc_tail/lizard_big + name = "Synthetic Sarathi Large" + icon_state = "large" + +/datum/sprite_accessory/ipc_tail/plug + name = "Power Plug" + icon_state = "plug" + secondary_color = TRUE + +/datum/sprite_accessory/ipc_tail/cat + name = "Pawsitrons Cat" + icon_state = "cat" + +/datum/sprite_accessory/ipc_tail/fox + name = "Pawsitrons Fox" + icon_state = "fox" + +/datum/sprite_accessory/ipc_tail/fox_alt + name = "Pawsitrons Fox 2" + icon_state = "fox2" + // Start chassis - the worst thing ever please rework this /datum/sprite_accessory/ipc_chassis // Used for changing limb icons, doesn't need to hold the actual icon. That's handled in ipc.dm icon = null icon_state = "who cares fuck you" // In order to pull the chassis correctly, we need AN icon_state(see line 36-39). It doesn't have to be useful, because it isn't used. color_src = 0 + var/use_eyes = FALSE //do we use normal robotic eyes? used when we dont want a screen but still want visible eyes + var/has_screen = TRUE //do we have a screen to toggle + var/has_overlay = FALSE //does this chasis have a overlay icon? + var/is_digi = FALSE //does this chasis use digitigrade /datum/sprite_accessory/ipc_chassis/mcgreyscale name = "Morpheus Cyberkinetics (Custom)" @@ -287,3 +346,25 @@ /datum/sprite_accessory/ipc_chassis/zenghupharmaceuticals name = "Zeng-Hu Pharmaceuticals" limbs_id = "zhpipc" + +/datum/sprite_accessory/ipc_chassis/pgfmechanicsplantigrade + name = "PGF MECHANICS TYPE-P" + limbs_id = "pgfipc-p" + has_screen = FALSE + color_src = MUTCOLORS + has_overlay = TRUE + use_eyes = TRUE + +/datum/sprite_accessory/ipc_chassis/pgfmechanicsdigigrade + name = "PGF MECHANICS TYPE-D" + limbs_id = "pgfipc-p" //the digigrade var makes it so we use digi leg variant instead + has_screen = FALSE + color_src = MUTCOLORS + has_overlay = TRUE + use_eyes = TRUE + is_digi = TRUE + +/datum/sprite_accessory/ipc_chassis/inteqsprinter + name = "Inteq Mothership 'Sprinter'" + limbs_id = "inteqsprinter" + has_screen = FALSE diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index fee2b6f0957d..8a8677523fc1 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -971,6 +971,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) S = GLOB.ipc_screens_list[H.dna.features["ipc_screen"]] if("ipc_antenna") S = GLOB.ipc_antennas_list[H.dna.features["ipc_antenna"]] + if("ipc_tail") + S = GLOB.ipc_tail_list[H.dna.features["ipc_tail"]] if("ipc_chassis") S = GLOB.ipc_chassis_list[H.dna.features["ipc_chassis"]] if("ipc_brain") diff --git a/code/modules/mob/living/carbon/human/species_types/IPC.dm b/code/modules/mob/living/carbon/human/species_types/IPC.dm index dfa12f329054..381708757fd1 100644 --- a/code/modules/mob/living/carbon/human/species_types/IPC.dm +++ b/code/modules/mob/living/carbon/human/species_types/IPC.dm @@ -17,8 +17,8 @@ mutantlungs = null //no more collecting change for you mutantappendix = null mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord) - mutant_bodyparts = list("ipc_screen", "ipc_antenna", "ipc_chassis", "ipc_brain") - default_features = list("mcolor" = "#7D7D7D", "ipc_screen" = "Static", "ipc_antenna" = "None", "ipc_chassis" = "Morpheus Cyberkinetics (Custom)", "ipc_brain" = "Posibrain", "body_size" = "Normal") + mutant_bodyparts = list("ipc_screen", "ipc_antenna", "ipc_chassis", "ipc_tail", "ipc_brain") + default_features = list("mcolor" = "#7D7D7D", "ipc_screen" = "Static", "ipc_antenna" = "None", "ipc_chassis" = "Morpheus Cyberkinetics (Custom)", "ipc_tail" = "None", "ipc_brain" = "Posibrain", "body_size" = "Normal") meat = /obj/item/stack/sheet/plasteel{amount = 5} skinned_type = /obj/item/stack/sheet/metal{amount = 10} exotic_bloodtype = "Coolant" @@ -49,13 +49,14 @@ /// The last screen used when the IPC died. var/saved_screen var/datum/action/innate/change_screen/change_screen + var/has_screen = TRUE //do we have a screen. Used to determine if we mess with the screen or not /datum/species/ipc/random_name(unique) var/ipc_name = "[pick(GLOB.posibrain_names)]-[rand(100, 999)]" return ipc_name /datum/species/ipc/New() - . = ..() + // This is in new because "[HEAD_LAYER]" etc. is NOT a constant compile-time value. For some reason. // Why not just use HEAD_LAYER? Well, because HEAD_LAYER is a number, and if you try to use numbers as indexes, // BYOND will try to make it an ordered list. So, we have to use a string. This is annoying, but it's the only way to do it smoothly. @@ -64,17 +65,19 @@ ) /datum/species/ipc/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) // Let's make that IPC actually robotic. + . = ..() if(ishuman(C)) var/mob/living/carbon/human/H = C if(!change_screen) - change_screen = new - change_screen.Grant(H) + var/datum/species/ipc/species_datum = H.dna.species + if(species_datum?.has_screen) + change_screen = new + change_screen.Grant(H) if(H.dna.features["ipc_brain"] == "Man-Machine Interface") mutantbrain = /obj/item/organ/brain/mmi_holder else mutantbrain = /obj/item/organ/brain/mmi_holder/posibrain C.RegisterSignal(C, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, TYPE_PROC_REF(/mob/living/carbon, charge)) - return ..() /datum/species/ipc/on_species_loss(mob/living/carbon/C) . = ..() @@ -83,6 +86,8 @@ C.UnregisterSignal(C, COMSIG_PROCESS_BORGCHARGER_OCCUPANT) /datum/species/ipc/spec_death(gibbed, mob/living/carbon/C) + if(!has_screen) + return saved_screen = C.dna.features["ipc_screen"] C.dna.features["ipc_screen"] = "BSOD" C.update_body() @@ -91,6 +96,8 @@ /datum/species/ipc/proc/post_death(mob/living/carbon/C) if(C.stat < DEAD) return + if(!has_screen) + return C.dna.features["ipc_screen"] = null // Turns off their monitor on death. C.update_body() @@ -110,6 +117,11 @@ if(!ishuman(owner)) return var/mob/living/carbon/human/H = owner + var/datum/species/ipc/species_datum = H.dna.species + if(!species_datum) + return + if(!species_datum.has_screen) + return H.dna.features["ipc_screen"] = screen_choice H.eye_color = sanitize_hexcolor(color_choice) H.update_body() @@ -215,14 +227,17 @@ /datum/species/ipc/spec_revival(mob/living/carbon/human/H) - H.dna.features["ipc_screen"] = "BSOD" - H.update_body() + if(has_screen) + H.dna.features["ipc_screen"] = "BSOD" + H.update_body() H.say("Reactivating [pick("core systems", "central subroutines", "key functions")]...") addtimer(CALLBACK(src, PROC_REF(post_revival), H), 6 SECONDS) /datum/species/ipc/proc/post_revival(mob/living/carbon/human/H) if(H.stat == DEAD) return + if(!has_screen) + return H.dna.features["ipc_screen"] = saved_screen H.update_body() @@ -231,12 +246,39 @@ var/datum/sprite_accessory/ipc_chassis/chassis_of_choice = GLOB.ipc_chassis_list[C.dna.features["ipc_chassis"]] + if(chassis_of_choice.use_eyes) + LAZYREMOVE(species_traits, NOEYESPRITES) + LAZYADD(species_traits, EYECOLOR) + C.update_body() + + if(!chassis_of_choice.has_screen) + has_screen = FALSE + C.dna.features["ipc_screen"] = null + C.update_body() + + if(chassis_of_choice.is_digi) + digitigrade_customization = DIGITIGRADE_FORCED + bodytype = BODYTYPE_DIGITIGRADE + for(var/obj/item/bodypart/BP as anything in C.bodyparts) //Override bodypart data as necessary if(BP.limb_id=="synth") BP.uses_mutcolor = chassis_of_choice.color_src ? TRUE : FALSE + + if(chassis_of_choice.icon) + BP.static_icon = chassis_of_choice.icon + BP.icon = chassis_of_choice.icon + + if(chassis_of_choice.has_overlay) + BP.overlay_icon_state = TRUE + + if(chassis_of_choice.is_digi) + if(istype(BP,/obj/item/bodypart/leg)) + BP.bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE //i hate this so much + if(BP.uses_mutcolor) BP.should_draw_greyscale = TRUE BP.species_color = C.dna?.features["mcolor"] + BP.species_secondary_color = C.dna?.features["mcolor2"] BP.limb_id = chassis_of_choice.limbs_id BP.name = "\improper[chassis_of_choice.name] [parse_zone(BP.body_zone)]" diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index de0ebac6eddb..0c200df9f6b1 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -141,6 +141,7 @@ /obj/item/organ/eyes/robotic name = "robotic eyes" icon_state = "robotic_eyes" + eye_icon_state = "eyes_synth" // i feel like this should be here desc = "A very basic set of optical sensors with no extra vision modes or functions." status = ORGAN_ROBOTIC organ_flags = ORGAN_SYNTHETIC diff --git a/icons/mob/ipc_accessories.dmi b/icons/mob/ipc_accessories.dmi index 86311ca3172e..e9fb262aa319 100644 Binary files a/icons/mob/ipc_accessories.dmi and b/icons/mob/ipc_accessories.dmi differ diff --git a/icons/mob/species/ipc/bodyparts.dmi b/icons/mob/species/ipc/bodyparts.dmi index f5c348617b56..1b4b568dcc78 100644 Binary files a/icons/mob/species/ipc/bodyparts.dmi and b/icons/mob/species/ipc/bodyparts.dmi differ