diff --git a/code/__DEFINES/~skyrat_defines/DNA.dm b/code/__DEFINES/~skyrat_defines/DNA.dm new file mode 100644 index 00000000000..a083fa20c98 --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/DNA.dm @@ -0,0 +1,55 @@ +//We start from 10 to not interfere with TG species defines, should they add more +/// We're using all three mutcolor features for our skin coloration +#define MUTCOLOR_MATRIXED 10 +#define MUTCOLORS2 11 +#define MUTCOLORS3 12 +// Defines for whether an accessory should have one or three colors to choose for +#define USE_ONE_COLOR 11 +#define USE_MATRIXED_COLORS 12 +//Also.. yes for some reason specie traits and accessory defines are together + +//Some defines for sprite accessories + +// Which color source we're using when the accessory is added +#define DEFAULT_PRIMARY 1 +#define DEFAULT_SECONDARY 2 +#define DEFAULT_TERTIARY 3 +#define DEFAULT_MATRIXED 4 //uses all three colors for a matrix +#define DEFAULT_SKIN_OR_PRIMARY 5 //Uses skin tone color if the character uses one, otherwise primary + +// Defines for extra bits of accessories +#define COLOR_SRC_PRIMARY 1 +#define COLOR_SRC_SECONDARY 2 +#define COLOR_SRC_TERTIARY 3 +#define COLOR_SRC_MATRIXED 4 + +// Defines for mutant bodyparts indexes +#define MUTANT_INDEX_NAME "name" +#define MUTANT_INDEX_COLOR_LIST "color" + +//The color list that is passed to color matrixed things when a person is husked +#define HUSK_COLOR_LIST list(list(0.64, 0.64, 0.64, 0), list(0.64, 0.64, 0.64, 0), list(0.64, 0.64, 0.64, 0), list(0, 0, 0, 1)) + +//Defines for an accessory to be randomed +#define ACC_RANDOM "random" + +//organ slots +#define ORGAN_SLOT_PENIS "penis" +#define ORGAN_SLOT_WOMB "womb" +#define ORGAN_SLOT_VAGINA "vagina" +#define ORGAN_SLOT_TESTICLES "testicles" +#define ORGAN_SLOT_BREASTS "breasts" + +#define ORGAN_SLOT_WINGS "wings" + +#define MAXIMUM_MARKINGS_PER_LIMB 3 + +#define PREVIEW_PREF_JOB "Job" +#define PREVIEW_PREF_LOADOUT "Loadout" +#define PREVIEW_PREF_NAKED "Naked" + +#define MANDATORY_FEATURE_LIST list("mcolor" = "FFB","mcolor2" = "FFB","mcolor3" = "FFB","ethcolor" = "FCC","skin_color" = "FED","flavor_text" = "","breasts_size" = 1,"breasts_lactation" = FALSE,"penis_size" = 13,"penis_girth" = 9,"penis_taur_mode" = TRUE,"balls_size" = 1) + +#define UNDERWEAR_HIDE_SOCKS (1<<0) +#define UNDERWEAR_HIDE_SHIRT (1<<1) +#define UNDERWEAR_HIDE_UNDIES (1<<2) diff --git a/code/__DEFINES/~skyrat_defines/obj_flags.dm b/code/__DEFINES/~skyrat_defines/obj_flags.dm new file mode 100644 index 00000000000..e46d240181c --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/obj_flags.dm @@ -0,0 +1,7 @@ +///Makes the organ not pop out when dismembered +#define ORGAN_NO_DISMEMBERMENT (1<<7) + +#define GENITAL_SKIP_VISIBILITY 0 +#define GENITAL_NEVER_SHOW 1 +#define GENITAL_HIDDEN_BY_CLOTHES 2 +#define GENITAL_ALWAYS_SHOW 3 diff --git a/code/__DEFINES/~skyrat_defines/say.dm b/code/__DEFINES/~skyrat_defines/say.dm new file mode 100644 index 00000000000..f4de47b2531 --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/say.dm @@ -0,0 +1 @@ +#define MAX_FLAVOR_LEN 4096 //double the maximum message length. diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 21de1e8c37b..24f12d458e2 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -14,6 +14,8 @@ //socks init_sprite_accessory_subtypes(/datum/sprite_accessory/socks, GLOB.socks_list) //bodypart accessories (blizzard intensifies) + //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION + /* init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, GLOB.tails_list_lizard) init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/lizard, GLOB.animated_tails_list_lizard) @@ -32,6 +34,8 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/caps, GLOB.caps_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_wings, GLOB.moth_wings_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_markings, GLOB.moth_markings_list) + */ + //SKYRAT EDIT REMOVAL END //Species for(var/spath in subtypesof(/datum/species)) @@ -50,6 +54,7 @@ GLOB.emote_list = init_emote_list() init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes) + make_skyrat_datum_references() //SKYRAT EDIT ADDITION - CUSTOMIZATION //creates every subtype of prototype (excluding prototype) and adds it to list L. //if no list/L is provided, one is created. diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 9762b0e7c92..101e2de2118 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -50,6 +50,8 @@ /proc/random_backpack() return pick(GLOB.backpacklist) +//SKYRAT EDIT REMOVAL - CUSTOMIZATION (moved to modular) +/* /proc/random_features() if(!GLOB.tails_list_human.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, GLOB.tails_list_human) @@ -76,7 +78,10 @@ if(!GLOB.moth_markings_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_markings, GLOB.moth_markings_list) //For now we will always return none for tail_human and ears. - return(list("mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),"ethcolor" = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)], "tail_lizard" = pick(GLOB.tails_list_lizard), "tail_human" = "None", "wings" = "None", "snout" = pick(GLOB.snouts_list), "horns" = pick(GLOB.horns_list), "ears" = "None", "frills" = pick(GLOB.frills_list), "spines" = pick(GLOB.spines_list), "body_markings" = pick(GLOB.body_markings_list), "legs" = "Normal Legs", "caps" = pick(GLOB.caps_list), "moth_wings" = pick(GLOB.moth_wings_list), "moth_markings" = pick(GLOB.moth_markings_list))) + return(list("mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),"ethcolor" = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)], "tail_lizard" = pick(GLOB.tails_list_lizard), "tail_human" = "None", "wings" = "None", "snout" = pick(GLOB.snouts_list), "horns" = pick(GLOB.horns_list), "ears" = "None", "frills" = pick(GLOB.frills_list), "spines" = pick(GLOB.spines_list), "body_markings" = pick(GLOB.body_markings_list), "legs" = "Normal Legs", "caps" = pick(GLOB.caps_list), "moth_wings" = pick(GLOB.moth_wings_list), "moth_markings" = pick(GLOB.moth_markings_list))) +*/ +//SKYRAT EDIT REMOVAL END + /proc/random_hairstyle(gender) switch(gender) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 9ecf45d383e..7f7e7e88bc1 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -17,6 +17,8 @@ GLOBAL_LIST_EMPTY(undershirt_f) //stores only undershirt name //Socks GLOBAL_LIST_EMPTY(socks_list) //stores /datum/sprite_accessory/socks indexed by name //Lizard Bits (all datum lists indexed by name) +//SKYRAT EDIT REMOVAL - CUSTOMIZATION +/* GLOBAL_LIST_EMPTY(body_markings_list) GLOBAL_LIST_EMPTY(tails_list_lizard) GLOBAL_LIST_EMPTY(animated_tails_list_lizard) @@ -37,6 +39,8 @@ GLOBAL_LIST_EMPTY(r_wings_list) GLOBAL_LIST_EMPTY(moth_wings_list) GLOBAL_LIST_EMPTY(moth_markings_list) GLOBAL_LIST_EMPTY(caps_list) +*/ +//SKYRAT EDIT REMOVAL END GLOBAL_LIST_INIT(color_list_ethereal, list( "Red" = "ff4d4d", diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index cefc91b7107..1693a56e771 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -445,7 +445,13 @@ SUBSYSTEM_DEF(job) living_mob.mind.assigned_role = rank to_chat(M, "You are the [rank].") + var/list/packed_items //SKYRAT CHANGE ADDITION - CUSTOMIZATION if(job) + //SKYRAT CHANGE ADDITION BEGIN - CUSTOMIZATION + if(job.no_dresscode) + if(M.client) + packed_items = M.client.prefs.equip_preference_loadout(M, FALSE, job) + //SKYRAT CHANGE ADDITION END var/new_mob = job.equip(living_mob, null, null, joined_late , null, M.client)//silicons override this proc to return a mob if(ismob(new_mob)) living_mob = new_mob @@ -477,6 +483,12 @@ SUBSYSTEM_DEF(job) living_mob.add_memory("Your account ID is [wageslave.account_id].") if(job && living_mob) job.after_spawn(living_mob, M, joined_late) // note: this happens before the mob has a key! M will always have a client, H might not. + //SKYRAT CHANGE ADDITION BEGIN - CUSTOMIZATION + if(!job.no_dresscode) + if(M.client) + packed_items = M.client.prefs.equip_preference_loadout(M, FALSE, job) + M.client.prefs.add_packed_items(M, packed_items) + //SKYRAT CHANGE ADDITION END return living_mob diff --git a/code/datums/dna.dm b/code/datums/dna.dm index e6aaf50246e..f187abc1cbd 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -255,6 +255,8 @@ uni_identity = generate_uni_identity() unique_enzymes = generate_unique_enzymes() +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/dna/proc/initialize_dna(newblood_type, skip_index = FALSE) if(newblood_type) blood_type = newblood_type @@ -263,7 +265,8 @@ if(!skip_index) //I hate this generate_dna_blocks() features = random_features() - +*/ +//SKYRAT EDIT REMOVAL END /datum/dna/stored //subtype used by brain mob's stored_dna @@ -295,6 +298,8 @@ stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) if(mrace && has_dna()) var/datum/species/new_race @@ -314,6 +319,8 @@ var/species_holder = initial(mrace.species_language_holder) language_holder = new species_holder(src) update_atom_languages() +*/ +//SKYRAT EDIT REMOVAL BEGIN /mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) ..() diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 594aae2bafc..a284e718bd1 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -26,7 +26,9 @@ H.dna.blood_type = random_blood_type() // Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant. - H.dna.features["mcolor"] = random_short_color() + //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION + /* + H.dna.features["mcolor"] = random_short_color() SKYRAT EDIT - We dont use those in favor for a more modular system H.dna.features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] H.dna.features["tail_lizard"] = pick(GLOB.tails_list_lizard) H.dna.features["snout"] = pick(GLOB.snouts_list) @@ -35,6 +37,15 @@ H.dna.features["spines"] = pick(GLOB.spines_list) H.dna.features["body_markings"] = pick(GLOB.body_markings_list) H.dna.features["moth_wings"] = pick(GLOB.moth_wings_list) + */ + //SKYRAT EDIT REMOVAL END + //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION + H.dna.features = H.dna.species.get_random_features() + H.dna.mutant_bodyparts = H.dna.species.get_random_mutant_bodyparts(H.dna.features) + H.dna.body_markings = H.dna.species.get_random_body_markings(H.dna.features) + H.dna.species.mutant_bodyparts = H.dna.mutant_bodyparts.Copy() + H.dna.species.body_markings = H.dna.body_markings.Copy() + //SKYRAT EDIT ADDITION END H.update_body() H.update_hair() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 40004e4a491..1034f2b20cc 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1,5 +1,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/preferences var/client/parent //doohickeys for savefiles @@ -1962,3 +1964,5 @@ GLOBAL_LIST_EMPTY(preferences_datums) return else custom_names[name_id] = sanitized_name +*/ +//SKYRAT EDIT REMOVAL END diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 8afe339e0e5..fb577b3373c 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -1,4 +1,6 @@ //This is the lowest supported version, anything below this is completely obsolete and the entire savefile will be wiped. +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* #define SAVEFILE_VERSION_MIN 32 //This is the current version, anything below this will attempt to update (if it's not obsolete) @@ -520,3 +522,5 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S.ImportText("/",file("[path].txt")) #endif +*/ +//SKYRAT EDIT REMOVAL END diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm index a36dc2d2bef..41cbd618b8e 100644 --- a/code/modules/mob/dead/new_player/preferences_setup.dm +++ b/code/modules/mob/dead/new_player/preferences_setup.dm @@ -1,5 +1,7 @@ //The mob should have a gender you want before running this proc. Will run fine without H +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/preferences/proc/random_character(gender_override, antag_override = FALSE) if(randomise[RANDOM_SPECIES]) random_species() @@ -43,12 +45,18 @@ body_type = gender else body_type = pick(MALE, FEMALE) +*/ +//SKYRAT EDIT REMOVAL END +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/preferences/proc/random_species() var/random_species_type = GLOB.species_list[pick(GLOB.roundstart_races)] pref_species = new random_species_type if(randomise[RANDOM_NAME]) real_name = pref_species.random_name(gender,1) +*/ +//SKYRAT EDIT REMOVAL END ///Setup a hardcore random character and calculate their hardcore random score /datum/preferences/proc/hardcore_random_setup(mob/living/carbon/human/character, antagonist, is_latejoiner) @@ -105,6 +113,8 @@ hardcore_survival_score += available_hardcore_quirks[picked_quirk] available_hardcore_quirks -= picked_quirk +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/preferences/proc/update_preview_icon() // Determine what job is marked as 'High' priority, and dress them up as such. var/datum/job/previewJob @@ -134,3 +144,5 @@ COMPILE_OVERLAYS(mannequin) parent.show_character_previews(new /mutable_appearance(mannequin)) unset_busy_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES) +*/ +//SKYRAT EDIT REMOVAL END diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 5df3a23903f..47dae074fbd 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -104,6 +104,8 @@ apply_overlay(DAMAGE_LAYER) +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/update_inv_wear_mask() remove_overlay(FACEMASK_LAYER) @@ -120,6 +122,8 @@ update_hud_wear_mask(wear_mask) apply_overlay(FACEMASK_LAYER) +*/ +//SKYRAT EDIT REMOVAL END /mob/living/carbon/update_inv_neck() remove_overlay(NECK_LAYER) @@ -148,6 +152,8 @@ apply_overlay(BACK_LAYER) +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/update_inv_head() remove_overlay(HEAD_LAYER) @@ -163,6 +169,8 @@ update_hud_head(head) apply_overlay(HEAD_LAYER) +*/ +//SKYRAT EDIT REMOVAL END /mob/living/carbon/update_inv_handcuffed() @@ -215,6 +223,8 @@ var/obj/item/bodypart/BP = X BP.original_owner = src +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/proc/update_body_parts() //CHECK FOR UPDATE var/oldkey = icon_render_key @@ -244,6 +254,8 @@ apply_overlay(BODYPARTS_LAYER) update_damage_overlays() +*/ +//SKYRAT EDIT REMOVAL END @@ -263,6 +275,8 @@ //produces a key based on the mob's limbs +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/proc/generate_icon_render_key() for(var/X in bodyparts) var/obj/item/bodypart/BP = X @@ -278,6 +292,8 @@ if(HAS_TRAIT(src, TRAIT_HUSK)) . += "-husk" +*/ +//SKYRAT EDIT REMOVAL END //change the mob's icon to the one matching its key diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index d12f8d0b44b..57077f30927 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -104,7 +104,8 @@ var/mob/living/carbon/human/H = user if(!istype(H) || !H.dna || !H.dna.species || !H.dna.species.can_wag_tail(H)) return - if(!H.dna.species.is_wagging_tail()) + //if(!H.dna.species.is_wagging_tail()) - ORIGINAL + if(!H.dna.species.is_wagging_tail(H)) //SKYRAT EDIT CHANGE - CUSTOMIZATION H.dna.species.start_wagging_tail(H) else H.dna.species.stop_wagging_tail(H) @@ -120,7 +121,8 @@ var/mob/living/carbon/human/H = user if(!H.dna || !H.dna.species) return - if(H.dna.species.is_wagging_tail()) + //if(H.dna.species.is_wagging_tail()) - ORIGINAL + if(H.dna.species.is_wagging_tail(H)) //SKYRAT EDIT CHANGE - CUSTOMIZATION . = null /datum/emote/living/carbon/human/wing diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 19751deb6c7..c37f098337f 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -428,6 +428,29 @@ "\[Add comment\]"), "") else if(isobserver(user)) . += "Traits: [get_quirk_string(FALSE, CAT_QUIRK_ALL)]" + + //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION + for(var/genital in list("penis", "testicles", "vagina", "breasts")) + if(dna.species.mutant_bodyparts[genital]) + var/datum/sprite_accessory/genital/G = GLOB.sprite_accessories[genital][dna.species.mutant_bodyparts[genital][MUTANT_INDEX_NAME]] + if(G) + if(!(G.is_hidden(src))) + . += "[t_He] has exposed genitals... Look closer..." + break + if(!skipface) + var/line + if(length(dna.features["flavor_text"])) + var/message = dna.features["flavor_text"] + if(length_char(message) <= 40) + line = "[message]" + else + line = "[copytext_char(message, 1, 37)]... More..." + if(client) + if(length(client.prefs.ooc_prefs)) + line += " \[OOC\]" + if(line) + . += line + //SKYRAT EDIT ADDITION END . += "*---------*" SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index 194766acdca..f925a4c9ae7 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -97,6 +97,8 @@ There are several things that need to be remembered: /* --------------------------------------- */ //vvvvvv UPDATE_INV PROCS vvvvvv +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/human/update_inv_w_uniform() remove_overlay(UNIFORM_LAYER) @@ -139,6 +141,8 @@ There are several things that need to be remembered: apply_overlay(UNIFORM_LAYER) update_mutant_bodyparts() +*/ +//SKYRAT EDIT REMOVAL END /mob/living/carbon/human/update_inv_wear_id() @@ -199,6 +203,8 @@ There are several things that need to be remembered: apply_overlay(GLOVES_LAYER) +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/human/update_inv_glasses() remove_overlay(GLASSES_LAYER) @@ -225,6 +231,8 @@ There are several things that need to be remembered: glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2] overlays_standing[GLASSES_LAYER] = glasses_overlay apply_overlay(GLASSES_LAYER) +*/ +//SKYRAT EDIT REMOVAL END /mob/living/carbon/human/update_inv_ears() @@ -252,6 +260,8 @@ There are several things that need to be remembered: apply_overlay(EARS_LAYER) +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/human/update_inv_shoes() remove_overlay(SHOES_LAYER) @@ -276,6 +286,8 @@ There are several things that need to be remembered: overlays_standing[SHOES_LAYER] = shoes_overlay apply_overlay(SHOES_LAYER) +*/ +//SKYRAT EDIT REMOVAL END /mob/living/carbon/human/update_inv_s_store() @@ -334,6 +346,8 @@ There are several things that need to be remembered: +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /mob/living/carbon/human/update_inv_wear_suit() remove_overlay(SUIT_LAYER) @@ -357,6 +371,8 @@ There are several things that need to be remembered: update_mutant_bodyparts() apply_overlay(SUIT_LAYER) +*/ +//SKYRAT EDIT REMOVAL END /mob/living/carbon/human/update_inv_pockets() @@ -488,6 +504,8 @@ generate/load female uniform sprites matching all previously decided variables */ +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state = null) //Find a valid icon_state from variables+arguments @@ -529,6 +547,8 @@ generate/load female uniform sprites matching all previously decided variables standing.color = color return standing +*/ +//SKYRAT EDIT REMOVAL END /obj/item/proc/get_held_offsets() @@ -559,8 +579,10 @@ generate/load female uniform sprites matching all previously decided variables . += "-coloured-[skin_tone]" else if(dna.species.fixed_mut_color) . += "-coloured-[dna.species.fixed_mut_color]" - else if(dna.features["mcolor"]) - . += "-coloured-[dna.features["mcolor"]]" + //else if(dna.features["mcolor"]) - ORIGINAL + // . += "-coloured-[dna.features["mcolor"]]" - ORIGINAL + else if(MUTCOLORS in dna.species.species_traits) //SKYRAT EDIT CHANGE - CUSTOMIZATION + . += "-coloured-[dna.features["mcolor"]]" //SKYRAT EDIT CHANGE - CUSTOMIZATION else . += "-not_coloured" diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 7f866150083..b50ae94c897 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -57,7 +57,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) /// Default mutant bodyparts for this species, like horns. Don't forget to set one for every mutant bodypart you allow this species to have. var/list/default_features = list() /// Visible CURRENT bodyparts that are unique to a species. DO NOT USE THIS AS A LIST OF ALL POSSIBLE BODYPARTS AS IT WILL FUCK SHIT UP! Changes to this list for non-species specific bodyparts (ie cat ears and tails) should be assigned at organ level if possible. Layer hiding is handled by [datum/species/handle_mutant_bodyparts()] below. - var/list/mutant_bodyparts = list() + //var/list/mutant_bodyparts = list() - ORIGINAL + var/list/list/mutant_bodyparts = list() //SKYRAT EDIT CHANGE - CUSTOMIZATIOn ///Internal organs that are unique to this race, like a tail. var/list/mutant_organs = list() ///Multiplier for the race's speed. Positive numbers make it move slower, negative numbers make it move faster. @@ -321,6 +322,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) * * old_species - The species that the carbon used to be before becoming this race, used for regenerating organs. * * pref_load - Preferences to be loaded from character setup, loads in preferred mutant things like bodyparts, digilegs, skin color, etc. */ +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) // Drop the items the new species can't wear if((AGENDER in species_traits)) @@ -387,6 +390,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, multiplicative_slowdown=speedmod) SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) +*/ +//SKYRAT EDIT REMOVAL END /** * Proc called when a carbon is no longer this species. @@ -598,6 +603,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) * Arguments: * * H - Human, whoever we're handling the body for */ +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/species/proc/handle_body(mob/living/carbon/human/H) H.remove_overlay(BODY_LAYER) @@ -659,6 +666,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) H.apply_overlay(BODY_LAYER) handle_mutant_bodyparts(H) +*/ +//SKYRAT EDIT REMOVAL END /** * Handles the mutant bodyparts of a human @@ -669,6 +678,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) * * H - Human, whoever we're handling the body for * * forced_colour - The forced color of an accessory. Leave null to use mutant color. */ +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) var/list/bodyparts_to_add = mutant_bodyparts.Copy() var/list/relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER) @@ -869,6 +880,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) H.apply_overlay(BODY_BEHIND_LAYER) H.apply_overlay(BODY_ADJ_LAYER) H.apply_overlay(BODY_FRONT_LAYER) +*/ +//SKYRAT EDIT REMOVAL END //This exists so sprite accessories can still be per-layer without having to include that layer's @@ -946,10 +959,14 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(ITEM_SLOT_FEET) if(H.num_legs < 2) return FALSE + //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION + /* if(DIGITIGRADE in species_traits) if(!disable_warning) to_chat(H, "The footwear around here isn't compatible with your feet!") return FALSE + */ + //SKYRAT EDIT REMOVAL END return equip_delay_self_check(I, H, bypass_equip_delay_self) if(ITEM_SLOT_BELT) var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST) @@ -1842,6 +1859,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) //Tail Wagging// //////////////// +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /datum/species/proc/can_wag_tail(mob/living/carbon/human/H) return FALSE @@ -1851,6 +1870,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) /datum/species/proc/start_wagging_tail(mob/living/carbon/human/H) /datum/species/proc/stop_wagging_tail(mob/living/carbon/human/H) +*/ +//SKYRAT EDIT REMOVAL END /////////////// //FLIGHT SHIT// diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index 15a76493df0..7086823bda4 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -8,13 +8,16 @@ mutant_bodyparts = list("ears", "tail_human") default_features = list("mcolor" = "FFF", "tail_human" = "Cat", "ears" = "Cat", "wings" = "None") - mutantears = /obj/item/organ/ears/cat - mutant_organs = list(/obj/item/organ/tail/cat) + //mutantears = /obj/item/organ/ears/cat //SKYRAT EDIT REMOVAL - CUSTOMIZATION + //mutant_organs = list(/obj/item/organ/tail/cat) //SKYRAT EDIT REMOVAL - CUSTOMIZATION changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/felinid var/original_felinid = TRUE //set to false for felinids created by mass-purrbation payday_modifier = 0.75 + +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* //Curiosity killed the cat's wagging tail. /datum/species/human/felinid/spec_death(gibbed, mob/living/carbon/human/H) if(H) @@ -36,6 +39,8 @@ mutant_bodyparts -= "tail_human" mutant_bodyparts |= "waggingtail_human" H.update_body() +*/ +//SKYRAT EDIT REMOVAL END /datum/species/human/felinid/stop_wagging_tail(mob/living/carbon/human/H) if("waggingtail_human" in mutant_bodyparts) diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index aa872b35bd6..fc8fa4915c1 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -8,7 +8,7 @@ inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs") mutanttongue = /obj/item/organ/tongue/lizard - mutant_organs = list(/obj/item/organ/tail/lizard) + //mutant_organs = list(/obj/item/organ/tail/lizard) //SKYRAT EDIT REMOVAL - CUSTOMIZATION coldmod = 1.5 heatmod = 0.67 payday_modifier = 0.75 @@ -45,7 +45,9 @@ return randname -//I wag in death +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* +//I wag in death SKYRAT EDIT - customization /datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H) if(H) stop_wagging_tail(H) @@ -101,6 +103,8 @@ // organ.Insert will qdel any existing organs in the same slot, so // we don't need to manage that. new_tail.Insert(C, TRUE, FALSE) +*/ +//SKYRAT EDIT REMOVAL END /* Lizard subspecies: ASHWALKERS diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index a3976a66c32..0f72fa0c2de 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -94,6 +94,7 @@ var/obj/item/stack/current_gauze /// If something is currently grasping this bodypart and trying to staunch bleeding (see [/obj/item/grasp_self]) var/obj/item/self_grasp/grasped_by + var/rendered_bp_icon //SKYRAT EDIT ADDITION - CUSTOMIZATION /obj/item/bodypart/Initialize(mapload) @@ -763,6 +764,7 @@ var/datum/species/S = H.dna.species species_id = S.limbs_id + rendered_bp_icon = S.limbs_icon species_flags_list = H.dna.species.species_traits if(S.use_skintones) @@ -812,6 +814,8 @@ add_overlay(standing) //Gives you a proper icon appearance for the dismembered limb +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +/* /obj/item/bodypart/proc/get_limb_icon(dropped) icon_state = "" //to erase the default sprite, we're building the visual aspects of the bodypart through overlays alone. @@ -884,6 +888,8 @@ limb.color = "#[draw_color]" if(aux_zone) aux.color = "#[draw_color]" +*/ +//SKYRAT EDIT REMOVAL END /obj/item/bodypart/deconstruct(disassembled = TRUE) drop_organs() diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index cd16a6e1b4c..b275c0aac83 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -66,21 +66,25 @@ icon_state = "kitty" damage_multiplier = 2 +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION +/* /obj/item/organ/ears/cat/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = TRUE) ..() if(istype(H)) color = H.hair_color H.dna.species.mutant_bodyparts |= "ears" H.dna.features["ears"] = "Cat" - H.update_body() + H.update_body()*/ -/obj/item/organ/ears/cat/Remove(mob/living/carbon/human/H, special = 0) +/*/obj/item/organ/ears/cat/Remove(mob/living/carbon/human/H, special = 0) ..() if(istype(H)) color = H.hair_color H.dna.features["ears"] = "None" H.dna.species.mutant_bodyparts -= "ears" H.update_body() +*/ +//SKYRAT EDIT REMOVAL END /obj/item/organ/ears/penguin name = "penguin ears" diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm index 51bb28290e5..908bc0455bf 100644 --- a/code/modules/surgery/organs/tails.dm +++ b/code/modules/surgery/organs/tails.dm @@ -18,21 +18,25 @@ desc = "A severed cat tail. Who's wagging now?" tail_type = "Cat" +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION +/* /obj/item/organ/tail/cat/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = TRUE) ..() if(istype(H)) if(!("tail_human" in H.dna.species.mutant_bodyparts)) H.dna.species.mutant_bodyparts |= "tail_human" H.dna.features["tail_human"] = tail_type - H.update_body() + H.update_body()*/ -/obj/item/organ/tail/cat/Remove(mob/living/carbon/human/H, special = 0) +/*/obj/item/organ/tail/cat/Remove(mob/living/carbon/human/H, special = 0) ..() if(istype(H)) H.dna.features["tail_human"] = "None" H.dna.species.mutant_bodyparts -= "tail_human" color = H.hair_color H.update_body() +*/ +//SKYRAT EDIT REMOVAL END /obj/item/organ/tail/lizard name = "lizard tail" @@ -41,8 +45,10 @@ tail_type = "Smooth" var/spines = "None" +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION +/* /obj/item/organ/tail/lizard/Initialize() - . = ..() + ..() color = "#"+ random_color() /obj/item/organ/tail/lizard/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = TRUE) @@ -77,3 +83,5 @@ new_tail.tail_type = tail_type new_tail.spines = spines +*/ +//SKYRAT EDIT REMOVAL END diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 8199582d6d7..10563177449 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -24,6 +24,8 @@ /datum/language/sylvan, /datum/language/shadowtongue, /datum/language/terrum, + /datum/language/vox, //SKYRAT EDIT - customization - extra languages + /datum/language/dwarf, //SKYRAT EDIT - customization - extra languages /datum/language/nekomimetic )) diff --git a/config/game_options.txt b/config/game_options.txt index 03a18aed8cb..d73ce2d4674 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -437,6 +437,7 @@ ROUNDSTART_RACES human ## Races that are strictly worse than humans that could probably be turned on without balance concerns ROUNDSTART_RACES lizard +ROUNDSTART_RACES felinid #ROUNDSTART_RACES fly ROUNDSTART_RACES moth ROUNDSTART_RACES plasmaman @@ -463,6 +464,16 @@ ROUNDSTART_RACES ethereal #ROUNDSTART_RACES military_synth #ROUNDSTART_RACES agent +## SKYRAT RACES DOWN THERE +ROUNDSTART_RACES mammal +ROUNDSTART_RACES xeno +ROUNDSTART_RACES slimeperson +ROUNDSTART_RACES podweak +ROUNDSTART_RACES dwarf +ROUNDSTART_RACES ipc +ROUNDSTART_RACES synthliz +ROUNDSTART_RACES vox + ##------------------------------------------------------------------------------------------- ## Roundstart no-reset races diff --git a/modular_skyrat/master_files/icons/mob/clothing/eyes_vox.dmi b/modular_skyrat/master_files/icons/mob/clothing/eyes_vox.dmi new file mode 100644 index 00000000000..8a7476807e6 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/eyes_vox.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/feet_digi.dmi b/modular_skyrat/master_files/icons/mob/clothing/feet_digi.dmi new file mode 100644 index 00000000000..f798850ee71 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/feet_digi.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/head_muzzled.dmi b/modular_skyrat/master_files/icons/mob/clothing/head_muzzled.dmi new file mode 100644 index 00000000000..62c1ebea0ac Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/head_muzzled.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/head_vox.dmi b/modular_skyrat/master_files/icons/mob/clothing/head_vox.dmi new file mode 100644 index 00000000000..1043eddb4bf Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/head_vox.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/mask_muzzled.dmi b/modular_skyrat/master_files/icons/mob/clothing/mask_muzzled.dmi new file mode 100644 index 00000000000..a1404cfbcef Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/mask_muzzled.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/mask_vox.dmi b/modular_skyrat/master_files/icons/mob/clothing/mask_vox.dmi new file mode 100644 index 00000000000..74ed17f71f2 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/mask_vox.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/suit_digi.dmi b/modular_skyrat/master_files/icons/mob/clothing/suit_digi.dmi new file mode 100644 index 00000000000..2616c0b8936 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/suit_digi.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/suit_taur_hoof.dmi b/modular_skyrat/master_files/icons/mob/clothing/suit_taur_hoof.dmi new file mode 100644 index 00000000000..03fd8c8a307 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/suit_taur_hoof.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/suit_taur_paw.dmi b/modular_skyrat/master_files/icons/mob/clothing/suit_taur_paw.dmi new file mode 100644 index 00000000000..24cf51d2e5d Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/suit_taur_paw.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/suit_taur_snake.dmi b/modular_skyrat/master_files/icons/mob/clothing/suit_taur_snake.dmi new file mode 100644 index 00000000000..d178ba4a1c1 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/suit_taur_snake.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/uniform_digi.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/uniform_digi.dmi new file mode 100644 index 00000000000..b1b9ded7f00 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/under/uniform_digi.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_hoof.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_hoof.dmi new file mode 100644 index 00000000000..f6d7794df35 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_hoof.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_paw.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_paw.dmi new file mode 100644 index 00000000000..f6d7794df35 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_paw.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_snake.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_snake.dmi new file mode 100644 index 00000000000..f6d7794df35 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_snake.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/uniform_digi.dmi b/modular_skyrat/master_files/icons/mob/clothing/uniform_digi.dmi new file mode 100644 index 00000000000..b1b9ded7f00 Binary files /dev/null and b/modular_skyrat/master_files/icons/mob/clothing/uniform_digi.dmi differ diff --git a/modular_skyrat/modules/customization/__DEFINES/inventory.dm b/modular_skyrat/modules/customization/__DEFINES/inventory.dm new file mode 100644 index 00000000000..838a297134c --- /dev/null +++ b/modular_skyrat/modules/customization/__DEFINES/inventory.dm @@ -0,0 +1,8 @@ +//flags for outfits that have mutant variants: Most of these require additional sprites to work. +#define STYLE_DIGITIGRADE (1<<0) //jumpsuits, suits and shoes +#define STYLE_MUZZLE (1<<1) //hats or masks +#define STYLE_TAUR_SNAKE (1<<2) //taur-friendly suits +#define STYLE_TAUR_PAW (1<<3) +#define STYLE_TAUR_HOOF (1<<4) +#define STYLE_TAUR_ALL (STYLE_TAUR_SNAKE|STYLE_TAUR_PAW|STYLE_TAUR_HOOF) +#define STYLE_VOX (1<<5) //For glasses, masks and head pieces for the Vox race diff --git a/modular_skyrat/modules/customization/__DEFINES/lists.dm b/modular_skyrat/modules/customization/__DEFINES/lists.dm new file mode 100644 index 00000000000..8dcf8448b51 --- /dev/null +++ b/modular_skyrat/modules/customization/__DEFINES/lists.dm @@ -0,0 +1,9 @@ +GLOBAL_LIST_EMPTY(sprite_accessories) +GLOBAL_LIST_EMPTY(generic_accessories) + +GLOBAL_LIST_EMPTY(body_markings) +GLOBAL_LIST_EMPTY_TYPED(body_markings_per_limb, /list) +GLOBAL_LIST_EMPTY(body_marking_sets) + +GLOBAL_LIST_EMPTY(loadout_items) +GLOBAL_LIST_EMPTY(loadout_category_to_subcategory_to_items) diff --git a/modular_skyrat/modules/customization/__DEFINES/loadout.dm b/modular_skyrat/modules/customization/__DEFINES/loadout.dm new file mode 100644 index 00000000000..6c13ab2bb72 --- /dev/null +++ b/modular_skyrat/modules/customization/__DEFINES/loadout.dm @@ -0,0 +1,57 @@ +#define LOADOUT_POINTS_MAX 10 + +#define LOADOUT_CATEGORY_NONE "ERROR" +//Those two subcategories are good to apply to any category +#define LOADOUT_SUBCATEGORY_MISC "Miscellaneous" +#define LOADOUT_SUBCATEGORY_JOB "Job-related" + +//In backpack +#define LOADOUT_CATEGORY_BACKPACK "In backpack" +#define LOADOUT_SUBCATEGORY_BACKPACK_TOYS "Toys" + +//Neck +#define LOADOUT_CATEGORY_NECK "Neck" +#define LOADOUT_SUBCATEGORY_NECK_TIE "Ties" +#define LOADOUT_SUBCATEGORY_NECK_SCARVES "Scarves" + +//Mask +#define LOADOUT_CATEGORY_MASK "Mask" + +//In hands +#define LOADOUT_CATEGORY_HANDS "In hands" + +//Uniform +#define LOADOUT_CATEGORY_UNIFORM "Uniform" +#define LOADOUT_SUBCATEGORY_UNIFORM_SUITS "Suits" +#define LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS "Skirts" +#define LOADOUT_SUBCATEGORY_UNIFORM_DRESSES "Dresses" +#define LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS "Sweaters" +#define LOADOUT_SUBCATEGORY_UNIFORM_PANTS "Pants" +#define LOADOUT_SUBCATEGORY_UNIFORM_SHORTS "Shorts" + +//Suit +#define LOADOUT_CATEGORY_SUIT "Suit" +#define LOADOUT_SUBCATEGORY_SUIT_COATS "Coats" +#define LOADOUT_SUBCATEGORY_SUIT_JACKETS "Jackets" + +//Head +#define LOADOUT_CATEGORY_HEAD "Head" + +//Shoes +#define LOADOUT_CATEGORY_SHOES "Shoes" + +//Gloves +#define LOADOUT_CATEGORY_GLOVES "Gloves" + +//Glasses +#define LOADOUT_CATEGORY_GLASSES "Glasses" + +//Loadout information types, allowing a user to set more customization to them +//Doesn't store any extra information a user could set +#define LOADOUT_INFO_NONE 0 +//Stores a "style", which user can set from a pre-defined list on the loadout datum +#define LOADOUT_INFO_STYLE 1 +//Stores a single color for use by the loadout datum +#define LOADOUT_INFO_ONE_COLOR 2 +//Stores three colors! Good for polychromatic stuff +#define LOADOUT_INFO_THREE_COLORS 3 diff --git a/modular_skyrat/modules/customization/__HELPERS/global_lists.dm b/modular_skyrat/modules/customization/__HELPERS/global_lists.dm new file mode 100644 index 00000000000..6c941565be4 --- /dev/null +++ b/modular_skyrat/modules/customization/__HELPERS/global_lists.dm @@ -0,0 +1,54 @@ +/proc/make_skyrat_datum_references() + make_sprite_accessory_references() + make_body_marking_references() + make_body_marking_set_references() + make_loadout_references() + +/proc/make_sprite_accessory_references() + // Here we build the global list for all accessories + for(var/path in subtypesof(/datum/sprite_accessory)) + var/datum/sprite_accessory/P = path + if(initial(P.key) && initial(P.name)) + P = new path() + if(!GLOB.sprite_accessories[P.key]) + GLOB.sprite_accessories[P.key] = list() + GLOB.sprite_accessories[P.key][P.name] = P + //TODO: Replace "generic" definitions with something better + if(P.generic && !GLOB.generic_accessories[P.key]) + GLOB.generic_accessories[P.key] = P.generic + +/proc/make_body_marking_references() + // Here we build the global list for all body markings + for(var/path in subtypesof(/datum/body_marking)) + var/datum/body_marking/BM = path + if(initial(BM.name)) + BM = new path() + GLOB.body_markings[BM.name] = BM + //We go through all the possible affected bodyparts and a name reference where applicable + for(var/marking_zone in GLOB.marking_zones) + var/bitflag = GLOB.marking_zone_to_bitflag[marking_zone] + if(BM.affected_bodyparts & bitflag) + if(!GLOB.body_markings_per_limb[marking_zone]) + GLOB.body_markings_per_limb[marking_zone] = list() + GLOB.body_markings_per_limb[marking_zone] += BM.name + +/proc/make_body_marking_set_references() + // Here we build the global list for all body markings sets + for(var/path in subtypesof(/datum/body_marking_set)) + var/datum/body_marking_set/BM = path + if(initial(BM.name)) + BM = new path() + GLOB.body_marking_sets[BM.name] = BM + +/proc/make_loadout_references() + // Here we build the global loadout lists + for(var/path in subtypesof(/datum/loadout_item)) + var/datum/loadout_item/L = path + if(initial(L.path)) + L = new path() + GLOB.loadout_items[L.path] = L + if(!GLOB.loadout_category_to_subcategory_to_items[L.category]) + GLOB.loadout_category_to_subcategory_to_items[L.category] = list() + if(!GLOB.loadout_category_to_subcategory_to_items[L.category][L.subcategory]) + GLOB.loadout_category_to_subcategory_to_items[L.category][L.subcategory] = list() + GLOB.loadout_category_to_subcategory_to_items[L.category][L.subcategory] += L.path diff --git a/modular_skyrat/modules/customization/__HELPERS/is_helpers.dm b/modular_skyrat/modules/customization/__HELPERS/is_helpers.dm new file mode 100644 index 00000000000..1dc3e0571b2 --- /dev/null +++ b/modular_skyrat/modules/customization/__HELPERS/is_helpers.dm @@ -0,0 +1,9 @@ +//Human sub species helpers +#define issynthliz(A) (is_species(A,/datum/species/synthliz)) +#define isvox(A) (is_species(A,/datum/species/vox)) +#define isipc(A) (is_species(A,/datum/species/ipc)) +#define ismammal(A) (is_species(A,/datum/species/mammal)) +#define ispodweak(A) (is_species(A,/datum/species/pod/podweak)) +#define isxenohybrid(A) (is_species(A,/datum/species/xeno)) +#define isdwarf(A) (is_species(A,/datum/species/dwarf)) +#define isroundstartslime(A) (is_species(A,/datum/species/jelly/roundstartslime)) diff --git a/modular_skyrat/modules/customization/__HELPERS/mobs.dm b/modular_skyrat/modules/customization/__HELPERS/mobs.dm new file mode 100644 index 00000000000..a529dfa9993 --- /dev/null +++ b/modular_skyrat/modules/customization/__HELPERS/mobs.dm @@ -0,0 +1,63 @@ +/proc/random_features() + /*if(!GLOB.tails_list_human.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, GLOB.tails_list_human) + if(!GLOB.tails_list_lizard.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, GLOB.tails_list_lizard) + if(!GLOB.snouts_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts, GLOB.snouts_list) + if(!GLOB.horns_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/horns, GLOB.horns_list) + if(!GLOB.ears_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, GLOB.horns_list) + if(!GLOB.frills_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, GLOB.frills_list) + if(!GLOB.spines_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, GLOB.spines_list) + if(!GLOB.legs_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, GLOB.legs_list) + if(!GLOB.body_markings_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list) + if(!GLOB.wings_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, GLOB.wings_list) + if(!GLOB.moth_wings_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_wings, GLOB.moth_wings_list) + if(!GLOB.moth_markings_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_markings, GLOB.moth_markings_list)*/ + //For now we will always return none for tail_human and ears. + return MANDATORY_FEATURE_LIST + +/proc/accessory_list_of_key_for_species(key, datum/species/S) + var/list/accessory_list = list() + for(var/name in GLOB.sprite_accessories[key]) + var/datum/sprite_accessory/SP = GLOB.sprite_accessories[key][name] + if(SP.recommended_species && !(S.id in SP.recommended_species)) + continue + accessory_list += SP.name + return accessory_list + + +/proc/random_accessory_of_key_for_species(key, datum/species/S) + var/list/accessory_list = accessory_list_of_key_for_species(key, S) + var/datum/sprite_accessory/SP = GLOB.sprite_accessories[key][pick(accessory_list)] + if(!SP) + CRASH("Cant find random accessory of [key] key, for species [S.id]") + return SP + +/proc/random_unique_vox_name(attempts_to_find_unique_name=10) + for(var/i in 1 to attempts_to_find_unique_name) + . = capitalize(vox_name()) + + if(!findname(.)) + break + +/proc/assemble_body_markings_from_set(datum/body_marking_set/BMS, list/features, datum/species/pref_species) + var/list/body_markings = list() + for(var/set_name in BMS.body_marking_list) + var/datum/body_marking/BM = GLOB.body_markings[set_name] + for(var/zone in GLOB.body_markings_per_limb) + var/list/marking_list = GLOB.body_markings_per_limb[zone] + if(set_name in marking_list) + if(!body_markings[zone]) + body_markings[zone] = list() + body_markings[zone][set_name] = BM.get_default_color(features, pref_species) + return body_markings diff --git a/modular_skyrat/modules/customization/__HELPERS/names.dm b/modular_skyrat/modules/customization/__HELPERS/names.dm new file mode 100644 index 00000000000..d2d94859633 --- /dev/null +++ b/modular_skyrat/modules/customization/__HELPERS/names.dm @@ -0,0 +1,9 @@ +/proc/vox_name() + var/sounds = rand(2, 8) + var/i = 0 + var/newname = "" + + while(i <= sounds) + i++ + newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah","ri","ra")) + return newname diff --git a/modular_skyrat/modules/customization/_globalvars/lists.dm b/modular_skyrat/modules/customization/_globalvars/lists.dm new file mode 100644 index 00000000000..a2a46e32423 --- /dev/null +++ b/modular_skyrat/modules/customization/_globalvars/lists.dm @@ -0,0 +1,56 @@ +//DO NOT CHANGE THOSE LISTS UNLESS YOU KNOW WHAT YOURE DOING (will mess savefiles) + + +GLOBAL_LIST_INIT(breasts_size_translation, list("0" = "Flatchested", + "1" = "A", + "2" = "B", + "3" = "C", + "4" = "D", + "5" = "E", + "6" = "F", + "7" = "G", + "8" = "H", + "9" = "I", + "10" = "J", + "11" = "K", + "12" = "L", + "13" = "M", + "14" = "N", + "15" = "O", + "16" = "P", + )) + +GLOBAL_LIST_INIT(balls_size_translation, list("0" = "Small", + "1" = "Average", + "2" = "Big", + "3" = "Enormous" + )) + +/*GLOBAL_LIST_INIT(bitflag_to_marking_zones, list(HEAD = "Head", + CHEST = "Chest", + LEG_LEFT = "Left Leg", + LEG_RIGHT = "Right Leg", + ARM_LEFT = "Left Arm", + ARM_RIGHT = "Right Arm", + HAND_LEFT = "Left Hand", + HAND_RIGHT = "Right Hand" + ))*/ + +GLOBAL_LIST_INIT(marking_zone_to_bitflag, list(BODY_ZONE_HEAD = HEAD, + BODY_ZONE_CHEST = CHEST, + BODY_ZONE_L_LEG = LEG_LEFT, + BODY_ZONE_R_LEG = LEG_RIGHT, + BODY_ZONE_L_ARM = ARM_LEFT, + BODY_ZONE_R_ARM = ARM_RIGHT, + BODY_ZONE_PRECISE_L_HAND = HAND_LEFT, + BODY_ZONE_PRECISE_R_HAND = HAND_RIGHT + )) + +//GLOBAL_LIST_INIT(marking_zones, list("Head","Chest","Left Leg","Right Leg","Left Arm","Right Arm","Left Hand","Right Hand")) + +GLOBAL_LIST_INIT(marking_zones, list(BODY_ZONE_HEAD,BODY_ZONE_CHEST,BODY_ZONE_L_LEG,BODY_ZONE_R_LEG,BODY_ZONE_L_ARM,BODY_ZONE_R_ARM,BODY_ZONE_PRECISE_L_HAND,BODY_ZONE_PRECISE_R_HAND)) + +///Those are the values available from prefs +GLOBAL_LIST_INIT(preference_breast_sizes, list("Flatchested","A","B","C","D","E","F","G","H")) + +GLOBAL_LIST_INIT(preference_balls_sizes, list("Small","Average","Big","Enormous")) diff --git a/modular_skyrat/modules/customization/datums/dna.dm b/modular_skyrat/modules/customization/datums/dna.dm new file mode 100644 index 00000000000..b2f35531eb5 --- /dev/null +++ b/modular_skyrat/modules/customization/datums/dna.dm @@ -0,0 +1,75 @@ +/datum/dna + var/list/list/mutant_bodyparts = list() + features = MANDATORY_FEATURE_LIST + ///Body markings of the DNA's owner. This is for storing their original state for re-creating the character. They'll get changed on species mutation + var/list/list/body_markings = list() + +/datum/dna/proc/initialize_dna(newblood_type, skip_index = FALSE) + if(newblood_type) + blood_type = newblood_type + unique_enzymes = generate_unique_enzymes() + uni_identity = generate_uni_identity() + if(!skip_index) //I hate this + generate_dna_blocks() + features = species.get_random_features() + mutant_bodyparts = species.get_random_mutant_bodyparts(features) + +/mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, var/datum/preferences/pref_load) + if(mrace && has_dna()) + var/datum/species/new_race + if(ispath(mrace)) + new_race = new mrace + else if(istype(mrace)) + new_race = mrace + else + return + deathsound = new_race.deathsound + dna.species.on_species_loss(src, new_race, pref_load) + var/datum/species/old_species = dna.species + dna.species = new_race + //BODYPARTS AND FEATURES + var/list/bodyparts_to_add + var/list/organs_to_build = list() + if(pref_load) + dna.features = pref_load.features.Copy() + dna.real_name = pref_load.real_name + dna.mutant_bodyparts = pref_load.mutant_bodyparts.Copy() + dna.body_markings = pref_load.body_markings.Copy() + dna.species.body_markings = pref_load.body_markings.Copy() + else + dna.features = new_race.get_random_features() + dna.mutant_bodyparts = new_race.get_random_mutant_bodyparts(dna.features) + dna.body_markings = new_race.get_random_body_markings(dna.features) + dna.species.body_markings = dna.body_markings.Copy() + + bodyparts_to_add = dna.mutant_bodyparts.Copy() + + for(var/key in bodyparts_to_add) + var/datum/sprite_accessory/SP = GLOB.sprite_accessories[key][bodyparts_to_add[key][MUTANT_INDEX_NAME]] + if(!SP.factual) + bodyparts_to_add -= key + continue + if(SP.organ_type) + organs_to_build[key] = SP.organ_type + //Why dont we remove the key from the list here, as it's gonna get added either way? + //Well there's some jank that makes the organ not properly do it on initializations, which doesnt happen on organ manipulations + //And this way there is literally no difference in practice + dna.species.mutant_bodyparts = bodyparts_to_add.Copy() + + dna.species.on_species_gain(src, old_species, pref_load) + + //We have to build them later as they require other DNA information + for(var/key in organs_to_build) + var/path = organs_to_build[key] + var/obj/item/organ/ORG = new path + ORG.build_from_dna(dna, key) + ORG.Insert(src, 0, FALSE) + + dna.species.mutant_bodyparts = bodyparts_to_add.Copy() + //END OF BODYPARTS AND FEATURES + //dna.species.on_species_gain(src, old_species, pref_load) + if(ishuman(src)) + qdel(language_holder) + var/species_holder = initial(mrace.species_language_holder) + language_holder = new species_holder(src) + update_atom_languages() diff --git a/modular_skyrat/modules/customization/game/objects/items/balls.dm b/modular_skyrat/modules/customization/game/objects/items/balls.dm new file mode 100644 index 00000000000..6fbcfce1420 --- /dev/null +++ b/modular_skyrat/modules/customization/game/objects/items/balls.dm @@ -0,0 +1,74 @@ +/obj/item/toy/tennis + name = "tennis ball" + desc = "A classical tennis ball. It appears to have faint bite marks scattered all over its surface." + icon = 'modular_skyrat/modules/customization/icons/obj/balls.dmi' + icon_state = "tennis_classic" + lefthand_file = 'modular_skyrat/modules/customization/icons/mob/inhands/balls_left.dmi' + righthand_file = 'modular_skyrat/modules/customization/icons/mob/inhands/balls_right.dmi' + inhand_icon_state = "tennis_classic" + worn_icon = 'modular_skyrat/modules/customization/icons/mob/mouthball.dmi' + slot_flags = ITEM_SLOT_HEAD | ITEM_SLOT_NECK | ITEM_SLOT_EARS //Fluff item, put it wherever you want! + throw_range = 14 + w_class = WEIGHT_CLASS_SMALL + +/obj/item/toy/tennis/rainbow + name = "pseudo-euclidean interdimensional tennis sphere" + desc = "A tennis ball from another plane of existance. Really groovy." + icon_state = "tennis_rainbow" + inhand_icon_state = "tennis_rainbow" + actions_types = list(/datum/action/item_action/squeeze) //Giving the masses easy access to unilimted honks would be annoying + +/obj/item/toy/tennis/rainbow/Initialize() + . = ..() + AddComponent(/datum/component/squeak) + +/obj/item/toy/tennis/rainbow/izzy //izzyinbox's donator item + name = "Katlin's Ball" + desc = "A tennis ball that's seen a good bit of love, being covered in a few black and white hairs and slobber." + icon_state = "tennis_izzy" + inhand_icon_state = "tennis_izzy" + +/obj/item/toy/tennis/red //da red wuns go fasta + name = "red tennis ball" + desc = "A red tennis ball. It goes three times faster!" + icon_state = "tennis_red" + inhand_icon_state = "tennis_red" + throw_speed = 9 + +/obj/item/toy/tennis/yellow //because yellow is hot I guess + name = "yellow tennis ball" + desc = "A yellow tennis ball. It seems to have a flame-retardant coating." + icon_state = "tennis_yellow" + inhand_icon_state = "tennis_yellow" + resistance_flags = FIRE_PROOF + +/obj/item/toy/tennis/green //pestilence + name = "green tennis ball" + desc = "A green tennis ball. It seems to have an impermeable coating." + icon_state = "tennis_green" + inhand_icon_state = "tennis_green" + permeability_coefficient = 0.9 + +/obj/item/toy/tennis/cyan //electric + name = "cyan tennis ball" + desc = "A cyan tennis ball. It seems to have odd electrical properties." + icon_state = "tennis_cyan" + inhand_icon_state = "tennis_cyan" + siemens_coefficient = 0.9 + +/obj/item/toy/tennis/blue //reliability + name = "blue tennis ball" + desc = "A blue tennis ball. It seems ever so slightly more robust than normal." + icon_state = "tennis_blue" + inhand_icon_state = "tennis_blue" + max_integrity = 300 + +/obj/item/toy/tennis/purple //because purple dyes have high pH and would neutralize acids I guess + name = "purple tennis ball" + desc = "A purple tennis ball. It seems to have an acid-resistant coating." + icon_state = "tennis_purple" + inhand_icon_state = "tennis_purple" + resistance_flags = ACID_PROOF + +/datum/action/item_action/squeeze + name = "Squeak!" diff --git a/modular_skyrat/modules/customization/game/objects/items/storage/rings.dm b/modular_skyrat/modules/customization/game/objects/items/storage/rings.dm new file mode 100644 index 00000000000..998de22de8f --- /dev/null +++ b/modular_skyrat/modules/customization/game/objects/items/storage/rings.dm @@ -0,0 +1,28 @@ +/* + * Ring Box + */ + +/obj/item/storage/fancy/ringbox + name = "ring box" + desc = "A tiny box covered in soft red felt made for holding rings." + icon = 'modular_skyrat/modules/customization/icons/obj/ring.dmi' + icon_state = "gold ringbox" + icon_type = "gold ring" + w_class = WEIGHT_CLASS_TINY + spawn_type = /obj/item/clothing/gloves/ring + +/obj/item/storage/fancy/ringbox/ComponentInitialize() + . = ..() + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_items = 1 + STR.can_hold = typecacheof(list(/obj/item/clothing/gloves/ring)) + +/obj/item/storage/fancy/ringbox/diamond + icon_state = "diamond ringbox" + icon_type = "diamond ring" + spawn_type = /obj/item/clothing/gloves/ring/diamond + +/obj/item/storage/fancy/ringbox/silver + icon_state = "silver ringbox" + icon_type = "silver ring" + spawn_type = /obj/item/clothing/gloves/ring/silver diff --git a/modular_skyrat/modules/customization/game/objects/items/tanks/n2_tanks.dm b/modular_skyrat/modules/customization/game/objects/items/tanks/n2_tanks.dm new file mode 100644 index 00000000000..9533294e49a --- /dev/null +++ b/modular_skyrat/modules/customization/game/objects/items/tanks/n2_tanks.dm @@ -0,0 +1,33 @@ +/* + * Nitrogen Tanks for Vox + */ + +/obj/item/tank/internals/nitrogen + name = "nitrogen tank" + desc = "A tank of nitrogen. Designed specifically for Vox" + icon_state = "oxygen_fr" + force = 10 + distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE + +/obj/item/tank/internals/nitrogen/populate_gas() + air_contents.assert_gas(/datum/gas/nitrogen) + air_contents.gases[/datum/gas/nitrogen][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + +/obj/item/tank/internals/nitrogen/full/populate_gas() + air_contents.assert_gas(/datum/gas/nitrogen) + air_contents.gases[/datum/gas/nitrogen][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + + +/obj/item/tank/internals/nitrogen/belt + icon = 'modular_skyrat/modules/customization/icons/obj/tank.dmi' + lefthand_file = 'modular_skyrat/modules/customization/icons/mob/inhands/equipment/tanks_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/customization/icons/mob/inhands/equipment/tanks_righthand.dmi' + icon_state = "nitrogen_extended" + slot_flags = ITEM_SLOT_BELT + force = 5 + volume = 6 + w_class = WEIGHT_CLASS_SMALL + +/obj/item/tank/internals/nitrogen/belt/full/populate_gas() + air_contents.assert_gas(/datum/gas/nitrogen) + air_contents.gases[/datum/gas/nitrogen][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) diff --git a/modular_skyrat/modules/customization/icons/misc/language.dmi b/modular_skyrat/modules/customization/icons/misc/language.dmi new file mode 100644 index 00000000000..fb82122b251 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/misc/language.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/body_markings/secondary_markings.dmi b/modular_skyrat/modules/customization/icons/mob/body_markings/secondary_markings.dmi new file mode 100644 index 00000000000..7ecdfca56c1 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/body_markings/secondary_markings.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/body_markings/synthliz_secondary.dmi b/modular_skyrat/modules/customization/icons/mob/body_markings/synthliz_secondary.dmi new file mode 100644 index 00000000000..619ac2518c6 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/body_markings/synthliz_secondary.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/body_markings/synthliz_tertiary.dmi b/modular_skyrat/modules/customization/icons/mob/body_markings/synthliz_tertiary.dmi new file mode 100644 index 00000000000..63bc4ec755e Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/body_markings/synthliz_tertiary.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/body_markings/tertiary_markings.dmi b/modular_skyrat/modules/customization/icons/mob/body_markings/tertiary_markings.dmi new file mode 100644 index 00000000000..3971e8ada6e Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/body_markings/tertiary_markings.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/body_markings/vox_secondary.dmi b/modular_skyrat/modules/customization/icons/mob/body_markings/vox_secondary.dmi new file mode 100644 index 00000000000..4bfa940ce6b Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/body_markings/vox_secondary.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/body_markings/vox_tertiary.dmi b/modular_skyrat/modules/customization/icons/mob/body_markings/vox_tertiary.dmi new file mode 100644 index 00000000000..e014d51a647 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/body_markings/vox_tertiary.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/clothing/ears.dmi b/modular_skyrat/modules/customization/icons/mob/clothing/ears.dmi new file mode 100644 index 00000000000..016e396e947 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/clothing/ears.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/clothing/feet.dmi b/modular_skyrat/modules/customization/icons/mob/clothing/feet.dmi new file mode 100644 index 00000000000..2b28d069766 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/clothing/feet.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/clothing/hands.dmi b/modular_skyrat/modules/customization/icons/mob/clothing/hands.dmi new file mode 100644 index 00000000000..e3722919394 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/clothing/hands.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/clothing/head.dmi b/modular_skyrat/modules/customization/icons/mob/clothing/head.dmi new file mode 100644 index 00000000000..53b491cce76 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/clothing/head.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/clothing/neck.dmi b/modular_skyrat/modules/customization/icons/mob/clothing/neck.dmi new file mode 100644 index 00000000000..86dec62a416 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/clothing/neck.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi b/modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi new file mode 100644 index 00000000000..9d97ae36b50 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/clothing/underwear.dmi b/modular_skyrat/modules/customization/icons/mob/clothing/underwear.dmi new file mode 100644 index 00000000000..b4be221456e Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/clothing/underwear.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi b/modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi new file mode 100644 index 00000000000..fa376635f92 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/inhands/balls_left.dmi b/modular_skyrat/modules/customization/icons/mob/inhands/balls_left.dmi new file mode 100644 index 00000000000..2e751d0f449 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/inhands/balls_left.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/inhands/balls_right.dmi b/modular_skyrat/modules/customization/icons/mob/inhands/balls_right.dmi new file mode 100644 index 00000000000..45ee6864f0b Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/inhands/balls_right.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/inhands/equipment/tanks_lefthand.dmi b/modular_skyrat/modules/customization/icons/mob/inhands/equipment/tanks_lefthand.dmi new file mode 100644 index 00000000000..649b369f6c8 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/inhands/equipment/tanks_lefthand.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/inhands/equipment/tanks_righthand.dmi b/modular_skyrat/modules/customization/icons/mob/inhands/equipment/tanks_righthand.dmi new file mode 100644 index 00000000000..468b6de04b0 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/inhands/equipment/tanks_righthand.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/mouthball.dmi b/modular_skyrat/modules/customization/icons/mob/mouthball.dmi new file mode 100644 index 00000000000..b5c08dd6487 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/mouthball.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/mutant_bodyparts.dmi b/modular_skyrat/modules/customization/icons/mob/mutant_bodyparts.dmi new file mode 100644 index 00000000000..89c30e79c06 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/mutant_bodyparts.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/species/ipc_parts.dmi b/modular_skyrat/modules/customization/icons/mob/species/ipc_parts.dmi new file mode 100644 index 00000000000..bef1afec915 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/species/ipc_parts.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/species/mammal_parts_greyscale.dmi b/modular_skyrat/modules/customization/icons/mob/species/mammal_parts_greyscale.dmi new file mode 100644 index 00000000000..18310a0d128 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/species/mammal_parts_greyscale.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/species/synthliz_parts_greyscale.dmi b/modular_skyrat/modules/customization/icons/mob/species/synthliz_parts_greyscale.dmi new file mode 100644 index 00000000000..169b4d7c926 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/species/synthliz_parts_greyscale.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/species/vox_eyes.dmi b/modular_skyrat/modules/customization/icons/mob/species/vox_eyes.dmi new file mode 100644 index 00000000000..f726e216051 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/species/vox_eyes.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/species/vox_parts_greyscale.dmi b/modular_skyrat/modules/customization/icons/mob/species/vox_parts_greyscale.dmi new file mode 100644 index 00000000000..88b1e6018ec Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/species/vox_parts_greyscale.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/species/xeno_parts_greyscale.dmi b/modular_skyrat/modules/customization/icons/mob/species/xeno_parts_greyscale.dmi new file mode 100644 index 00000000000..a1b8b20ddf2 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/species/xeno_parts_greyscale.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ears.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ears.dmi new file mode 100644 index 00000000000..ce53b91af4b Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ears.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/frills.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/frills.dmi new file mode 100644 index 00000000000..574372f4d6a Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/frills.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/breasts_onmob.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/breasts_onmob.dmi new file mode 100644 index 00000000000..2c9cbe63549 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/breasts_onmob.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/penis_onmob.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/penis_onmob.dmi new file mode 100644 index 00000000000..d1ba6ccdf6b Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/penis_onmob.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/taur_penis_onmob.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/taur_penis_onmob.dmi new file mode 100644 index 00000000000..66497599bbc Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/taur_penis_onmob.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/testicles_onmob.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/testicles_onmob.dmi new file mode 100644 index 00000000000..91e50dd64e8 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/testicles_onmob.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/vagina_onmob.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/vagina_onmob.dmi new file mode 100644 index 00000000000..227e1343e8f Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/vagina_onmob.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ipc_antennas.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ipc_antennas.dmi new file mode 100644 index 00000000000..b60f400212d Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ipc_antennas.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ipc_screens.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ipc_screens.dmi new file mode 100644 index 00000000000..c7d44da5a84 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/ipc_screens.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/moth_wings.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/moth_wings.dmi new file mode 100644 index 00000000000..04ecff4f647 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/moth_wings.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/snouts.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/snouts.dmi new file mode 100644 index 00000000000..016174c3971 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/snouts.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_antennas.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_antennas.dmi new file mode 100644 index 00000000000..dd8f25647f5 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_antennas.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_snouts.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_snouts.dmi new file mode 100644 index 00000000000..c671e82a4fb Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_snouts.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_tails.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_tails.dmi new file mode 100644 index 00000000000..c411a53600e Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_tails.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/tails.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/tails.dmi new file mode 100644 index 00000000000..d87ff63726e Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/tails.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/taur.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/taur.dmi new file mode 100644 index 00000000000..b70e90fd3ab Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/taur.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_facial_hair.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_facial_hair.dmi new file mode 100644 index 00000000000..b9405b95eb3 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_facial_hair.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_hair.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_hair.dmi new file mode 100644 index 00000000000..cae45bed16a Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_hair.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_snouts.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_snouts.dmi new file mode 100644 index 00000000000..9ceadcb3f34 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_snouts.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_spines.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_spines.dmi new file mode 100644 index 00000000000..04c9f7b3963 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_spines.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_tails.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_tails.dmi new file mode 100644 index 00000000000..f1053a6f380 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_tails.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/wings.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/wings.dmi new file mode 100644 index 00000000000..3926a91139f Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/wings.dmi differ diff --git a/modular_skyrat/modules/customization/icons/mob/sprite_accessory/xeno_parts.dmi b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/xeno_parts.dmi new file mode 100644 index 00000000000..c25f4764f72 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/sprite_accessory/xeno_parts.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/balls.dmi b/modular_skyrat/modules/customization/icons/obj/balls.dmi new file mode 100644 index 00000000000..9b9f4575b39 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/balls.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/clothing/accessories.dmi b/modular_skyrat/modules/customization/icons/obj/clothing/accessories.dmi new file mode 100644 index 00000000000..f186134ac4c Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/clothing/accessories.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/clothing/gloves.dmi b/modular_skyrat/modules/customization/icons/obj/clothing/gloves.dmi new file mode 100644 index 00000000000..1c596a6a0ff Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/clothing/gloves.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi b/modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi new file mode 100644 index 00000000000..23a21420499 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/clothing/neck.dmi b/modular_skyrat/modules/customization/icons/obj/clothing/neck.dmi new file mode 100644 index 00000000000..622f43ea568 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/clothing/neck.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/clothing/shoes.dmi b/modular_skyrat/modules/customization/icons/obj/clothing/shoes.dmi new file mode 100644 index 00000000000..f23cdaee46c Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/clothing/shoes.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi b/modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi new file mode 100644 index 00000000000..fed81adfcca Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi b/modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi new file mode 100644 index 00000000000..57424c7b992 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/genitals/breasts.dmi b/modular_skyrat/modules/customization/icons/obj/genitals/breasts.dmi new file mode 100644 index 00000000000..c57fbe5fc8a Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/genitals/breasts.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/genitals/penis.dmi b/modular_skyrat/modules/customization/icons/obj/genitals/penis.dmi new file mode 100644 index 00000000000..c3fd184a7c2 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/genitals/penis.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/genitals/testicles.dmi b/modular_skyrat/modules/customization/icons/obj/genitals/testicles.dmi new file mode 100644 index 00000000000..386eab09561 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/genitals/testicles.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/genitals/vagina.dmi b/modular_skyrat/modules/customization/icons/obj/genitals/vagina.dmi new file mode 100644 index 00000000000..1bbe62ba0e1 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/genitals/vagina.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/ring.dmi b/modular_skyrat/modules/customization/icons/obj/ring.dmi new file mode 100644 index 00000000000..e24f1fab4c9 Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/ring.dmi differ diff --git a/modular_skyrat/modules/customization/icons/obj/tank.dmi b/modular_skyrat/modules/customization/icons/obj/tank.dmi new file mode 100644 index 00000000000..6e5d8b4270a Binary files /dev/null and b/modular_skyrat/modules/customization/icons/obj/tank.dmi differ diff --git a/modular_skyrat/modules/customization/modules/client/loadout/_loadout.dm b/modular_skyrat/modules/customization/modules/client/loadout/_loadout.dm new file mode 100644 index 00000000000..2e266472bcb --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/_loadout.dm @@ -0,0 +1,54 @@ +/datum/loadout_item + var/name + ///Category in which the item belongs to LOADOUT_CATEGORY_UNIFORM, LOADOUT_CATEGORY_BACKPACK etc. + var/category = LOADOUT_CATEGORY_NONE + ///Subcategory in which the item belongs to + var/subcategory = LOADOUT_SUBCATEGORY_MISC + ///Description of the loadout item, automatically set by New() if null + var/description + ///Typepath to the item being spawned + var/path + ///How much loadout points does it cost? + var/cost = 1 + ///If set, it's a list containing ckeys which only can get the item + var/list/ckeywhitelist + ///If set, is a list of job names of which can get the loadout item + var/list/restricted_roles + ///Descriptive explanation of the restricted roles, if empty will automatically generate on New() if nessecary + var/restricted_desc + ///Extra information which the user can set. (LOADOUT_INFO_NONE, LOADOUT_INFO_STYLE, LOADOUT_INFO_ONE_COLOR, LOADOUT_INFO_THREE_COLORS) + var/extra_info + +/datum/loadout_item/New() + if(!description && path) + var/obj/O = path + description = initial(O.desc) + if(restricted_roles && !restricted_desc) + var/passed_first = FALSE + restricted_desc = "" + for(var/job_name in restricted_roles) + if(!passed_first) + passed_first = TRUE + else + restricted_desc += ", " + restricted_desc += job_name + +/datum/loadout_item/proc/get_spawned_item(customization) //Pass the value from the associative list + var/obj/item/spawned = new path() + if(customization != "None") + customize(spawned, customization) + return spawned + +//Proc designed to be overwritten by invidivual loadout items. has support for a one color feed, as that is common +/datum/loadout_item/proc/customize(var/obj/item/spawned, customization) + if(extra_info == LOADOUT_INFO_ONE_COLOR) + spawned.color = "#[customization]" + +/datum/loadout_item/proc/default_customization() + switch(extra_info) + if(LOADOUT_INFO_ONE_COLOR) + return "FFF" + if(LOADOUT_INFO_THREE_COLORS) + return "FFF|FFF|FFF" + else + return "None" diff --git a/modular_skyrat/modules/customization/modules/client/loadout/backpack.dm b/modular_skyrat/modules/customization/modules/client/loadout/backpack.dm new file mode 100644 index 00000000000..9db019f1640 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/backpack.dm @@ -0,0 +1,159 @@ +/datum/loadout_item/backpack + category = LOADOUT_CATEGORY_BACKPACK + +//MISC +/datum/loadout_item/backpack/matches + name = "Matchbox" + path = /obj/item/storage/box/matches + +/datum/loadout_item/backpack/cheaplighter + name = "Cheap lighter" + path = /obj/item/lighter/greyscale + +/datum/loadout_item/backpack/zippolighter + name = "Zippo Lighter" + path = /obj/item/lighter + cost = 2 + +/datum/loadout_item/backpack/cigar + name = "Cigar" + path = /obj/item/clothing/mask/cigarette/cigar + cost = 4 //smoking is bad mkay + +/datum/loadout_item/backpack/cigarettes + name = "Cigarette pack" + path = /obj/item/storage/fancy/cigarettes + +/datum/loadout_item/backpack/wallet + name = "Wallet" + path = /obj/item/storage/wallet + +/datum/loadout_item/backpack/flask + name = "Flask" + path = /obj/item/reagent_containers/food/drinks/flask + cost = 2 + +/datum/loadout_item/backpack/skub + name = "Skub" + path = /obj/item/skub + +/datum/loadout_item/backpack/multipen + name = "A multicolored pen" + path = /obj/item/pen/fourcolor + +/datum/loadout_item/backpack/fountainpen + name = "A fancy pen" + path = /obj/item/pen/fountain + cost = 2 + +/datum/loadout_item/backpack/modular_tablet + name = "A modular tablet" + path = /obj/item/modular_computer/tablet/preset/cheap/ + cost = 4 + +/datum/loadout_item/backpack/modular_laptop + name = "A modular laptop" + path = /obj/item/modular_computer/laptop/preset/civilian + cost = 7 + +/datum/loadout_item/backpack/ringbox_gold + name = "A gold ring box" + path = /obj/item/storage/fancy/ringbox + cost = 3 + +/datum/loadout_item/backpack/ringbox_silver + name = "A silver ring box" + path = /obj/item/storage/fancy/ringbox/silver + cost = 3 + +/datum/loadout_item/backpack/ringbox_diamond + name = "A diamond ring box" + path = /obj/item/storage/fancy/ringbox/diamond + cost = 5 + +/datum/loadout_item/backpack/tapeplayer + name = "Taperecorder" + path = /obj/item/taperecorder + +/datum/loadout_item/backpack/tape + name = "Spare cassette tape" + path = /obj/item/tape/random + +/datum/loadout_item/backpack/newspaper + name = "Newspaper" + path = /obj/item/newspaper + +//TOYS +/datum/loadout_item/backpack/toy + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS + +/datum/loadout_item/backpack/toy/dice + name = "Dice bag" + path = /obj/item/storage/pill_bottle/dice + +/datum/loadout_item/backpack/toy/eightball + name = "Magic eightball" + path = /obj/item/toy/eightball + +/datum/loadout_item/backpack/toy/cards + name = "Playing cards" + path = /obj/item/toy/cards/deck + +/datum/loadout_item/backpack/toy/plushcarp + name = "Space carp plushie" + path = /obj/item/toy/plush/carpplushie + +/datum/loadout_item/backpack/toy/plushliz + name = "Lizard plushie" + path = /obj/item/toy/plush/lizardplushie + +/datum/loadout_item/backpack/toy/plushsnek + name = "Snake plushie" + path = /obj/item/toy/plush/snakeplushie + +/datum/loadout_item/backpack/toy/plushslime + name = "Slime plushie" + path = /obj/item/toy/plush/slimeplushie + +/datum/loadout_item/backpack/toy/tennis + name = "Classic Tennis Ball" + path = /obj/item/toy/tennis + +/datum/loadout_item/backpack/toy/tennisred + name = "Red Tennis Ball" + path = /obj/item/toy/tennis/red + +/datum/loadout_item/backpack/toy/tennisyellow + name = "Yellow Tennis Ball" + path = /obj/item/toy/tennis/yellow + +/datum/loadout_item/backpack/toy/tennisgreen + name = "Green Tennis Ball" + path = /obj/item/toy/tennis/green + +/datum/loadout_item/backpack/toy/tenniscyan + name = "Cyan Tennis Ball" + path = /obj/item/toy/tennis/cyan + +/datum/loadout_item/backpack/toy/tennisblue + name = "Blue Tennis Ball" + path = /obj/item/toy/tennis/blue + +/datum/loadout_item/backpack/toy/tennispurple + name = "Purple Tennis Ball" + path = /obj/item/toy/tennis/purple + +/datum/loadout_item/backpack/toy/toykatana + name = "Toy Katana" + path = /obj/item/toy/katana + cost = 3 + +/datum/loadout_item/backpack/toy/crayons + name = "Box of crayons" + path = /obj/item/storage/crayons + +/datum/loadout_item/backpack/toy/narplush + name = "Narsie Plushie" + path = /obj/item/toy/plush/narplush + cost = 5 + restricted_roles = list("Chaplain") diff --git a/modular_skyrat/modules/customization/modules/client/loadout/glasses.dm b/modular_skyrat/modules/customization/modules/client/loadout/glasses.dm new file mode 100644 index 00000000000..ff4bfcdeb43 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/glasses.dm @@ -0,0 +1,48 @@ +/datum/loadout_item/glasses + category = LOADOUT_CATEGORY_GLASSES + +//MISC +/datum/loadout_item/glasses/blindfold + name = "Blindfold" + path = /obj/item/clothing/glasses/blindfold + +/datum/loadout_item/glasses/cold + name = "Cold goggles" + path = /obj/item/clothing/glasses/cold + +/datum/loadout_item/glasses/eyepatch + name = "Eyepatch" + path = /obj/item/clothing/glasses/eyepatch + +/datum/loadout_item/glasses/heat + name = "Heat goggles" + path = /obj/item/clothing/glasses/heat + +/datum/loadout_item/glasses/hipster + name = "Hipster glasses" + path = /obj/item/clothing/glasses/regular/hipster + +/datum/loadout_item/glasses/jamjar + name = "Jamjar glasses" + path = /obj/item/clothing/glasses/regular/jamjar + +/datum/loadout_item/glasses/monocle + name = "Monocle" + path = /obj/item/clothing/glasses/monocle + +/datum/loadout_item/glasses/orange + name = "Orange glasses" + path = /obj/item/clothing/glasses/orange + +/datum/loadout_item/glasses/red + name = "Red Glasses" + path = /obj/item/clothing/glasses/red + +/datum/loadout_item/glasses/prescription + name = "Prescription glasses" + path = /obj/item/clothing/glasses/regular + +/datum/loadout_item/glasses/sechud + name = "Security Hud" + path = /obj/item/clothing/glasses/hud/security + restricted_roles = list("Security Officer", "Warden", "Head of Security") diff --git a/modular_skyrat/modules/customization/modules/client/loadout/gloves.dm b/modular_skyrat/modules/customization/modules/client/loadout/gloves.dm new file mode 100644 index 00000000000..ceb623604fa --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/gloves.dm @@ -0,0 +1,22 @@ +/datum/loadout_item/gloves + category = LOADOUT_CATEGORY_GLOVES + +//MISC +/datum/loadout_item/gloves/fingerless + name = "Fingerless Gloves" + path = /obj/item/clothing/gloves/fingerless + +/datum/loadout_item/gloves/goldring + name = "A gold ring" + path = /obj/item/clothing/gloves/ring + cost = 2 + +/datum/loadout_item/gloves/silverring + name = "A silver ring" + path = /obj/item/clothing/gloves/ring/silver + cost = 2 + +/datum/loadout_item/gloves/diamondring + name = "A diamond ring" + path = /obj/item/clothing/gloves/ring/diamond + cost = 4 diff --git a/modular_skyrat/modules/customization/modules/client/loadout/hands.dm b/modular_skyrat/modules/customization/modules/client/loadout/hands.dm new file mode 100644 index 00000000000..16434b4920c --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/hands.dm @@ -0,0 +1,12 @@ +/datum/loadout_item/hands + category = LOADOUT_CATEGORY_HANDS + +//MISC +/datum/loadout_item/hands/cane + name = "Cane" + path = /obj/item/cane + +/datum/loadout_item/hands/briefcase + name = "Briefcase" + path = /obj/item/storage/briefcase + cost = 2 //Authentic leather diff --git a/modular_skyrat/modules/customization/modules/client/loadout/head.dm b/modular_skyrat/modules/customization/modules/client/loadout/head.dm new file mode 100644 index 00000000000..6996d506bdb --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/head.dm @@ -0,0 +1,152 @@ +/datum/loadout_item/head + category = LOADOUT_CATEGORY_HEAD + +//MISC +/datum/loadout_item/head/baseball + name = "Ballcap" + path = /obj/item/clothing/head/soft/mime + extra_info = LOADOUT_INFO_ONE_COLOR + +/datum/loadout_item/head/beanie + name = "Beanie" + path = /obj/item/clothing/head/beanie + extra_info = LOADOUT_INFO_ONE_COLOR + +/datum/loadout_item/head/beret + name = "Black beret" + path = /obj/item/clothing/head/beret/black + +/datum/loadout_item/head/flatcap + name = "Flat cap" + path = /obj/item/clothing/head/flatcap + +/datum/loadout_item/head/pirate + name = "Pirate hat" + path = /obj/item/clothing/head/pirate + +/datum/loadout_item/head/rice_hat + name = "Rice hat" + path = /obj/item/clothing/head/rice_hat + +/datum/loadout_item/head/ushanka + name = "Ushanka" + path = /obj/item/clothing/head/ushanka + +/datum/loadout_item/head/slime + name = "Slime hat" + path = /obj/item/clothing/head/collectable/slime + +/datum/loadout_item/head/fedora + name = "Fedora" + path = /obj/item/clothing/head/fedora + +/datum/loadout_item/head/that + name = "Top Hat" + path = /obj/item/clothing/head/that + +/datum/loadout_item/head/flakhelm + name = "Flak Helmet" + path = /obj/item/clothing/head/flakhelm + cost = 2 + +/datum/loadout_item/head/bunnyears + name = "Bunny Ears" + path = /obj/item/clothing/head/rabbitears + +/datum/loadout_item/head/mailmanhat + name = "Mailman's Hat" + path = /obj/item/clothing/head/mailman + +//Cowboy Stuff +/datum/loadout_item/head/cowboyhat + name = "Cowboy Hat, Brown" + path = /obj/item/clothing/head/cowboyhat + +/datum/loadout_item/head/cowboyhat/black + name = "Cowboy Hat, Black" + path = /obj/item/clothing/head/cowboyhat/black + +/datum/loadout_item/head/cowboyhat/white + name = "Cowboy Hat, White" + path = /obj/item/clothing/head/cowboyhat/white + +/datum/loadout_item/head/cowboyhat/pink + name = "Cowboy Hat, Pink" + path = /obj/item/clothing/head/cowboyhat/pink + +/* +//trek fancy Hats! +/datum/gear/trekcap + name = "Federation Officer's Cap (White)" + category = SLOT_HEAD + path = /obj/item/clothing/head/caphat/formal/fedcover + restricted_roles = list("Captain","Head of Personnel") + +/datum/gear/trekcapcap + name = "Federation Officer's Cap (Black)" + category = SLOT_HEAD + path = /obj/item/clothing/head/caphat/formal/fedcover/black + restricted_roles = list("Captain","Head of Personnel") + +/datum/gear/trekcapmedisci + name = "Federation Officer's Cap (Blue)" + category = SLOT_HEAD + path = /obj/item/clothing/head/caphat/formal/fedcover/medsci + restricted_desc = "Medical and Science" + restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Geneticist","Research Director","Scientist", "Roboticist") + +/datum/gear/trekcapeng + name = "Federation Officer's Cap (Yellow)" + category = SLOT_HEAD + path = /obj/item/clothing/head/caphat/formal/fedcover/eng + restricted_desc = "Engineering, Security, and Cargo" + restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") + +/datum/gear/trekcapsec + name = "Federation Officer's Cap (Red)" + category = SLOT_HEAD + path = /obj/item/clothing/head/caphat/formal/fedcover/sec + restricted_desc = "Engineering, Security, and Cargo" + restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") +*/ +/*Commenting out Until next Christmas or made automatic +/datum/gear/santahatr + name = "Red Santa Hat" + category = SLOT_HEAD + path = /obj/item/clothing/head/christmashat +/datum/gear/santahatg + name = "Green Santa Hat" + category = SLOT_HEAD + path = /obj/item/clothing/head/christmashatg +*/ + +//JOB +/datum/loadout_item/head/job + subcategory = LOADOUT_SUBCATEGORY_JOB + +/datum/loadout_item/head/job/cowboyhat/sec + name = "Cowboy Hat, Security" + path = /obj/item/clothing/head/cowboyhat/sec + restricted_desc = "Security" + restricted_roles = list("Warden","Detective","Security Officer","Head of Security") + +/datum/loadout_item/head/job/navybluehosberet + name = "Head of security's navyblue beret" + path = /obj/item/clothing/head/beret/sec/navyhos + restricted_roles = list("Head of Security") + +/datum/loadout_item/head/job/navyblueofficerberet + name = "Security officer's Navyblue beret" + path = /obj/item/clothing/head/beret/sec/navyofficer + restricted_roles = list("Security Officer") + +/datum/loadout_item/head/job/navybluewardenberet + name = "Warden's navyblue beret" + path = /obj/item/clothing/head/beret/sec/navywarden + restricted_roles = list("Warden") + +/datum/loadout_item/head/job/nursehat + name = "Nurse Hat" + path = /obj/item/clothing/head/nursehat + restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") + restricted_desc = "Medical" diff --git a/modular_skyrat/modules/customization/modules/client/loadout/mask.dm b/modular_skyrat/modules/customization/modules/client/loadout/mask.dm new file mode 100644 index 00000000000..a259e390b21 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/mask.dm @@ -0,0 +1,11 @@ +/datum/loadout_item/mask + category = LOADOUT_CATEGORY_MASK + +//MISC +/datum/loadout_item/mask/balaclava + name = "Balaclava" + path = /obj/item/clothing/mask/balaclava + +/datum/loadout_item/mask/moustache + name = "Fake moustache" + path = /obj/item/clothing/mask/fakemoustache diff --git a/modular_skyrat/modules/customization/modules/client/loadout/neck.dm b/modular_skyrat/modules/customization/modules/client/loadout/neck.dm new file mode 100644 index 00000000000..c746b70b133 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/neck.dm @@ -0,0 +1,92 @@ +/datum/loadout_item/neck + category = LOADOUT_CATEGORY_NECK + +//MISC +/datum/loadout_item/neck/headphones + name = "Headphones" + path = /obj/item/clothing/ears/headphones + +/datum/loadout_item/neck/choker + name = "Choker" + path = /obj/item/clothing/neck/human_petcollar/choker + +/datum/loadout_item/neck/collar + name = "Collar" + path = /obj/item/clothing/neck/human_petcollar + +/datum/loadout_item/neck/leathercollar + name = "Leather collar" + path = /obj/item/clothing/neck/human_petcollar/leather + +/datum/loadout_item/neck/stethoscope + name = "Stethoscope" + path = /obj/item/clothing/neck/stethoscope + restricted_roles = list("Medical Doctor", "Chief Medical Officer") + +//SCARVES +/datum/loadout_item/neck/scarf + subcategory = LOADOUT_SUBCATEGORY_NECK_SCARVES + +/datum/loadout_item/neck/scarf/scarf + name = "White scarf" + path = /obj/item/clothing/neck/scarf + +/datum/loadout_item/neck/scarf/blackscarf + name = "Black scarf" + path = /obj/item/clothing/neck/scarf/black + +/datum/loadout_item/neck/scarf/redscarf + name = "Red scarf" + path = /obj/item/clothing/neck/scarf/red + +/datum/loadout_item/neck/scarf/greenscarf + name = "Green scarf" + path = /obj/item/clothing/neck/scarf/green + +/datum/loadout_item/neck/scarf/darkbluescarf + name = "Dark blue scarf" + path = /obj/item/clothing/neck/scarf/darkblue + +/datum/loadout_item/neck/scarf/purplescarf + name = "Purple scarf" + path = /obj/item/clothing/neck/scarf/purple + +/datum/loadout_item/neck/scarf/yellowscarf + name = "Yellow scarf" + path = /obj/item/clothing/neck/scarf/yellow + +/datum/loadout_item/neck/scarf/orangescarf + name = "Orange scarf" + path = /obj/item/clothing/neck/scarf/orange + +/datum/loadout_item/neck/scarf/cyanscarf + name = "Cyan scarf" + path = /obj/item/clothing/neck/scarf/cyan + +/datum/loadout_item/neck/scarf/stripedredscarf + name = "Striped red scarf" + path = /obj/item/clothing/neck/stripedredscarf + +/datum/loadout_item/neck/scarf/stripedbluescarf + name = "Striped blue scarf" + path = /obj/item/clothing/neck/stripedbluescarf + +/datum/loadout_item/neck/scarf/stripedgreenscarf + name = "Striped green scarf" + path = /obj/item/clothing/neck/stripedgreenscarf + +//TIES +/datum/loadout_item/neck/tie + subcategory = LOADOUT_SUBCATEGORY_NECK_TIE + +/datum/loadout_item/neck/tie/bluetie + name = "Blue tie" + path = /obj/item/clothing/neck/tie/blue + +/datum/loadout_item/neck/tie/redtie + name = "Red tie" + path = /obj/item/clothing/neck/tie/red + +/datum/loadout_item/neck/tie/blacktie + name = "Black tie" + path = /obj/item/clothing/neck/tie/black diff --git a/modular_skyrat/modules/customization/modules/client/loadout/shoes.dm b/modular_skyrat/modules/customization/modules/client/loadout/shoes.dm new file mode 100644 index 00000000000..db1f81fea15 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/shoes.dm @@ -0,0 +1,74 @@ +/datum/loadout_item/shoes + category = LOADOUT_CATEGORY_SHOES + +//MISC +/datum/loadout_item/shoes/laceup + name = "Laceup shoes" + path = /obj/item/clothing/shoes/laceup + +/datum/loadout_item/shoes/workboots + name = "Work boots" + path = /obj/item/clothing/shoes/workboots + +/datum/loadout_item/shoes/jackboots + name = "Jackboots" + path = /obj/item/clothing/shoes/jackboots + +/datum/loadout_item/shoes/winterboots + name = "Winter boots" + path = /obj/item/clothing/shoes/winterboots + +/datum/loadout_item/shoes/sandals + name = "Sandals" + path = /obj/item/clothing/shoes/sandal + +/datum/loadout_item/shoes/blackshoes + name = "Black shoes" + path = /obj/item/clothing/shoes/sneakers/black + +/datum/loadout_item/shoes/brownshoes + name = "Brown shoes" + path = /obj/item/clothing/shoes/sneakers/brown + +/datum/loadout_item/shoes/whiteshoes + name = "White shoes" + path = /obj/item/clothing/shoes/sneakers/white + +/datum/loadout_item/shoes/gildedcuffs + name = "Gilded leg wraps" + path= /obj/item/clothing/shoes/wraps + +/datum/loadout_item/shoes/silvercuffs + name = "Silver leg wraps" + path= /obj/item/clothing/shoes/wraps/silver + +/datum/loadout_item/shoes/redcuffs + name = "Red leg wraps" + path= /obj/item/clothing/shoes/wraps/red + +/datum/loadout_item/shoes/bluecuffs + name = "Blue leg wraps" + path= /obj/item/clothing/shoes/wraps/blue + +/*/datum/loadout_item/shoes/christmasbootsr - it aint christmas! + name = "Red Christmas Boots" + category = SLOT_SHOES + path= /obj/item/clothing/shoes/winterboots/christmasbootsr + +/datum/loadout_item/shoes/christmasbootsg + name = "Green Christmas Boots" + category = SLOT_SHOES + path= /obj/item/clothing/shoes/winterboots/christmasbootsg + +/datum/loadout_item/shoes/santaboots + name = "Santa Boots" + category = SLOT_SHOES + path= /obj/item/clothing/shoes/winterboots/santaboots*/ + +/datum/loadout_item/shoes/cowboyboots + name = "Cowboy Boots, Brown" + path = /obj/item/clothing/shoes/cowboyboots + +/datum/loadout_item/shoes/cowboyboots/black + name = "Cowboy Boots, Black" + path = /obj/item/clothing/shoes/cowboyboots/black diff --git a/modular_skyrat/modules/customization/modules/client/loadout/suit.dm b/modular_skyrat/modules/customization/modules/client/loadout/suit.dm new file mode 100644 index 00000000000..57872648d5b --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/suit.dm @@ -0,0 +1,159 @@ +/datum/loadout_item/suit + category = LOADOUT_CATEGORY_SUIT + +//MISC +/datum/loadout_item/suit/poncho + name = "Poncho" + path = /obj/item/clothing/suit/poncho + +/datum/loadout_item/suit/ponchogreen + name = "Green poncho" + path = /obj/item/clothing/suit/poncho/green + +/datum/loadout_item/suit/ponchored + name = "Red poncho" + path = /obj/item/clothing/suit/poncho/red + +/datum/loadout_item/suit/redhood + name = "Red cloak" + path = /obj/item/clothing/suit/hooded/cloak/david + cost = 3 + +/datum/loadout_item/suit/ianshirt + name = "Ian Shirt" + path = /obj/item/clothing/suit/ianshirt + +//COATS +/datum/loadout_item/suit/coat + subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS + +/datum/loadout_item/suit/coat/normal + name = "Winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat + +/datum/loadout_item/suit/coat/aformal + name = "Assistant's formal winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/aformal + +/datum/loadout_item/suit/coat/runed + name = "Runed winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/narsie/fake + +/datum/loadout_item/suit/coat/brass + name = "Brass winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/ratvar/fake + +/*/datum/loadout_item/suit/coat/polycoat + name = "Polychromic winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/polychromic + cost = 4 //too many people with neon green coats is hard on the eyes +*/ + +//JACKETS +/datum/loadout_item/suit/jacket + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS + +/datum/loadout_item/suit/jacket/jacketbomber + name = "Bomber jacket" + path = /obj/item/clothing/suit/jacket + +/datum/loadout_item/suit/jacket/jacketleather + name = "Leather jacket" + path = /obj/item/clothing/suit/jacket/leather + +/datum/loadout_item/suit/jacket/overcoatleather + name = "Leather overcoat" + path = /obj/item/clothing/suit/jacket/leather/overcoat + +/datum/loadout_item/suit/jacket/jacketpuffer + name = "Puffer jacket" + path = /obj/item/clothing/suit/jacket/puffer + +/datum/loadout_item/suit/jacket/vestpuffer + name = "Puffer vest" + path = /obj/item/clothing/suit/jacket/puffer/vest + +/datum/loadout_item/suit/jacket/jacketlettermanbrown + name = "Brown letterman jacket" + path = /obj/item/clothing/suit/jacket/letterman + +/datum/loadout_item/suit/jacket/jacketlettermanred + name = "Red letterman jacket" + path = /obj/item/clothing/suit/jacket/letterman_red + +/datum/loadout_item/suit/jacket/jacketlettermanNT + name = "Nanotrasen letterman jacket" + path = /obj/item/clothing/suit/jacket/letterman_nanotrasen + +/datum/loadout_item/suit/jacket/militaryjacket + name = "Military Jacket" + path = /obj/item/clothing/suit/jacket/miljacket + +/datum/loadout_item/suit/jacket/flakjack + name = "Flak Jacket" + path = /obj/item/clothing/suit/flakjack + cost = 2 + +//JOB RELATED +/datum/loadout_item/suit/job + subcategory = LOADOUT_SUBCATEGORY_JOB + +/datum/loadout_item/suit/job/coat_med + name = "Medical winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/medical + restricted_roles = list("Chief Medical Officer", "Medical Doctor") // Reserve it to Medical Doctors and their boss, the Chief Medical Officer + +/datum/loadout_item/suit/job/coat_paramedic + name = "Paramedic winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/paramedic + restricted_roles = list("Chief Medical Officer", "Paramedic") // Reserve it to Paramedics and their boss, the Chief Medical Officer + +/datum/loadout_item/suit/job/coat_robotics + name = "Robotics winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/robotics + restricted_roles = list("Research Director", "Roboticist") + +/datum/loadout_item/suit/job/coat_sci + name = "Science winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/science + restricted_roles = list("Research Director", "Scientist", "Roboticist") // Reserve it to the Science Departement + +/datum/loadout_item/suit/job/coat_eng + name = "Engineering winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/engineering + restricted_roles = list("Chief Engineer", "Station Engineer") // Reserve it to Station Engineers and their boss, the Chief Engineer + +/datum/loadout_item/suit/job/coat_atmos + name = "Atmospherics winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos + restricted_roles = list("Chief Engineer", "Atmospheric Technician") // Reserve it to Atmos Techs and their boss, the Chief Engineer + +/datum/loadout_item/suit/job/coat_hydro + name = "Hydroponics winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/hydro + restricted_roles = list("Head of Personnel", "Botanist") // Reserve it to Botanists and their boss, the Head of Personnel + +/datum/loadout_item/suit/job/coat_cargo + name = "Cargo winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/cargo + restricted_roles = list("Quartermaster", "Cargo Technician") // Reserve it to Cargo Techs and their boss, the Quartermaster + +/datum/loadout_item/suit/job/coat_miner + name = "Mining winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/miner + restricted_roles = list("Quartermaster", "Shaft Miner") // Reserve it to Miners and their boss, the Quartermaster + +/datum/loadout_item/suit/job/navybluejackethos + name = "head of security's navyblue jacket" + path = /obj/item/clothing/suit/armor/hos/navyblue + restricted_roles = list("Head of Security") + +/datum/loadout_item/suit/job/navybluejacketofficer + name = "security officer's navyblue jacket" + path = /obj/item/clothing/suit/armor/navyblue + restricted_roles = list("Security Officer") + +/datum/loadout_item/suit/job/navybluejacketwarden + name = "warden navyblue jacket" + path = /obj/item/clothing/suit/armor/vest/warden/navyblue + restricted_roles = list("Warden") diff --git a/modular_skyrat/modules/customization/modules/client/loadout/uniform.dm b/modular_skyrat/modules/customization/modules/client/loadout/uniform.dm new file mode 100644 index 00000000000..69cd585881d --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/loadout/uniform.dm @@ -0,0 +1,488 @@ +/datum/loadout_item/uniform + category = LOADOUT_CATEGORY_UNIFORM + +//MISC +/datum/loadout_item/uniform/assistantformal + name = "Assistant's formal uniform" + path = /obj/item/clothing/under/misc/assistantformal + +/datum/loadout_item/uniform/maidcostume + name = "Maid costume" + path = /obj/item/clothing/under/costume/maid + +/datum/loadout_item/uniform/mailmanuniform + name = "Mailman's jumpsuit" + path = /obj/item/clothing/under/misc/mailman + +/datum/loadout_item/uniform/croptop + name = "Croptop" + path = /obj/item/clothing/under/croptop + +/datum/loadout_item/uniform/kilt + name = "Kilt" + path = /obj/item/clothing/under/costume/kilt + +/*/datum/loadout_item/uniform/polykilt + name = "Polychromic Kilt" + path = /obj/item/clothing/under/costume/kilt/polychromic + cost = 3*/ + +/datum/loadout_item/uniform/gear_harnesses + name = "Gear Harness" + path = /obj/item/clothing/under/misc/gear_harness + +/datum/loadout_item/uniform/pinkstripper + name = "Pink stripper outfit" + path = /obj/item/clothing/under/misc/stripper + cost = 3 + +/datum/loadout_item/uniform/greenstripper + name = "Green stripper outfit" + path = /obj/item/clothing/under/misc/stripper/green + cost = 3 + +/datum/loadout_item/uniform/qipao + name = "Qipao, Black" + path = /obj/item/clothing/under/costume/qipao + cost = 3 + +/datum/loadout_item/uniform/qipao/white + name = "Qipao, White" + path = /obj/item/clothing/under/costume/qipao/white + cost = 3 + +/datum/loadout_item/uniform/qipao/red + name = "Qipao, Red" + path = /obj/item/clothing/under/costume/qipao/red + cost = 3 + +/datum/loadout_item/uniform/cheongsam + name = "Cheongsam, Black" + path = /obj/item/clothing/under/costume/cheongsam + cost = 3 + +/datum/loadout_item/uniform/cheongsam/white + name = "Cheongsam, White" + path = /obj/item/clothing/under/costume/cheongsam/white + cost = 3 + +/datum/loadout_item/uniform/cheongsam/red + name = "Cheongsam, Red" + path = /obj/item/clothing/under/costume/cheongsam/red + cost = 3 + +//SUITS +/datum/loadout_item/uniform/suit + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SUITS + +/datum/loadout_item/uniform/suit/suitblack + name = "Black suit" + path = /obj/item/clothing/under/suit/black + +/datum/loadout_item/uniform/suit/suitgreen + name = "Green suit" + path = /obj/item/clothing/under/suit/green + +/datum/loadout_item/uniform/suit/suitred + name = "Red suit" + path = /obj/item/clothing/under/suit/red + +/datum/loadout_item/uniform/suit/suitcharcoal + name = "Charcoal suit" + path = /obj/item/clothing/under/suit/charcoal + +/datum/loadout_item/uniform/suit/suitnavy + name = "Navy suit" + path = /obj/item/clothing/under/suit/navy + +/datum/loadout_item/uniform/suit/suitburgundy + name = "Burgundy suit" + path = /obj/item/clothing/under/suit/burgundy + +/datum/loadout_item/uniform/suit/suittan + name = "Tan suit" + path = /obj/item/clothing/under/suit/tan + +/datum/loadout_item/uniform/suit/suitwhite + name = "White suit" + path = /obj/item/clothing/under/suit/white + +//SKIRTS +/datum/loadout_item/uniform/skirt + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS + +/datum/loadout_item/uniform/skirt/skirtblack + name = "Black skirt" + path = /obj/item/clothing/under/dress/skirt + +/datum/loadout_item/uniform/skirt/skirtblue + name = "Blue skirt" + path = /obj/item/clothing/under/dress/skirt/blue + +/datum/loadout_item/uniform/skirt/skirtred + name = "Red skirt" + path = /obj/item/clothing/under/dress/skirt/red + +/datum/loadout_item/uniform/skirt/skirtpurple + name = "Purple skirt" + path = /obj/item/clothing/under/dress/skirt/purple + +/datum/loadout_item/uniform/skirt/skirtplaid + name = "Plaid skirt" + path = /obj/item/clothing/under/dress/skirt/plaid + +/datum/loadout_item/uniform/skirt/sweptskirt + name = "Swept skirt" + path = /obj/item/clothing/under/dress/skirt/swept + +/datum/loadout_item/uniform/skirt/schoolgirlblue + name = "Blue Schoolgirl Uniform" + path = /obj/item/clothing/under/costume/schoolgirl + +/datum/loadout_item/uniform/skirt/schoolgirlred + name = "Red Schoolgirl Uniform" + path = /obj/item/clothing/under/costume/schoolgirl/red + +/datum/loadout_item/uniform/skirt/schoolgirlgreen + name = "Green Schoolgirl Uniform" + path = /obj/item/clothing/under/costume/schoolgirl/green + +/datum/loadout_item/uniform/skirt/schoolgirlorange + name = "Orange Schoolgirl Uniform" + path = /obj/item/clothing/under/costume/schoolgirl/orange + +/datum/loadout_item/uniform/skirt/denimskirt + name = "Denim Skirt" + path = /obj/item/clothing/under/pants/denimskirt + +//DRESSES +/datum/loadout_item/uniform/dress + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES + +/datum/loadout_item/uniform/dress/stripeddress + name = "Striped Dress" + path = /obj/item/clothing/under/dress/striped + +/datum/loadout_item/uniform/dress/sundresswhite + name = "White Sundress" + path = /obj/item/clothing/under/dress/sundress/white + +/datum/loadout_item/uniform/dress/sundress + name = "Sundress" + path = /obj/item/clothing/under/dress/sundress + +/datum/loadout_item/uniform/dress/greendress + name = "Green Dress" + path = /obj/item/clothing/under/dress/green + +/datum/loadout_item/uniform/dress/pinkdress + name = "Pink Dress" + path = /obj/item/clothing/under/dress/pink + +/datum/loadout_item/uniform/dress/flowerdress + name = "Flower Dress" + path = /obj/item/clothing/under/dress/flower + + +//PANTS +/datum/loadout_item/uniform/pants + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_PANTS + +/datum/loadout_item/uniform/pants/yoga + name = "Yoga Pants" + path = /obj/item/clothing/under/pants/yoga + +/datum/loadout_item/uniform/pants/bjeans + name = "Black Jeans" + path = /obj/item/clothing/under/pants/blackjeans + +/datum/loadout_item/uniform/pants/cjeans + name = "Classic Jeans" + path = /obj/item/clothing/under/pants/classicjeans + +/datum/loadout_item/uniform/pants/khaki + name = "Khaki Pants" + path = /obj/item/clothing/under/pants/khaki + +/datum/loadout_item/uniform/pants/wpants + name = "White Pants" + path = /obj/item/clothing/under/pants/white + +/datum/loadout_item/uniform/pants/rpants + name = "Red Pants" + path = /obj/item/clothing/under/pants/red + +/datum/loadout_item/uniform/pants/tpants + name = "Tan Pants" + path = /obj/item/clothing/under/pants/tan + +/datum/loadout_item/uniform/pants/trpants + name = "Track Pants" + path = /obj/item/clothing/under/pants/track + +/datum/loadout_item/uniform/pants/rippedjeans + name = "Ripped Jeans" + path = /obj/item/clothing/under/pants/jeanripped + +//SHORTS +/datum/loadout_item/uniform/shorts + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SHORTS + +/*/datum/loadout_item/uniform/shorts/polyshorts + name = "Polychromic Shorts" + path = /obj/item/clothing/under/misc/polyshorts + cost = 3*/ + +/*/datum/loadout_item/uniform/shorts/polyshortpants + name = "Polychromic Athletic Shorts" + path = /obj/item/clothing/under/shorts/polychromic*/ + cost = 2 + +/datum/loadout_item/uniform/shorts/jeanshort + name = "Jean Shorts" + path = /obj/item/clothing/under/pants/jeanshort + +/datum/loadout_item/uniform/shorts/camoshorts + name = "Camo Pants" + path = /obj/item/clothing/under/pants/camo + +/datum/loadout_item/uniform/shorts/athleticshorts + name = "Athletic Shorts" + path = /obj/item/clothing/under/shorts/red + + +//SWEATERS +/datum/loadout_item/uniform/sweater + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS + +/datum/loadout_item/uniform/sweater/turtleneck + name = "Tactitool Turtleneck" + path = /obj/item/clothing/under/syndicate/tacticool + +/datum/loadout_item/uniform/sweater/creamsweater + name = "Cream Commando Sweater" + path = /obj/item/clothing/under/sweater + +/datum/loadout_item/uniform/sweater/blacksweater + name = "Black Commando Sweater" + path = /obj/item/clothing/under/sweater/black + +/datum/loadout_item/uniform/sweater/purpsweater + name = "Purple Commando Sweater" + path = /obj/item/clothing/under/sweater/purple + +/datum/loadout_item/uniform/sweater/greensweater + name = "Green Commando Sweater" + path = /obj/item/clothing/under/sweater/green + +/datum/loadout_item/uniform/sweater/redsweater + name = "Red Commando Sweater" + path = /obj/item/clothing/under/sweater/red + +/datum/loadout_item/uniform/sweater/bluesweater + name = "Navy Commando Sweater" + path = /obj/item/clothing/under/sweater/blue + +/datum/loadout_item/uniform/sweater/keyholesweater + name = "Keyhole Sweater" + path = /obj/item/clothing/under/sweater/keyhole + +//SWEATERS +/datum/loadout_item/uniform/job + subcategory = LOADOUT_SUBCATEGORY_JOB + +/datum/loadout_item/uniform/job/navyblueuniformhos + name = "Head of Security navyblue uniform" + path = /obj/item/clothing/under/rank/security/head_of_security/formal + restricted_roles = list("Head of Security") + +/datum/loadout_item/uniform/job/navyblueuniformofficer + name = "Security officer navyblue uniform" + path = /obj/item/clothing/under/rank/security/officer/formal + restricted_roles = list("Security Officer") + +/datum/loadout_item/uniform/job/navyblueuniformwarden + name = "Warden navyblue uniform" + path = /obj/item/clothing/under/rank/security/warden/formal + restricted_roles = list("Warden") + +/datum/loadout_item/uniform/job/secskirt + name = "Security skirt" + path = /obj/item/clothing/under/rank/security/officer/skirt + restricted_roles = list("Security Officer", "Warden", "Head of Security") + +/datum/loadout_item/uniform/job/hosskirt + name = "Head of security's skirt" + path = /obj/item/clothing/under/rank/security/head_of_security/skirt + restricted_roles = list("Head of Security") + +/datum/loadout_item/uniform/job/bluescrubs + name = "Blue Scrubs" + path = /obj/item/clothing/under/rank/medical/doctor/blue + restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") + restricted_desc = "Medical" + +/datum/loadout_item/uniform/job/greenscrubs + name = "Green Scrubs" + path = /obj/item/clothing/under/rank/medical/doctor/green + restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") + restricted_desc = "Medical" + +/datum/loadout_item/uniform/job/purplescrubs + name = "Purple Scrubs" + path = /obj/item/clothing/under/rank/medical/doctor/purple + restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") + restricted_desc = "Medical" + +/datum/loadout_item/uniform/job/nursesuit + name = "Nurse Suit" + path = /obj/item/clothing/under/rank/medical/doctor/nurse + restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") + restricted_desc = "Medical" + +/*// Trekie things +//TOS +/datum/loadout_item/trekcmdtos + name = "TOS uniform, cmd" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/command + restricted_desc = "Heads of Staff" + restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") + +/datum/loadout_item/trekmedscitos + name = "TOS uniform, med/sci" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/medsci + restricted_desc = "Medical and Science" + restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Geneticist","Research Director","Scientist", "Roboticist") + +/datum/loadout_item/trekengtos + name = "TOS uniform, ops/sec" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/engsec + restricted_desc = "Engineering, Security, and Cargo" + restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") + + //handled by modular skyrat code as reskins +//TNG +/datum/loadout_item/trekcmdtng + name = "TNG uniform, cmd" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/command/next + restricted_desc = "Heads of Staff" + restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") +/datum/loadout_item/trekmedscitng + name = "TNG uniform, med/sci" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/medsci/next + restricted_desc = "Medical and Science" + restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Geneticist","Research Director","Scientist", "Roboticist") +/datum/loadout_item/trekengtng + name = "TNG uniform, ops/sec" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/engsec/next + restricted_desc = "Engineering, Security, and Cargo" + restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") +//VOY +/datum/loadout_item/trekcmdvoy + name = "VOY uniform, cmd" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/command/voy + restricted_desc = "Heads of Staff" + restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") +/datum/loadout_item/trekmedscivoy + name = "VOY uniform, med/sci" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/medsci/voy + restricted_desc = "Medical and Science" + restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Geneticist","Research Director","Scientist", "Roboticist") +/datum/loadout_item/trekengvoy + name = "VOY uniform, ops/sec" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/engsec/voy + restricted_desc = "Engineering, Security, and Cargo" + restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") +//DS9 +/datum/loadout_item/trekcmdds9 + name = "DS9 uniform, cmd" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/command/ds9 + restricted_desc = "Heads of Staff" + restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") +/datum/loadout_item/trekmedscids9 + name = "DS9 uniform, med/sci" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/medsci/ds9 + restricted_desc = "Medical and Science" + restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Geneticist","Research Director","Scientist", "Roboticist") +/datum/loadout_item/trekengds9 + name = "DS9 uniform, ops/sec" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/engsec/ds9 + restricted_desc = "Engineering, Security, and Cargo" + restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") +//ENT +/datum/loadout_item/trekcmdent + name = "ENT uniform, cmd" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/command/ent + restricted_desc = "Heads of Staff" + restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") +/datum/loadout_item/trekmedscient + name = "ENT uniform, med/sci" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/medsci/ent + restricted_desc = "Medical and Science" + restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Geneticist","Research Director","Scientist", "Roboticist") +/datum/loadout_item/trekengent + name = "ENT uniform, ops/sec" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/engsec/ent + restricted_desc = "Engineering, Security, and Cargo" + restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") +*/ + +//TheMotionPicture +/*/datum/loadout_item/trekfedutil + name = "TMP uniform" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/fedutil + restricted_desc = "All, barring Service and Civilian" + restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster", + "Medical Doctor","Chemist","Virologist","Geneticist","Scientist", "Roboticist", + "Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer", + "Cargo Technician", "Shaft Miner") + +/datum/loadout_item/trekfedtrainee + name = "TMP uniform, trainee" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/fedutil/trainee + restricted_roles = list("Assistant", "Janitor", "Cargo Technician") + +/datum/loadout_item/trekfedservice + name = "TMP uniform, service" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/trek/fedutil/service + restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer" + restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor")*/ + + +//Christmas +/*Commenting out Until next Christmas or made automatic +/datum/loadout_item/christmasmaler + name = "Red Masculine Christmas Suit" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/costume/christmas +/datum/loadout_item/christmasmaleg + name = "Green Masculine Christmas Suit" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/costume/christmas/green +/datum/loadout_item/christmasfemaler + name = "Red Feminine Christmas Suit" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/costume/christmas/croptop +/datum/loadout_item/christmasfemaleg + name = "Green Feminine Christmas Suit" + category = SLOT_W_UNIFORM + path = /obj/item/clothing/under/costume/christmas/croptop/green*/ + diff --git a/modular_skyrat/modules/customization/modules/client/preferences.dm b/modular_skyrat/modules/customization/modules/client/preferences.dm new file mode 100644 index 00000000000..480443eeff9 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/preferences.dm @@ -0,0 +1,2546 @@ +/datum/preferences + var/client/parent + //doohickeys for savefiles + var/path + var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used + var/max_save_slots = 3 + + //non-preference stuff + var/muted = 0 + var/last_ip + var/last_id + + //game-preferences + var/lastchangelog = "" //Saved changlog filesize to detect if there was a change + var/ooccolor = "#c43b23" + var/asaycolor = "#ff4500" //This won't change the color for current admins, only incoming ones. + var/enable_tips = TRUE + var/tip_delay = 500 //tip delay in milliseconds + + //Antag preferences + var/list/be_special = list() //Special role selection + var/tmp/old_be_special = 0 //Bitflag version of be_special, used to update old savefiles and nothing more + //If it's 0, that's good, if it's anything but 0, the owner of this prefs file's antag choices were, + //autocorrected this round, not that you'd need to check that. + + var/UI_style = null + var/buttons_locked = FALSE + var/hotkeys = TRUE + + ///Runechat preference. If true, certain messages will be displayed on the map, not ust on the chat area. Boolean. + var/chat_on_map = TRUE + ///Limit preference on the size of the message. Requires chat_on_map to have effect. + var/max_chat_length = CHAT_MESSAGE_MAX_LENGTH + ///Whether non-mob messages will be displayed, such as machine vendor announcements. Requires chat_on_map to have effect. Boolean. + var/see_chat_non_mob = TRUE + ///Whether emotes will be displayed on runechat. Requires chat_on_map to have effect. Boolean. + var/see_rc_emotes = TRUE + + // Custom Keybindings + var/list/key_bindings = list() + + var/tgui_fancy = TRUE + var/tgui_lock = FALSE + var/windowflashing = TRUE + var/toggles = TOGGLES_DEFAULT + var/db_flags + var/chat_toggles = TOGGLES_DEFAULT_CHAT + var/ghost_form = "ghost" + var/ghost_orbit = GHOST_ORBIT_CIRCLE + var/ghost_accs = GHOST_ACCS_DEFAULT_OPTION + var/ghost_others = GHOST_OTHERS_DEFAULT_OPTION + var/ghost_hud = 1 + var/inquisitive_ghost = 1 + var/allow_midround_antag = 1 + var/preferred_map = null + var/pda_style = MONO + var/pda_color = "#808000" + + var/uses_glasses_colour = 0 + + //character preferences + var/slot_randomized //keeps track of round-to-round randomization of the character slot, prevents overwriting + var/real_name //our character's name + var/gender = MALE //gender of character (well duh) + var/age = 30 //age of character + var/underwear = "Nude" //underwear type + var/underwear_color = "FFF" //underwear color + var/undershirt = "Nude" //undershirt type + var/undershirt_color = "FFF" //underwear color + var/socks = "Nude" //socks type + var/socks_color = "FFF" //underwear color + var/backpack = DBACKPACK //backpack type + var/jumpsuit_style = PREF_SUIT //suit/skirt + var/hairstyle = "Bald" //Hair type + var/hair_color = "000" //Hair color + var/facial_hairstyle = "Shaved" //Face hair type + var/facial_hair_color = "000" //Facial hair color + var/skin_tone = "caucasian1" //Skin color + var/eye_color = "000" //Eye color + var/datum/species/pref_species = new /datum/species/human() //Mutant race + //Has to include all information that extra organs from mutant bodyparts would need. (so far only genitals now) + var/list/features = MANDATORY_FEATURE_LIST + var/list/randomise = list(RANDOM_UNDERWEAR = FALSE, RANDOM_UNDERWEAR_COLOR = TRUE, RANDOM_UNDERSHIRT = FALSE, RANDOM_SOCKS = FALSE, RANDOM_BACKPACK = TRUE, RANDOM_JUMPSUIT_STYLE = TRUE, RANDOM_HAIRSTYLE = TRUE, RANDOM_HAIR_COLOR = TRUE, RANDOM_FACIAL_HAIRSTYLE = TRUE, RANDOM_FACIAL_HAIR_COLOR = TRUE, RANDOM_SKIN_TONE = TRUE, RANDOM_EYE_COLOR = TRUE) + var/phobia = "spiders" + + var/list/custom_names = list() + var/preferred_ai_core_display = "Blue" + var/prefered_security_department = SEC_DEPT_RANDOM + + //Quirk list + var/list/all_quirks = list() + + //Job preferences 2.0 - indexed by job title , no key or value implies never + var/list/job_preferences = list() + + // Want randomjob if preferences already filled - Donkie + var/joblessrole = BERANDOMJOB //defaults to 1 for fewer assistants + + // 0 = character settings, 1 = game preferences + var/current_tab = 0 + + var/unlock_content = 0 + + var/list/ignoring = list() + + var/clientfps = 0 + + var/parallax + + var/ambientocclusion = TRUE + ///Should we automatically fit the viewport? + var/auto_fit_viewport = FALSE + ///Should we be in the widescreen mode set by the config? + var/widescreenpref = TRUE + ///What size should pixels be displayed as? 0 is strech to fit + var/pixel_size = 0 + ///What scaling method should we use? Distort means nearest neighbor + var/scaling_method = SCALING_METHOD_DISTORT + var/uplink_spawn_loc = UPLINK_PDA + ///The playtime_reward_cloak variable can be set to TRUE from the prefs menu only once the user has gained over 5K playtime hours. If true, it allows the user to get a cool looking roundstart cloak. + var/playtime_reward_cloak = FALSE + + var/list/exp = list() + var/list/menuoptions + + var/action_buttons_screen_locs = list() + + ///This var stores the amount of points the owner will get for making it out alive. + var/hardcore_survival_score = 0 + + ///Someone thought we were nice! We get a little heart in OOC until we join the server past the below time (we can keep it until the end of the round otherwise) + var/hearted + ///If we have a hearted commendations, we honor it every time the player loads preferences until this time has been passed + var/hearted_until + /// Agendered spessmen can choose whether to have a male or female bodytype + var/body_type + + /// If we have persistent scars enabled + var/persistent_scars = TRUE + /// We have 5 slots for persistent scars, if enabled we pick a random one to load (empty by default) and scars at the end of the shift if we survived as our original person + var/list/scars_list = list("1" = "", "2" = "", "3" = "", "4" = "", "5" = "") + /// Which of the 5 persistent scar slots we randomly roll to load for this round, if enabled. Actually rolled in [/datum/preferences/proc/load_character(slot)] + var/scars_index = 1 + /// Will the person see accessories not meant for their species to choose from + var/mismatched_customization = FALSE + var/allow_advanced_colors = FALSE + var/list/list/mutant_bodyparts = list() + var/list/list/body_markings = list() + + var/character_settings_tab = 0 + + ///How many loadout points we've got remaining + var/loadout_points = LOADOUT_POINTS_MAX + ///Loadout items, this is an associative list stored as [name] = "info". Info can be either colors or styles for the loadout items + var/loadout = list() + + var/loadout_category = "" + var/loadout_subcategory = "" + + var/preview_pref = PREVIEW_PREF_JOB + + var/ooc_prefs = "" + var/erp_pref = "Ask" + var/noncon_pref = "Ask" + var/vore_pref = "Ask" + + //BACKGROUND STUFF + var/general_record = "" + var/security_record = "" + var/medical_record = "" + + var/background_info = "" + var/exploitable_info = "" + +/datum/preferences/New(client/C) + parent = C + + for(var/custom_name_id in GLOB.preferences_custom_names) + custom_names[custom_name_id] = get_default_name(custom_name_id) + + UI_style = GLOB.available_ui_styles[1] + if(istype(C)) + if(!IsGuestKey(C.key)) + load_path(C.ckey) + unlock_content = C.IsByondMember() + if(unlock_content) + max_save_slots = 8 + var/loaded_preferences_successfully = load_preferences() + if(loaded_preferences_successfully) + if(load_character()) + return + //we couldn't load character data so just randomize the character appearance + name + random_character() //let's create a random character then - rather than a fat, bald and naked man. + key_bindings = deepCopyList(GLOB.hotkey_keybinding_list_by_key) // give them default keybinds and update their movement keys + C?.update_movement_keys(src) + real_name = pref_species.random_name(gender,1) + if(!loaded_preferences_successfully) + save_preferences() + save_character() //let's save this new random character so it doesn't keep generating new ones. + menuoptions = list() + return + +#define APPEARANCE_CATEGORY_COLUMN "" +#define MAX_MUTANT_ROWS 4 + +/datum/preferences/proc/ShowChoices(mob/user) + if(!user || !user.client) + return + if(slot_randomized) + load_character(default_slot) // Reloads the character slot. Prevents random features from overwriting the slot if saved. + slot_randomized = FALSE + update_preview_icon() + var/list/dat = list("
") + + dat += "Character Settings" + dat += "Game Preferences" + dat += "OOC Preferences" + dat += "Custom Keybindings" + + if(!path) + dat += "
Please create an account to save your preferences
" + + dat += "
" + + dat += "
" + + switch(current_tab) + if (0) // Character Settings# + if(path) + var/savefile/S = new /savefile(path) + if(S) + dat += "
" + var/name + var/unspaced_slots = 0 + for(var/i=1, i<=max_save_slots, i++) + unspaced_slots++ + if(unspaced_slots > 4) + dat += "
" + unspaced_slots = 0 + S.cd = "/character[i]" + S["real_name"] >> name + if(!name) + name = "Character[i]" + dat += "[name] " + dat += "
" + + dat += "
" + + dat += "
" + dat += "General" + dat += "Appearance" + dat += "Markings" + dat += "Background" + dat += "Loadout" //If you change the index of this tab, change all the logic regarding tab + dat += "
" + + dat += "
" + dat += "
" + dat += "" + dat += "" + dat += "" + if(character_settings_tab == 4) //if loadout + dat += "" + else + dat += "" + + dat += "" + + dat += "" + dat += "
" + dat += "Preview:" + dat += "[PREVIEW_PREF_JOB]" + dat += "[PREVIEW_PREF_LOADOUT]" + dat += "[PREVIEW_PREF_NAKED]" + dat += "" + dat += "Remaining loadout points: [loadout_points]" + dat += "" + dat += "Mismatched parts: [(mismatched_customization) ? "Enabled" : "Disabled"]" + dat += "" + dat += " Advanced colors: [(allow_advanced_colors) ? "Enabled" : "Disabled"]" + if(allow_advanced_colors) + dat += "Reset colors
" + dat += "
" + dat += "
" + dat += "
" + switch(character_settings_tab) + if(0) //General + dat += "

Occupation Choices

" + dat += "Set Occupation Preferences
" + if(CONFIG_GET(flag/roundstart_traits)) + dat += "

Quirk Setup

" + dat += "Configure Quirks
" + dat += "
Current Quirks: [all_quirks.len ? all_quirks.Join(", ") : "None"]
" + dat += "

Identity

" + dat += "" + + dat += "
" + if(is_banned_from(user.ckey, "Appearance")) + dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.
" + dat += "Random Name " + //dat += "Always Random Name: [(randomise[RANDOM_NAME]) ? "Yes" : "No"]" + //dat += "When Antagonist: [(randomise[RANDOM_NAME_ANTAG]) ? "Yes" : "No"]" + /*if(user.client.get_exp_living(TRUE) >= PLAYTIME_HARDCORE_RANDOM) + dat += "Hardcore Random: [(randomise[RANDOM_HARDCORE]) ? "Yes" : "No"]"*/ + dat += "
Name: " + dat += "[real_name]
" + + if(!(AGENDER in pref_species.species_traits)) + var/dispGender + if(gender == MALE) + dispGender = "Male" + else if(gender == FEMALE) + dispGender = "Female" + else + dispGender = "Other" + dat += "Gender: [dispGender]" + if(gender == PLURAL || gender == NEUTER) + dat += "
Body Type: [body_type == MALE ? "Male" : "Female"]" + + /*if(randomise[RANDOM_BODY] || randomise[RANDOM_BODY_ANTAG]) //doesn't work unless random body + dat += "Always Random Gender: [(randomise[RANDOM_GENDER]) ? "Yes" : "No"]" + dat += "When Antagonist: [(randomise[RANDOM_GENDER_ANTAG]) ? "Yes" : "No"]"*/ + + dat += "
Age: [age]" + /*if(randomise[RANDOM_BODY] || randomise[RANDOM_BODY_ANTAG]) //doesn't work unless random body + dat += "Always Random Age: [(randomise[RANDOM_AGE]) ? "Yes" : "No"]" + dat += "When Antagonist: [(randomise[RANDOM_AGE_ANTAG]) ? "Yes" : "No"]"*/ + + dat += "

Special Names:
" + var/old_group + for(var/custom_name_id in GLOB.preferences_custom_names) + var/namedata = GLOB.preferences_custom_names[custom_name_id] + if(!old_group) + old_group = namedata["group"] + else if(old_group != namedata["group"]) + old_group = namedata["group"] + dat += "
" + dat += "[namedata["pref_name"]]: [custom_names[custom_name_id]] " + dat += "

" + + dat += "Custom Job Preferences:
" + dat += "Preferred AI Core Display: [preferred_ai_core_display]
" + dat += "Preferred Security Department: [prefered_security_department]
" + + //Adds a thing to select which phobia because I can't be assed to put that in the quirks window + if("Phobia" in all_quirks) + dat += "

Phobia

" + + dat += "[phobia]
" + + if(1) //Appearance + dat += "

Body

" + dat += "Random Body " + //dat += "Always Random Body: [(randomise[RANDOM_BODY]) ? "Yes" : "No"]" + //dat += "When Antagonist: [(randomise[RANDOM_BODY_ANTAG]) ? "Yes" : "No"]
" + + dat += "" + else if(use_skintones) + dat += "" + + if(HAIR in pref_species.species_traits) + + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Hairstyle

" + + dat += "[hairstyle]" + dat += "<>" + //dat += "[(randomise[RANDOM_HAIRSTYLE]) ? "Lock" : "Unlock"]" + + dat += "
   Change" + //dat += "[(randomise[RANDOM_HAIR_COLOR]) ? "Lock" : "Unlock"]" + + dat += "

Facial Hairstyle

" + + dat += "[facial_hairstyle]" + dat += "<>" + //dat += "[(randomise[RANDOM_FACIAL_HAIRSTYLE]) ? "Lock" : "Unlock"]" + + dat += "
   Change" + //dat += "[(randomise[RANDOM_FACIAL_HAIR_COLOR]) ? "Lock" : "Unlock"]" + dat += "
" + + //Mutant stuff + var/mutant_category = 0 + + var/list/generic_cache = GLOB.generic_accessories + for(var/key in mutant_bodyparts) + if(!generic_cache[key]) //This means that we have a mutant bodypart that shouldnt be bundled here (genitals) + continue + if(!mutant_category) + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

[generic_cache[key]]

" + + dat += print_bodypart_change_line(key) + + dat += "
" + + mutant_category++ + if(mutant_category >= MAX_MUTANT_ROWS) + dat += "" + mutant_category = 0 + + if(mutant_category) + dat += "" + mutant_category = 0 + dat += "
" + dat += "Species:
[pref_species.name]
" + dat += "

Flavor Text

" + dat += "Set Examine Text
" + if(length(features["flavor_text"]) <= 40) + if(!length(features["flavor_text"])) + dat += "\[...\]" + else + dat += "[html_encode(features["flavor_text"])]" + else + dat += "[copytext(html_encode(features["flavor_text"]), 1, 40)]..." + + dat += "

OOC Preferences

" + dat += "ERP:[erp_pref] " + dat += "Non-Con:[noncon_pref] " + dat += "Vore:[vore_pref]
" + dat += "Set OOC prefs
" + if(length(ooc_prefs) <= 40) + if(!length(ooc_prefs)) + dat += "\[...\]" + else + dat += "[html_encode(ooc_prefs)]" + else + dat += "[copytext(html_encode(ooc_prefs), 1, 40)]..." + dat += "
" + + //dat += "Random Species " + //dat += "Always Random Species: [(randomise[RANDOM_SPECIES]) ? "Yes" : "No"]
" + + var/use_skintones = pref_species.use_skintones + if(use_skintones) + + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Skin Tone

" + + dat += "[skin_tone]" + //dat += "[(randomise[RANDOM_SKIN_TONE]) ? "Lock" : "Unlock"]" + dat += "
" + + + if(!use_skintones) + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Primary Color

" + dat += "    Change
" + + dat += "

Secondary Color

" + dat += "    Change
" + + dat += "

Tertiary Color

" + dat += "    Change
" + + if(istype(pref_species, /datum/species/ethereal)) //not the best thing to do tbf but I dont know whats better. + + if(!use_skintones) + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Ethereal Color

" + + dat += "    Change
" + + + if((EYECOLOR in pref_species.species_traits) && !(NOEYESPRITES in pref_species.species_traits)) + + /*if(!use_skintones) + dat += APPEARANCE_CATEGORY_COLUMN*/ + + dat += "

Eye Color

" + dat += "    Change" + //dat += "[(randomise[RANDOM_EYE_COLOR]) ? "Lock" : "Unlock"]" + + dat += "
" + + dat += "" + if (user.client.get_exp_living(TRUE) >= PLAYTIME_VETERAN) + dat += "
Don The Ultimate Gamer Cloak?:
[(playtime_reward_cloak) ? "Enabled" : "Disabled"]
" + + + if(pref_species.can_have_genitals) + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Penis

" + var/penis_name = mutant_bodyparts["penis"][MUTANT_INDEX_NAME] + dat += print_bodypart_change_line("penis") + if(penis_name != "None") + dat += "
Length: [features["penis_size"]] inches." + dat += "
Girth: [features["penis_girth"]] inches circumference" + + dat += "

Testicles

" + var/balls_name = mutant_bodyparts["testicles"][MUTANT_INDEX_NAME] + dat += print_bodypart_change_line("testicles") + if(balls_name != "None") + var/named_size = balls_size_to_description(features["balls_size"]) + dat += "
Size: [named_size]" + + if(mutant_bodyparts["taur"]) + var/datum/sprite_accessory/taur/TSP = GLOB.sprite_accessories["taur"][mutant_bodyparts["taur"][MUTANT_INDEX_NAME]] + if(TSP.factual && !(TSP.taur_mode & STYLE_TAUR_SNAKE)) + var/text_string = (features["penis_taur_mode"]) ? "Yes" : "No" + dat += "
Taur Mode: [text_string]" + dat += "" + dat += "" + + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Vagina

" + dat += print_bodypart_change_line("vagina") + dat += "

Womb

" + dat += print_bodypart_change_line("womb") + dat += "" + + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Breasts

" + var/breasts_name = mutant_bodyparts["breasts"][MUTANT_INDEX_NAME] + dat += print_bodypart_change_line("breasts") + if(breasts_name != "None") + var/named_size = breasts_size_to_cup(features["breasts_size"]) + var/named_lactation = (features["breasts_lactation"]) ? "Yes" : "No" + dat += "
Size: [named_size]" + dat += "
Can Lactate: [named_lactation]" + dat += "" + + dat += "
" + + dat += "
Underwear:
[underwear]" + //dat += "[(randomise[RANDOM_UNDERWEAR]) ? "Lock" : "Unlock"]" + + dat += "    Change" + //dat += "[(randomise[RANDOM_UNDERWEAR_COLOR]) ? "Lock" : "Unlock"]" + + dat += "
Undershirt:
[undershirt]" + //dat += "[(randomise[RANDOM_UNDERSHIRT]) ? "Lock" : "Unlock"]" + dat += "    Change" + + dat += "
Socks:
[socks]" + //dat += "[(randomise[RANDOM_SOCKS]) ? "Lock" : "Unlock"]" + dat += "    Change" + + dat += "
Jumpsuit Style:
[jumpsuit_style]" + //dat += "[(randomise[RANDOM_JUMPSUIT_STYLE]) ? "Lock" : "Unlock"]" + + dat += "
Backpack:
[backpack]" + //dat += "[(randomise[RANDOM_BACKPACK]) ? "Lock" : "Unlock"]" + + if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) + dat += "
Temporal Scarring:
[(persistent_scars) ? "Enabled" : "Disabled"]" + dat += "Clear scar slots" + + dat += "
Uplink Spawn Location:
[uplink_spawn_loc]
" + if(2) //Markings + dat += "Use a preset: Choose" + dat += "" + dat += " Primary:   Change" + dat += " Secondary:   Change" + dat += " Tertiary:   Change" + dat += "
" + dat += "" + dat += "
" + var/iterated_markings = 0 + for(var/zone in GLOB.marking_zones) + var/named_zone = " " + switch(zone) + if(BODY_ZONE_R_ARM) + named_zone = "Right Arm" + if(BODY_ZONE_L_ARM) + named_zone = "Left Arm" + if(BODY_ZONE_HEAD) + named_zone = "Head" + if(BODY_ZONE_CHEST) + named_zone = "Chest" + if(BODY_ZONE_R_LEG) + named_zone = "Right Leg" + if(BODY_ZONE_L_LEG) + named_zone = "Left Leg" + if(BODY_ZONE_PRECISE_R_HAND) + named_zone = "Right Hand" + if(BODY_ZONE_PRECISE_L_HAND) + named_zone = "Left Hand" + dat += "

[named_zone]

" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + if(body_markings[zone]) + for(var/key in body_markings[zone]) + var/datum/body_marking/BD = GLOB.body_markings[key] + var/can_move_up = " " + var/can_move_down = " " + var/color_line = " " + var/current_index = LAZYFIND(body_markings[zone], key) + if(BD.always_color_customizable || allow_advanced_colors) + var/color = body_markings[zone][key] + color_line = "R" + color_line += "   Set" + if(current_index < length(body_markings[zone])) + can_move_down = "Down" + if(current_index > 1) + can_move_up = "Up" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + if(!(body_markings[zone]) || body_markings[zone].len < MAXIMUM_MARKINGS_PER_LIMB) + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + dat += "
[can_move_up][can_move_down][key][color_line]Remove
Add
" + + iterated_markings += 1 + if(iterated_markings >= 4) + dat += "
" + iterated_markings = 0 + + dat += "
" + if(3) //Background + dat += "" + dat += "" + + + dat += "" + dat += "" + dat += "
" + dat += "

Records

" + dat += "

General

" + dat += "Set general record
" + if(length(general_record) <= 40) + if(!length(general_record)) + dat += "\[...\]" + else + dat += "[html_encode(general_record)]" + else + dat += "[copytext(html_encode(general_record), 1, 40)]..." + dat += "
" + + + dat += "

Medical

" + dat += "Set medical record
" + if(length(medical_record) <= 40) + if(!length(medical_record)) + dat += "\[...\]" + else + dat += "[html_encode(medical_record)]" + else + dat += "[copytext(html_encode(medical_record), 1, 40)]..." + dat += "
" + + + dat += "

Security

" + dat += "Set security record
" + if(length(security_record) <= 40) + if(!length(security_record)) + dat += "\[...\]" + else + dat += "[html_encode(security_record)]" + else + dat += "[copytext(html_encode(security_record), 1, 40)]..." + dat += "
" + dat += "
" + dat += "

Information

" + dat += "

Background

" + dat += "Set background information
" + if(length(background_info) <= 40) + if(!length(background_info)) + dat += "\[...\]" + else + dat += "[html_encode(background_info)]" + else + dat += "[copytext(html_encode(background_info), 1, 40)]..." + dat += "

Exploitable

" + dat += "Set exploitable information
" + if(length(exploitable_info) <= 40) + if(!length(exploitable_info)) + dat += "\[...\]" + else + dat += "[html_encode(exploitable_info)]" + else + dat += "[copytext(html_encode(exploitable_info), 1, 40)]..." + dat += "
" + //Empty column for future stuff here + dat += "
" + if(4) //Loadout + dat += "
" + for(var/category in GLOB.loadout_category_to_subcategory_to_items) + dat += "[category] " + dat += "
" + dat += "
" + if(loadout_category != "") + dat += "
" + for(var/subcategory in GLOB.loadout_category_to_subcategory_to_items[loadout_category]) + dat += "[subcategory] " + dat += "
" + dat += "
" + if(loadout_subcategory != "") + var/list/item_names = GLOB.loadout_category_to_subcategory_to_items[loadout_category][loadout_subcategory] + + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + var/even = FALSE + for(var/path in item_names) + var/datum/loadout_item/LI = GLOB.loadout_items[path] + if(LI.ckeywhitelist && !LI.ckeywhitelist[user.ckey] && !user.client.holder) + continue + var/background_cl = "#23273C" + if(even) + background_cl = "#17191C" + even = !even + var/loadout_button_class + var/customization_button = "" + if(loadout[LI.path]) //We have this item purchased, but we can sell it + loadout_button_class = "href='?_src_=prefs;task=change_loadout;item=[path]' class='linkOn'" + var/custom_info = loadout[LI.path] + switch(LI.extra_info) + if(LOADOUT_INFO_ONE_COLOR) + customization_button = "
    Change
" + if(LOADOUT_INFO_THREE_COLORS) + customization_button = "" //TODO + if(LOADOUT_INFO_STYLE) + customization_button = "" //TODO + else if(LI.cost > loadout_points) //We cannot afford this item + loadout_button_class = "class='linkOff'" + else //We can buy it + loadout_button_class = "href='?_src_=prefs;task=change_loadout;item=[path]'" + + + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + dat += "
Name DescriptionRestrictions
Cost
[LI.name][customization_button][LI.description][LI.restricted_desc]
[LI.cost]
" + + if (1) // Game Preferences + dat += "
" + dat += "

General Settings

" + dat += "UI Style: [UI_style]
" + dat += "tgui Window Mode: [(tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"]
" + dat += "tgui Window Placement: [(tgui_lock) ? "Primary monitor" : "Free (default)"]
" + dat += "Show Runechat Chat Bubbles: [chat_on_map ? "Enabled" : "Disabled"]
" + dat += "Runechat message char limit: [max_chat_length]
" + dat += "See Runechat for non-mobs: [see_chat_non_mob ? "Enabled" : "Disabled"]
" + dat += "See Runechat emotes: [see_rc_emotes ? "Enabled" : "Disabled"]
" + dat += "
" + dat += "Action Buttons: [(buttons_locked) ? "Locked In Place" : "Unlocked"]
" + dat += "Hotkey mode: [(hotkeys) ? "Hotkeys" : "Default"]
" + dat += "
" + dat += "PDA Color:     Change
" + dat += "PDA Style: [pda_style]
" + dat += "
" + dat += "Ghost Ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]
" + dat += "Ghost Radio: [(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"]
" + dat += "Ghost Sight: [(chat_toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]
" + dat += "Ghost Whispers: [(chat_toggles & CHAT_GHOSTWHISPER) ? "All Speech" : "Nearest Creatures"]
" + dat += "Ghost PDA: [(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"]
" + dat += "Ghost Law Changes: [(chat_toggles & CHAT_GHOSTLAWS) ? "All Law Changes" : "No Law Changes"]
" + + if(unlock_content) + dat += "Ghost Form: [ghost_form]
" + dat += "Ghost Orbit: [ghost_orbit]
" + + var/button_name = "If you see this something went wrong." + switch(ghost_accs) + if(GHOST_ACCS_FULL) + button_name = GHOST_ACCS_FULL_NAME + if(GHOST_ACCS_DIR) + button_name = GHOST_ACCS_DIR_NAME + if(GHOST_ACCS_NONE) + button_name = GHOST_ACCS_NONE_NAME + + dat += "Ghost Accessories: [button_name]
" + + switch(ghost_others) + if(GHOST_OTHERS_THEIR_SETTING) + button_name = GHOST_OTHERS_THEIR_SETTING_NAME + if(GHOST_OTHERS_DEFAULT_SPRITE) + button_name = GHOST_OTHERS_DEFAULT_SPRITE_NAME + if(GHOST_OTHERS_SIMPLE) + button_name = GHOST_OTHERS_SIMPLE_NAME + + dat += "Ghosts of Others: [button_name]
" + dat += "
" + + dat += "Income Updates: [(chat_toggles & CHAT_BANKCARD) ? "Allowed" : "Muted"]
" + dat += "
" + + dat += "FPS: [clientfps]
" + + dat += "Parallax (Fancy Space): " + switch (parallax) + if (PARALLAX_LOW) + dat += "Low" + if (PARALLAX_MED) + dat += "Medium" + if (PARALLAX_INSANE) + dat += "Insane" + if (PARALLAX_DISABLE) + dat += "Disabled" + else + dat += "High" + dat += "
" + + dat += "Ambient Occlusion: [ambientocclusion ? "Enabled" : "Disabled"]
" + dat += "Fit Viewport: [auto_fit_viewport ? "Auto" : "Manual"]
" + if (CONFIG_GET(string/default_view) != CONFIG_GET(string/default_view_square)) + dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled ([CONFIG_GET(string/default_view_square)])"]
" + + button_name = pixel_size + dat += "Pixel Scaling: [(button_name) ? "Pixel Perfect [button_name]x" : "Stretch to fit"]
" + + switch(scaling_method) + if(SCALING_METHOD_DISTORT) + button_name = "Nearest Neighbor" + if(SCALING_METHOD_NORMAL) + button_name = "Point Sampling" + if(SCALING_METHOD_BLUR) + button_name = "Bilinear" + dat += "Scaling Method: [button_name]
" + + if (CONFIG_GET(flag/maprotation)) + var/p_map = preferred_map + if (!p_map) + p_map = "Default" + if (config.defaultmap) + p_map += " ([config.defaultmap.map_name])" + else + if (p_map in config.maplist) + var/datum/map_config/VM = config.maplist[p_map] + if (!VM) + p_map += " (No longer exists)" + else + p_map = VM.map_name + else + p_map += " (No longer exists)" + if(CONFIG_GET(flag/preference_map_voting)) + dat += "Preferred Map: [p_map]
" + + dat += "
" + + dat += "

Special Role Settings

" + + if(is_banned_from(user.ckey, ROLE_SYNDICATE)) + dat += "You are banned from antagonist roles.
" + src.be_special = list() + + + for (var/i in GLOB.special_roles) + if(is_banned_from(user.ckey, i)) + dat += "Be [capitalize(i)]: BANNED
" + else + var/days_remaining = null + if(ispath(GLOB.special_roles[i]) && CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age + var/mode_path = GLOB.special_roles[i] + var/datum/game_mode/temp_mode = new mode_path + days_remaining = temp_mode.get_remaining_days(user.client) + + if(days_remaining) + dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS]
" + else + dat += "Be [capitalize(i)]: [(i in be_special) ? "Enabled" : "Disabled"]
" + dat += "
" + dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"]
" + dat += "
" + if(2) //OOC Preferences + dat += "" + + if(user.client.holder) + dat +="" + dat += "
" + dat += "

OOC Settings

" + dat += "Window Flashing: [(windowflashing) ? "Enabled":"Disabled"]
" + dat += "
" + dat += "Play Admin MIDIs: [(toggles & SOUND_MIDI) ? "Enabled":"Disabled"]
" + dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"]
" + dat += "Play End of Round Sounds: [(toggles & SOUND_ENDOFROUND) ? "Enabled":"Disabled"]
" + dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"]
" + dat += "
" + + + if(user.client) + if(unlock_content) + dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" + + if(unlock_content || check_rights_for(user.client, R_ADMIN)) + dat += "OOC Color:     Change
" + if(hearted_until) + dat += "Clear OOC Commend Heart
" + + dat += "
" + + dat += "

Admin Settings

" + + dat += "Adminhelp Sounds: [(toggles & SOUND_ADMINHELP)?"Enabled":"Disabled"]
" + dat += "Prayer Sounds: [(toggles & SOUND_PRAYERS)?"Enabled":"Disabled"]
" + dat += "Announce Login: [(toggles & ANNOUNCE_LOGIN)?"Enabled":"Disabled"]
" + dat += "
" + dat += "Combo HUD Lighting: [(toggles & COMBOHUD_LIGHTING)?"Full-bright":"No Change"]
" + dat += "
" + dat += "Hide Dead Chat: [(chat_toggles & CHAT_DEAD)?"Shown":"Hidden"]
" + dat += "Hide Radio Messages: [(chat_toggles & CHAT_RADIO)?"Shown":"Hidden"]
" + dat += "Hide Prayers: [(chat_toggles & CHAT_PRAYER)?"Shown":"Hidden"]
" + dat += "Ignore Being Summoned as Cult Ghost: [(toggles & ADMIN_IGNORE_CULT_GHOST)?"Don't Allow Being Summoned":"Allow Being Summoned"]
" + if(CONFIG_GET(flag/allow_admin_asaycolor)) + dat += "
" + dat += "ASAY Color:     Change
" + + //deadmin + dat += "

Deadmin While Playing

" + var/timegate = CONFIG_GET(number/auto_deadmin_timegate) + if(timegate) + dat += "Noted roles will automatically deadmin during the first [FLOOR(timegate / 600, 1)] minutes of the round, and will defer to individual preferences after.
" + + if(CONFIG_GET(flag/auto_deadmin_players) && !timegate) + dat += "Always Deadmin: FORCED
" + else + dat += "Always Deadmin: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_ALWAYS)?"Enabled":"Disabled"]
" + if(!(toggles & DEADMIN_ALWAYS)) + dat += "
" + if(!CONFIG_GET(flag/auto_deadmin_antagonists) || (CONFIG_GET(flag/auto_deadmin_antagonists) && !timegate)) + dat += "As Antag: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_ANTAGONIST)?"Deadmin":"Keep Admin"]
" + else + dat += "As Antag: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_heads) || (CONFIG_GET(flag/auto_deadmin_heads) && !timegate)) + dat += "As Command: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_POSITION_HEAD)?"Deadmin":"Keep Admin"]
" + else + dat += "As Command: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_security) || (CONFIG_GET(flag/auto_deadmin_security) && !timegate)) + dat += "As Security: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_POSITION_SECURITY)?"Deadmin":"Keep Admin"]
" + else + dat += "As Security: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_silicons) || (CONFIG_GET(flag/auto_deadmin_silicons) && !timegate)) + dat += "As Silicon: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_POSITION_SILICON)?"Deadmin":"Keep Admin"]
" + else + dat += "As Silicon: FORCED
" + + dat += "
" + if(3) // Custom keybindings + // Create an inverted list of keybindings -> key + var/list/user_binds = list() + for (var/key in key_bindings) + for(var/kb_name in key_bindings[key]) + user_binds[kb_name] += list(key) + + var/list/kb_categories = list() + // Group keybinds by category + for (var/name in GLOB.keybindings_by_name) + var/datum/keybinding/kb = GLOB.keybindings_by_name[name] + kb_categories[kb.category] += list(kb) + + dat += "" + + for (var/category in kb_categories) + dat += "

[category]

" + for (var/i in kb_categories[category]) + var/datum/keybinding/kb = i + if(!length(user_binds[kb.name])) + dat += " Unbound" + var/list/default_keys = hotkeys ? kb.hotkey_keys : kb.classic_keys + if(LAZYLEN(default_keys)) + dat += "| Default: [default_keys.Join(", ")]" + dat += "
" + else + var/bound_key = user_binds[kb.name][1] + dat += " [bound_key]" + for(var/bound_key_index in 2 to length(user_binds[kb.name])) + bound_key = user_binds[kb.name][bound_key_index] + dat += " | [bound_key]" + if(length(user_binds[kb.name]) < MAX_KEYS_PER_KEYBIND) + dat += "| Add Secondary" + var/list/default_keys = hotkeys ? kb.classic_keys : kb.hotkey_keys + if(LAZYLEN(default_keys)) + dat += "| Default: [default_keys.Join(", ")]" + dat += "
" + + dat += "

" + dat += "\[Reset to default\]" + dat += "" + dat += "
" + + if(!IsGuestKey(user.key)) + dat += "Undo " + dat += "Save Setup " + + dat += "Reset Setup" + dat += "
" + + winshow(user, "preferences_window", TRUE) + var/datum/browser/popup = new(user, "preferences_browser", "
Character Setup
", 640, 770) + popup.set_content(dat.Join()) + popup.open(FALSE) + onclose(user, "preferences_window", src) + +#undef APPEARANCE_CATEGORY_COLUMN +#undef MAX_MUTANT_ROWS + +/datum/preferences/proc/CaptureKeybinding(mob/user, datum/keybinding/kb, var/old_key) + var/HTML = {" +
Keybinding: [kb.full_name]
[kb.description]

Press any key to change
Press ESC to clear
+ + "} + winshow(user, "capturekeypress", TRUE) + var/datum/browser/popup = new(user, "capturekeypress", "
Keybindings
", 350, 300) + popup.set_content(HTML) + popup.open(FALSE) + onclose(user, "capturekeypress", src) + +/datum/preferences/proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Chief Engineer"), widthPerColumn = 295, height = 620) + if(!SSjob) + return + + //limit - The amount of jobs allowed per column. Defaults to 17 to make it look nice. + //splitJobs - Allows you split the table by job. You can make different tables for each department by including their heads. Defaults to CE to make it look nice. + //widthPerColumn - Screen's width for every column. + //height - Screen's height. + + var/width = widthPerColumn + + var/HTML = "
" + if(SSjob.occupations.len <= 0) + HTML += "The job SSticker is not yet finished creating jobs, please try again later" + HTML += "
Done

" // Easier to press up here. + + else + HTML += "Choose occupation chances
" + HTML += "
Left-click to raise an occupation preference, right-click to lower it.
" + HTML += "
Done

" // Easier to press up here. + HTML += "" + HTML += "
" // Table within a table for alignment, also allows you to easily add more colomns. + HTML += "" + var/index = -1 + + //The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows. + var/datum/job/lastJob + + for(var/datum/job/job in sortList(SSjob.occupations, /proc/cmp_job_display_asc)) + + index += 1 + if((index >= limit) || (job.title in splitJobs)) + width += widthPerColumn + if((index < limit) && (lastJob != null)) + //If the cells were broken up by a job in the splitJob list then it will fill in the rest of the cells with + //the last job's selection color. Creating a rather nice effect. + for(var/i = 0, i < (limit - index), i += 1) + HTML += "" + HTML += "
  
" + index = 0 + + HTML += "" + continue + var/required_playtime_remaining = job.required_playtime_remaining(user.client) + if(required_playtime_remaining) + HTML += "[rank]" + continue + if(!job.player_old_enough(user.client)) + var/available_in_days = job.available_in_days(user.client) + HTML += "[rank]" + continue + if((job_preferences[SSjob.overflow_role] == JP_LOW) && (rank != SSjob.overflow_role) && !is_banned_from(user.ckey, SSjob.overflow_role)) + HTML += "[rank]" + continue + if((rank in GLOB.command_positions) || (rank == "AI"))//Bold head jobs + HTML += "[rank]" + else + HTML += "[rank]" + + HTML += "" + continue + + HTML += "[prefLevelLabel]" + HTML += "" + + for(var/i = 1, i < (limit - index), i += 1) // Finish the column so it is even + HTML += "" + + HTML += "
" + var/rank = job.title + lastJob = job + if(is_banned_from(user.ckey, rank)) + HTML += "[rank] BANNED
\[ [get_exp_format(required_playtime_remaining)] as [job.get_exp_req_type()] \]
\[IN [(available_in_days)] DAYS\]
" + + var/prefLevelLabel = "ERROR" + var/prefLevelColor = "pink" + var/prefUpperLevel = -1 // level to assign on left click + var/prefLowerLevel = -1 // level to assign on right click + + switch(job_preferences[job.title]) + if(JP_HIGH) + prefLevelLabel = "High" + prefLevelColor = "slateblue" + prefUpperLevel = 4 + prefLowerLevel = 2 + if(JP_MEDIUM) + prefLevelLabel = "Medium" + prefLevelColor = "green" + prefUpperLevel = 1 + prefLowerLevel = 3 + if(JP_LOW) + prefLevelLabel = "Low" + prefLevelColor = "orange" + prefUpperLevel = 2 + prefLowerLevel = 4 + else + prefLevelLabel = "NEVER" + prefLevelColor = "red" + prefUpperLevel = 3 + prefLowerLevel = 1 + + HTML += "" + + if(rank == SSjob.overflow_role)//Overflow is special + if(job_preferences[SSjob.overflow_role] == JP_LOW) + HTML += "Yes" + else + HTML += "No" + HTML += "
  
" + HTML += "
" + + var/message = "Be an [SSjob.overflow_role] if preferences unavailable" + if(joblessrole == BERANDOMJOB) + message = "Get random job if preferences unavailable" + else if(joblessrole == RETURNTOLOBBY) + message = "Return to lobby if preferences unavailable" + HTML += "

[message]
" + HTML += "
Reset Preferences
" + + var/datum/browser/popup = new(user, "mob_occupation", "
Occupation Preferences
", width, height) + popup.set_window_options("can_close=0") + popup.set_content(HTML) + popup.open(FALSE) + +/datum/preferences/proc/SetJobPreferenceLevel(datum/job/job, level) + if (!job) + return FALSE + + if (level == JP_HIGH) // to high + //Set all other high to medium + for(var/j in job_preferences) + if(job_preferences[j] == JP_HIGH) + job_preferences[j] = JP_MEDIUM + //technically break here + + job_preferences[job.title] = level + return TRUE + +/datum/preferences/proc/UpdateJobPreference(mob/user, role, desiredLvl) + if(!SSjob || SSjob.occupations.len <= 0) + return + var/datum/job/job = SSjob.GetJob(role) + + if(!job) + user << browse(null, "window=mob_occupation") + ShowChoices(user) + return + + if (!isnum(desiredLvl)) + to_chat(user, "UpdateJobPreference - desired level was not a number. Please notify coders!") + ShowChoices(user) + return + + var/jpval = null + switch(desiredLvl) + if(3) + jpval = JP_LOW + if(2) + jpval = JP_MEDIUM + if(1) + jpval = JP_HIGH + + if(role == SSjob.overflow_role) + if(job_preferences[job.title] == JP_LOW) + jpval = null + else + jpval = JP_LOW + + SetJobPreferenceLevel(job, jpval) + SetChoices(user) + + return 1 + + +/datum/preferences/proc/ResetJobs() + job_preferences = list() + +/datum/preferences/proc/SetQuirks(mob/user) + if(!SSquirks) + to_chat(user, "The quirk subsystem is still initializing! Try again in a minute.") + return + + var/list/dat = list() + if(!SSquirks.quirks.len) + dat += "The quirk subsystem hasn't finished initializing, please hold..." + dat += "
Done

" + else + dat += "
Choose quirk setup

" + dat += "
Left-click to add or remove quirks. You need negative quirks to have positive ones.
\ + Quirks are applied at roundstart and cannot normally be removed.
" + dat += "
Done
" + dat += "
" + dat += "
Current quirks: [all_quirks.len ? all_quirks.Join(", ") : "None"]
" + dat += "
[GetPositiveQuirkCount()] / [MAX_QUIRKS] max positive quirks
\ + Quirk balance remaining: [GetQuirkBalance()]

" + for(var/V in SSquirks.quirks) + var/datum/quirk/T = SSquirks.quirks[V] + var/quirk_name = initial(T.name) + var/has_quirk + var/quirk_cost = initial(T.value) * -1 + var/lock_reason = "This trait is unavailable." + var/quirk_conflict = FALSE + for(var/_V in all_quirks) + if(_V == quirk_name) + has_quirk = TRUE + if(initial(T.mood_quirk) && CONFIG_GET(flag/disable_human_mood)) + lock_reason = "Mood is disabled." + quirk_conflict = TRUE + if(has_quirk) + if(quirk_conflict) + all_quirks -= quirk_name + has_quirk = FALSE + else + quirk_cost *= -1 //invert it back, since we'd be regaining this amount + if(quirk_cost > 0) + quirk_cost = "+[quirk_cost]" + var/font_color = "#AAAAFF" + if(initial(T.value) != 0) + font_color = initial(T.value) > 0 ? "#AAFFAA" : "#FFAAAA" + if(quirk_conflict) + dat += "[quirk_name] - [initial(T.desc)] \ + LOCKED: [lock_reason]
" + else + if(has_quirk) + dat += "[has_quirk ? "Remove" : "Take"] ([quirk_cost] pts.) \ + [quirk_name] - [initial(T.desc)]
" + else + dat += "[has_quirk ? "Remove" : "Take"] ([quirk_cost] pts.) \ + [quirk_name] - [initial(T.desc)]
" + dat += "
Reset Quirks
" + + var/datum/browser/popup = new(user, "mob_occupation", "
Quirk Preferences
", 900, 600) //no reason not to reuse the occupation window, as it's cleaner that way + popup.set_window_options("can_close=0") + popup.set_content(dat.Join()) + popup.open(FALSE) + +/datum/preferences/proc/GetQuirkBalance() + var/bal = 0 + for(var/V in all_quirks) + var/datum/quirk/T = SSquirks.quirks[V] + bal -= initial(T.value) + return bal + +/datum/preferences/proc/GetPositiveQuirkCount() + . = 0 + for(var/q in all_quirks) + if(SSquirks.quirk_points[q] > 0) + .++ + +/datum/preferences/Topic(href, href_list, hsrc) //yeah, gotta do this I guess.. + . = ..() + if(href_list["close"]) + var/client/C = usr.client + if(C) + C.clear_character_previews() + +/datum/preferences/proc/process_link(mob/user, list/href_list) + if(href_list["bancheck"]) + var/list/ban_details = is_banned_from_with_details(user.ckey, user.client.address, user.client.computer_id, href_list["bancheck"]) + var/admin = FALSE + if(GLOB.admin_datums[user.ckey] || GLOB.deadmins[user.ckey]) + admin = TRUE + for(var/i in ban_details) + if(admin && !text2num(i["applies_to_admins"])) + continue + ban_details = i + break //we only want to get the most recent ban's details + if(ban_details && ban_details.len) + var/expires = "This is a permanent ban." + if(ban_details["expiration_time"]) + expires = " The ban is for [DisplayTimeText(text2num(ban_details["duration"]) MINUTES)] and expires on [ban_details["expiration_time"]] (server time)." + to_chat(user, "You, or another user of this computer or connection ([ban_details["key"]]) is banned from playing [href_list["bancheck"]].
The ban reason is: [ban_details["reason"]]
This ban (BanID #[ban_details["id"]]) was applied by [ban_details["admin_key"]] on [ban_details["bantime"]] during round ID [ban_details["round_id"]].
[expires]
") + return + if(href_list["preference"] == "job") + switch(href_list["task"]) + if("close") + user << browse(null, "window=mob_occupation") + ShowChoices(user) + if("reset") + ResetJobs() + SetChoices(user) + if("random") + switch(joblessrole) + if(RETURNTOLOBBY) + if(is_banned_from(user.ckey, SSjob.overflow_role)) + joblessrole = BERANDOMJOB + else + joblessrole = BEOVERFLOW + if(BEOVERFLOW) + joblessrole = BERANDOMJOB + if(BERANDOMJOB) + joblessrole = RETURNTOLOBBY + SetChoices(user) + if("setJobLevel") + UpdateJobPreference(user, href_list["text"], text2num(href_list["level"])) + else + SetChoices(user) + return 1 + + else if(href_list["preference"] == "trait") + switch(href_list["task"]) + if("close") + user << browse(null, "window=mob_occupation") + ShowChoices(user) + if("update") + var/quirk = href_list["trait"] + if(!SSquirks.quirks[quirk]) + return + for(var/V in SSquirks.quirk_blacklist) //V is a list + var/list/L = V + if(!(quirk in L)) + continue + for(var/Q in all_quirks) + if((Q in L) && !(Q == quirk)) //two quirks have lined up in the list of the list of quirks that conflict with each other, so return (see quirks.dm for more details) + to_chat(user, "[quirk] is incompatible with [Q].") + return + var/value = SSquirks.quirk_points[quirk] + var/balance = GetQuirkBalance() + if(quirk in all_quirks) + if(balance + value < 0) + to_chat(user, "Refunding this would cause you to go below your balance!") + return + all_quirks -= quirk + else + var/is_positive_quirk = SSquirks.quirk_points[quirk] > 0 + if(is_positive_quirk && GetPositiveQuirkCount() >= MAX_QUIRKS) + to_chat(user, "You can't have more than [MAX_QUIRKS] positive quirks!") + return + if(balance - value < 0) + to_chat(user, "You don't have enough balance to gain this quirk!") + return + all_quirks += quirk + SetQuirks(user) + if("reset") + all_quirks = list() + SetQuirks(user) + else + SetQuirks(user) + return TRUE + + switch(href_list["task"]) + if("change_loadout_customization") + var/path = text2path(href_list["item"]) + if(!loadout[path]) + return + var/datum/loadout_item/LI = GLOB.loadout_items[path] + switch(LI.extra_info) + if(LOADOUT_INFO_ONE_COLOR) + var/new_color = input(user, "Choose your item's color:", "Character Preference","#[loadout[path]]") as color|null + if(new_color) + if(!loadout[path]) + return + loadout[path] = sanitize_hexcolor(new_color) + if(LOADOUT_INFO_THREE_COLORS) + return + if(LOADOUT_INFO_STYLE) + return + if("change_loadout") + var/path = text2path(href_list["item"]) + var/datum/loadout_item/LI = GLOB.loadout_items[path] + if(loadout[path]) //We sell it! + loadout -= path + loadout_points += LI.cost + else //We attempt to buy it + if(LI.cost > loadout_points) + return + if(LI.ckeywhitelist && !LI.ckeywhitelist[user.ckey] && !user.client.holder) + return + loadout_points -= LI.cost + loadout[LI.path] = LI.default_customization() //As in "No extra information associated" + if("change_marking") + switch(href_list["preference"]) + if("use_preset") + var/action = alert(user, "Are you sure you want to use a preset (This will clear your existing markings)?", "", "Yes", "No") + if(action && action == "Yes") + var/list/candidates = GLOB.body_marking_sets.Copy() + if(!mismatched_customization) + for(var/name in candidates) + var/datum/body_marking_set/BMS = GLOB.body_marking_sets[name] + if(BMS.recommended_species && !(pref_species.id in BMS.recommended_species)) + candidates -= name + if(length(candidates) == 0) + return + var/desired_set = input(user, "Choose your new body markings:", "Character Preference") as null|anything in candidates + if(desired_set) + var/datum/body_marking_set/BMS = GLOB.body_marking_sets[desired_set] + body_markings = assemble_body_markings_from_set(BMS, features, pref_species) + + if("reset_color") + var/zone = href_list["key"] + var/name = href_list["name"] + if(!body_markings[zone] || !body_markings[zone][name]) + return + var/datum/body_marking/BM = GLOB.body_markings[name] + body_markings[zone][name] = BM.get_default_color(features, pref_species) + if("change_color") + var/zone = href_list["key"] + var/name = href_list["name"] + if(!body_markings[zone] || !body_markings[zone][name]) + return + var/color = body_markings[zone][name] + var/new_color = input(user, "Choose your markings color:", "Character Preference","#[color]") as color|null + if(new_color) + if(!body_markings[zone] || !body_markings[zone][name]) + return + body_markings[zone][name] = sanitize_hexcolor(new_color) + if("marking_move_up") + var/zone = href_list["key"] + var/name = href_list["name"] + var/list/marking_list = LAZYACCESS(body_markings, zone) + var/current_index = LAZYFIND(marking_list, name) + if(!current_index || --current_index < 1) + return + var/marking_content = marking_list[name] + marking_list -= name + marking_list.Insert(current_index, name) + marking_list[name] = marking_content + if("marking_move_down") + var/zone = href_list["key"] + var/name = href_list["name"] + var/list/marking_list = LAZYACCESS(body_markings, zone) + var/current_index = LAZYFIND(marking_list, name) + if(!current_index || ++current_index > length(marking_list)) + return + var/marking_content = marking_list[name] + marking_list -= name + marking_list.Insert(current_index, name) + marking_list[name] = marking_content + if("add_marking") + var/zone = href_list["key"] + if(!GLOB.body_markings_per_limb[zone]) + return + var/list/possible_candidates = GLOB.body_markings_per_limb[zone].Copy() + if(body_markings[zone]) + //To prevent exploiting hrefs to bypass the marking limit + if(body_markings[zone].len >= MAXIMUM_MARKINGS_PER_LIMB) + return + //Remove already used markings from the candidates + for(var/list/this_list in body_markings[zone]) + possible_candidates -= this_list[MUTANT_INDEX_NAME] + if(!mismatched_customization) + for(var/name in possible_candidates) + var/datum/body_marking/BD = GLOB.body_markings[name] + if(BD.recommended_species && !(pref_species.id in BD.recommended_species)) + possible_candidates -= name + + if(possible_candidates.len == 0) + return + var/desired_marking = input(user, "Choose your new marking to add:", "Character Preference") as null|anything in possible_candidates + if(desired_marking) + var/datum/body_marking/BD = GLOB.body_markings[desired_marking] + if(!body_markings[zone]) + body_markings[zone] = list() + body_markings[zone][BD.name] = BD.get_default_color(features, pref_species) + + if("remove_marking") + var/zone = href_list["key"] + var/name = href_list["name"] + if(!body_markings[zone] || !body_markings[zone][name]) + return + body_markings[zone] -= name + if(body_markings[zone].len == 0) + body_markings -= zone + if("change_marking") + var/zone = href_list["key"] + var/changing_name = href_list["name"] + + var/list/possible_candidates = GLOB.body_markings_per_limb[zone].Copy() + if(body_markings[zone]) + //Remove already used markings from the candidates + for(var/keyed_name in body_markings[zone]) + possible_candidates -= keyed_name + if(!mismatched_customization) + for(var/name in possible_candidates) + var/datum/body_marking/BD = GLOB.body_markings[name] + if(BD.recommended_species && !(pref_species.id in BD.recommended_species)) + possible_candidates -= name + if(possible_candidates.len == 0) + return + var/desired_marking = input(user, "Choose a marking to change the current one to:", "Character Preference") as null|anything in possible_candidates + if(desired_marking) + if(!body_markings[zone] || !body_markings[zone][changing_name]) + return + var/held_index = LAZYFIND(body_markings[zone], changing_name) + body_markings[zone] -= changing_name + var/datum/body_marking/BD = GLOB.body_markings[desired_marking] + var/marking_content = BD.get_default_color(features, pref_species) + body_markings[zone].Insert(held_index, desired_marking) + body_markings[zone][desired_marking] = marking_content + if("change_genitals") + switch(href_list["preference"]) + if("breasts_size") + var/new_size = input(user, "Choose your character's breasts size:", "Character Preference") as null|anything in GLOB.preference_breast_sizes + if(new_size) + features["breasts_size"] = breasts_cup_to_size(new_size) + if("breasts_lactation") + features["breasts_lactation"] = !features["breasts_lactation"] + if("penis_taur_mode") + features["penis_taur_mode"] = !features["penis_taur_mode"] + if("penis_size") + var/new_length = input(user, "Choose your penis length:\n(2-20 in inches)", "Character Preference") as num|null + if(new_length) + features["penis_size"] = clamp(round(new_length, 1), 2, 20) + if(features["penis_girth"] >= new_length) + features["penis_girth"] = new_length - 1 + if("penis_girth") + var/max_girth = 15 + if(features["penis_size"] >= max_girth) + max_girth = features["penis_size"] + var/new_girth = input(user, "Choose your penis girth:\n(1-[max_girth] (based on length) in inches)", "Character Preference") as num|null + if(new_girth) + features["penis_girth"] = clamp(round(new_girth, 1), 1, max_girth) + if("balls_size") + var/new_size = input(user, "Choose your character's balls size:", "Character Preference") as null|anything in GLOB.preference_balls_sizes + if(new_size) + features["balls_size"] = balls_description_to_size(new_size) + if("change_bodypart") + switch(href_list["preference"]) + if("change_name") + var/key = href_list["key"] + if(!mutant_bodyparts[key]) + return + var/new_name + if(mismatched_customization) + new_name = input(user, "Choose your character's [key]:", "Character Preference") as null|anything in GLOB.sprite_accessories[key] + else + new_name = input(user, "Choose your character's [key]:", "Character Preference") as null|anything in accessory_list_of_key_for_species(key,pref_species) + if(new_name && mutant_bodyparts[key]) + mutant_bodyparts[key][MUTANT_INDEX_NAME] = new_name + validate_color_keys_for_part(key) + if(!allow_advanced_colors) + var/datum/sprite_accessory/SA = GLOB.sprite_accessories[key][new_name] + mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(features) + if("change_color") + var/key = href_list["key"] + if(!mutant_bodyparts[key]) + return + var/list/colorlist = mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] + var/index = text2num(href_list["color_index"]) + if(colorlist.len < index) + return + var/new_color = input(user, "Choose your character's [key] color:", "Character Preference","#[colorlist[index]]") as color|null + if(new_color) + colorlist[index] = sanitize_hexcolor(new_color) + if("reset_color") + var/key = href_list["key"] + if(!mutant_bodyparts[key]) + return + var/datum/sprite_accessory/SA = GLOB.sprite_accessories[key][mutant_bodyparts[key][MUTANT_INDEX_NAME]] + mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(features) + if("reset_all_colors") + var/action = alert(user, "Are you sure you want to reset all colors?", "", "Yes", "No") + if(action == "Yes") + reset_colors() + + if("random") + switch(href_list["preference"]) + if("name") + real_name = pref_species.random_name(gender,1) + if("age") + age = rand(AGE_MIN, AGE_MAX) + if("hair") + hair_color = random_short_color() + if("hairstyle") + hairstyle = random_hairstyle(gender) + if("facial") + facial_hair_color = random_short_color() + if("facial_hairstyle") + facial_hairstyle = random_facial_hairstyle(gender) + if("underwear") + underwear = random_underwear(gender) + if("underwear_color") + underwear_color = random_short_color() + if("undershirt") + undershirt = random_undershirt(gender) + if("socks") + socks = random_socks() + if(BODY_ZONE_PRECISE_EYES) + eye_color = random_eye_color() + if("s_tone") + set_skin_tone(random_skin_tone()) + if("species") + random_species() + if("bag") + backpack = pick(GLOB.backpacklist) + if("suit") + jumpsuit_style = pick(GLOB.jumpsuitlist) + if("all") + random_character(gender) + + if("input") + + if(href_list["preference"] in GLOB.preferences_custom_names) + ask_for_custom_name(user,href_list["preference"]) + + + switch(href_list["preference"]) + if("ghostform") + if(unlock_content) + var/new_form = input(user, "Thanks for supporting BYOND - Choose your ghostly form:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_forms + if(new_form) + ghost_form = new_form + if("ghostorbit") + if(unlock_content) + var/new_orbit = input(user, "Thanks for supporting BYOND - Choose your ghostly orbit:","Thanks for supporting BYOND", null) as null|anything in GLOB.ghost_orbits + if(new_orbit) + ghost_orbit = new_orbit + + if("ghostaccs") + var/new_ghost_accs = alert("Do you want your ghost to show full accessories where possible, hide accessories but still use the directional sprites where possible, or also ignore the directions and stick to the default sprites?",,GHOST_ACCS_FULL_NAME, GHOST_ACCS_DIR_NAME, GHOST_ACCS_NONE_NAME) + switch(new_ghost_accs) + if(GHOST_ACCS_FULL_NAME) + ghost_accs = GHOST_ACCS_FULL + if(GHOST_ACCS_DIR_NAME) + ghost_accs = GHOST_ACCS_DIR + if(GHOST_ACCS_NONE_NAME) + ghost_accs = GHOST_ACCS_NONE + + if("ghostothers") + var/new_ghost_others = alert("Do you want the ghosts of others to show up as their own setting, as their default sprites or always as the default white ghost?",,GHOST_OTHERS_THEIR_SETTING_NAME, GHOST_OTHERS_DEFAULT_SPRITE_NAME, GHOST_OTHERS_SIMPLE_NAME) + switch(new_ghost_others) + if(GHOST_OTHERS_THEIR_SETTING_NAME) + ghost_others = GHOST_OTHERS_THEIR_SETTING + if(GHOST_OTHERS_DEFAULT_SPRITE_NAME) + ghost_others = GHOST_OTHERS_DEFAULT_SPRITE + if(GHOST_OTHERS_SIMPLE_NAME) + ghost_others = GHOST_OTHERS_SIMPLE + + if("name") + var/new_name = input(user, "Choose your character's name:", "Character Preference") as text|null + if(new_name) + new_name = reject_bad_name(new_name) + if(new_name) + real_name = new_name + else + to_chat(user, "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and .") + + if("age") + var/new_age = input(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX])", "Character Preference") as num|null + if(new_age) + age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN) + + if("flavor_text") + var/msg = input(usr, "Set the flavor text in your 'examine' verb. This is for describing what people can tell by looking at your character.", "Flavor Text", features["flavor_text"]) as message|null //Skyrat edit, removed stripped_multiline_input() + if(!isnull(msg)) + features["flavor_text"] = strip_html_simple(msg, MAX_FLAVOR_LEN, TRUE) + + if("ooc_prefs") + var/msg = input(usr, "Set your OOC preferences.", "OOC Prefs", ooc_prefs) as message|null + if(!isnull(msg)) + ooc_prefs = strip_html_simple(msg, MAX_FLAVOR_LEN, TRUE) + + if("general_record") + var/msg = input(usr, "Set your general record. This is more or less public information, available from security, medical and command consoles", "General Record", general_record) as message|null + if(!isnull(msg)) + general_record = strip_html_simple(msg, MAX_FLAVOR_LEN, TRUE) + + if("medical_record") + var/msg = input(usr, "Set your medical record. ", "Medical Record", medical_record) as message|null + if(!isnull(msg)) + medical_record = strip_html_simple(msg, MAX_FLAVOR_LEN, TRUE) + + if("security_record") + var/msg = input(usr, "Set your security record. ", "Medical Record", security_record) as message|null + if(!isnull(msg)) + security_record = strip_html_simple(msg, MAX_FLAVOR_LEN, TRUE) + + if("background_info") + var/msg = input(usr, "Set your background information. (Where you come from, which culture were you raised in and why you are working here etc.)", "Background Info", background_info) as message|null + if(!isnull(msg)) + background_info = strip_html_simple(msg, MAX_FLAVOR_LEN, TRUE) + + if("exploitable_info") + var/msg = input(usr, "Set your exploitable information. This is sensitive informations that antagonists may get to see, recommended for better roleplay experience", "Exploitable Info", exploitable_info) as message|null + if(!isnull(msg)) + exploitable_info = strip_html_simple(msg, MAX_FLAVOR_LEN, TRUE) + + if("erp_pref") + switch(erp_pref) + if("Yes") + erp_pref = "Ask" + if("Ask") + erp_pref = "No" + if("No") + erp_pref = "Yes" + if("noncon_pref") + switch(noncon_pref) + if("Yes") + noncon_pref = "Ask" + if("Ask") + noncon_pref = "No" + if("No") + noncon_pref = "Yes" + if("vore_pref") + switch(vore_pref) + if("Yes") + vore_pref = "Ask" + if("Ask") + vore_pref = "No" + if("No") + vore_pref = "Yes" + + if("hair") + var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference","#"+hair_color) as color|null + if(new_hair) + hair_color = sanitize_hexcolor(new_hair) + + if("hairstyle") + var/new_hairstyle + if(gender == MALE) + new_hairstyle = input(user, "Choose your character's hairstyle:", "Character Preference") as null|anything in GLOB.hairstyles_male_list + else if(gender == FEMALE) + new_hairstyle = input(user, "Choose your character's hairstyle:", "Character Preference") as null|anything in GLOB.hairstyles_female_list + else + new_hairstyle = input(user, "Choose your character's hairstyle:", "Character Preference") as null|anything in GLOB.hairstyles_list + if(new_hairstyle) + hairstyle = new_hairstyle + + if("next_hairstyle") + if (gender == MALE) + hairstyle = next_list_item(hairstyle, GLOB.hairstyles_male_list) + else if(gender == FEMALE) + hairstyle = next_list_item(hairstyle, GLOB.hairstyles_female_list) + else + hairstyle = next_list_item(hairstyle, GLOB.hairstyles_list) + + if("previous_hairstyle") + if (gender == MALE) + hairstyle = previous_list_item(hairstyle, GLOB.hairstyles_male_list) + else if(gender == FEMALE) + hairstyle = previous_list_item(hairstyle, GLOB.hairstyles_female_list) + else + hairstyle = previous_list_item(hairstyle, GLOB.hairstyles_list) + + if("facial") + var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference","#"+facial_hair_color) as color|null + if(new_facial) + facial_hair_color = sanitize_hexcolor(new_facial) + + if("facial_hairstyle") + var/new_facial_hairstyle + if(gender == MALE) + new_facial_hairstyle = input(user, "Choose your character's facial-hairstyle:", "Character Preference") as null|anything in GLOB.facial_hairstyles_male_list + else if(gender == FEMALE) + new_facial_hairstyle = input(user, "Choose your character's facial-hairstyle:", "Character Preference") as null|anything in GLOB.facial_hairstyles_female_list + else + new_facial_hairstyle = input(user, "Choose your character's facial-hairstyle:", "Character Preference") as null|anything in GLOB.facial_hairstyles_list + if(new_facial_hairstyle) + facial_hairstyle = new_facial_hairstyle + + if("next_facehairstyle") + if (gender == MALE) + facial_hairstyle = next_list_item(facial_hairstyle, GLOB.facial_hairstyles_male_list) + else if(gender == FEMALE) + facial_hairstyle = next_list_item(facial_hairstyle, GLOB.facial_hairstyles_female_list) + else + facial_hairstyle = next_list_item(facial_hairstyle, GLOB.facial_hairstyles_list) + + if("previous_facehairstyle") + if (gender == MALE) + facial_hairstyle = previous_list_item(facial_hairstyle, GLOB.facial_hairstyles_male_list) + else if (gender == FEMALE) + facial_hairstyle = previous_list_item(facial_hairstyle, GLOB.facial_hairstyles_female_list) + else + facial_hairstyle = previous_list_item(facial_hairstyle, GLOB.facial_hairstyles_list) + + if("underwear") + var/new_underwear + if(gender == MALE) + new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_m + else if(gender == FEMALE) + new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_f + else + new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_list + if(new_underwear) + underwear = new_underwear + + if("underwear_color") + var/new_underwear_color = input(user, "Choose your character's underwear color:", "Character Preference","#"+underwear_color) as color|null + if(new_underwear_color) + underwear_color = sanitize_hexcolor(new_underwear_color) + + if("undershirt_color") + var/new_undershirt_color = input(user, "Choose your character's undershirt color:", "Character Preference","#"+undershirt_color) as color|null + if(new_undershirt_color) + undershirt_color = sanitize_hexcolor(new_undershirt_color) + + if("socks_color") + var/new_socks_color = input(user, "Choose your character's socks color:", "Character Preference","#"+socks_color) as color|null + if(new_socks_color) + socks_color = sanitize_hexcolor(new_socks_color) + + if("undershirt") + var/new_undershirt + if(gender == MALE) + new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_m + else if(gender == FEMALE) + new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_f + else + new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_list + if(new_undershirt) + undershirt = new_undershirt + + if("socks") + var/new_socks + new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in GLOB.socks_list + if(new_socks) + socks = new_socks + + if("eyes") + var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+eye_color) as color|null + if(new_eyes) + eye_color = sanitize_hexcolor(new_eyes) + + if("species") + + var/result = input(user, "Select a species", "Species Selection") as null|anything in GLOB.roundstart_races + + if(result) + var/newtype = GLOB.species_list[result] + set_new_species(newtype) + /*//Now that we changed our species, we must verify that the mutant colour is still allowed. + var/temp_hsv = RGBtoHSV(features["mcolor"]) + if(features["mcolor"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#7F7F7F")[3])) + features["mcolor"] = pref_species.default_color*/ + if(randomise[RANDOM_NAME]) + real_name = pref_species.random_name(gender) + + if("mutant_color") + var/new_mutantcolor = input(user, "Choose your character's primary color:", "Character Preference","#"+features["mcolor"]) as color|null + if(new_mutantcolor) + if(new_mutantcolor == "#000000") + features["mcolor"] = pref_species.default_color + else + features["mcolor"] = sanitize_hexcolor(new_mutantcolor) + if(!allow_advanced_colors) + reset_colors() + + if("mutant_color2") + var/new_mutantcolor = input(user, "Choose your character's secondary color:", "Character Preference","#"+features["mcolor2"]) as color|null + if(new_mutantcolor) + if(new_mutantcolor == "#000000") + features["mcolor2"] = pref_species.default_color + else + features["mcolor2"] = sanitize_hexcolor(new_mutantcolor) + if(!allow_advanced_colors) + reset_colors() + + if("mutant_color3") + var/new_mutantcolor = input(user, "Choose your character's tertiary color:", "Character Preference","#"+features["mcolor3"]) as color|null + if(new_mutantcolor) + if(new_mutantcolor == "#000000") + features["mcolor3"] = pref_species.default_color + else + features["mcolor3"] = sanitize_hexcolor(new_mutantcolor) + if(!allow_advanced_colors) + reset_colors() + + if("color_ethereal") + var/new_etherealcolor = input(user, "Choose your ethereal color", "Character Preference") as null|anything in GLOB.color_list_ethereal + if(new_etherealcolor) + features["ethcolor"] = GLOB.color_list_ethereal[new_etherealcolor] + + + /*if("tail_lizard") + var/new_tail + new_tail = input(user, "Choose your character's tail:", "Character Preference") as null|anything in GLOB.tails_list_lizard + if(new_tail) + features["tail_lizard"] = new_tail + + if("tail_human") + var/new_tail + new_tail = input(user, "Choose your character's tail:", "Character Preference") as null|anything in GLOB.tails_list_human + if(new_tail) + features["tail_human"] = new_tail + + if("snout") + var/new_snout + new_snout = input(user, "Choose your character's snout:", "Character Preference") as null|anything in GLOB.snouts_list + if(new_snout) + features["snout"] = new_snout + + if("horns") + var/new_horns + new_horns = input(user, "Choose your character's horns:", "Character Preference") as null|anything in GLOB.horns_list + if(new_horns) + features["horns"] = new_horns + + if("ears") + var/new_ears + new_ears = input(user, "Choose your character's ears:", "Character Preference") as null|anything in GLOB.ears_list + if(new_ears) + features["ears"] = new_ears + + if("wings") + var/new_wings + new_wings = input(user, "Choose your character's wings:", "Character Preference") as null|anything in GLOB.r_wings_list + if(new_wings) + features["wings"] = new_wings + + if("frills") + var/new_frills + new_frills = input(user, "Choose your character's frills:", "Character Preference") as null|anything in GLOB.frills_list + if(new_frills) + features["frills"] = new_frills + + if("spines") + var/new_spines + new_spines = input(user, "Choose your character's spines:", "Character Preference") as null|anything in GLOB.spines_list + if(new_spines) + features["spines"] = new_spines + + if("body_markings") + var/new_body_markings + new_body_markings = input(user, "Choose your character's body markings:", "Character Preference") as null|anything in GLOB.body_markings_list + if(new_body_markings) + features["body_markings"] = new_body_markings + + if("legs") + var/new_legs + new_legs = input(user, "Choose your character's legs:", "Character Preference") as null|anything in GLOB.legs_list + if(new_legs) + features["legs"] = new_legs + + if("moth_wings") + var/new_moth_wings + new_moth_wings = input(user, "Choose your character's wings:", "Character Preference") as null|anything in GLOB.moth_wings_list + if(new_moth_wings) + features["moth_wings"] = new_moth_wings + + if("moth_markings") + var/new_moth_markings + new_moth_markings = input(user, "Choose your character's markings:", "Character Preference") as null|anything in GLOB.moth_markings_list + if(new_moth_markings) + features["moth_markings"] = new_moth_markings*/ + + if("s_tone") + var/new_s_tone = input(user, "Choose your character's skin-tone:", "Character Preference") as null|anything in GLOB.skin_tones + if(new_s_tone) + set_skin_tone(new_s_tone) + + if("ooccolor") + var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference",ooccolor) as color|null + if(new_ooccolor) + ooccolor = new_ooccolor + + if("asaycolor") + var/new_asaycolor = input(user, "Choose your ASAY color:", "Game Preference",asaycolor) as color|null + if(new_asaycolor) + asaycolor = new_asaycolor + + if("bag") + var/new_backpack = input(user, "Choose your character's style of bag:", "Character Preference") as null|anything in GLOB.backpacklist + if(new_backpack) + backpack = new_backpack + + if("suit") + if(jumpsuit_style == PREF_SUIT) + jumpsuit_style = PREF_SKIRT + else + jumpsuit_style = PREF_SUIT + + if("uplink_loc") + var/new_loc = input(user, "Choose your character's traitor uplink spawn location:", "Character Preference") as null|anything in GLOB.uplink_spawn_loc_list + if(new_loc) + uplink_spawn_loc = new_loc + + if("playtime_reward_cloak") + if (user.client.get_exp_living(TRUE) >= PLAYTIME_VETERAN) + playtime_reward_cloak = !playtime_reward_cloak + + if("ai_core_icon") + var/ai_core_icon = input(user, "Choose your preferred AI core display screen:", "AI Core Display Screen Selection") as null|anything in GLOB.ai_core_display_screens + if(ai_core_icon) + preferred_ai_core_display = ai_core_icon + + if("sec_dept") + var/department = input(user, "Choose your preferred security department:", "Security Departments") as null|anything in GLOB.security_depts_prefs + if(department) + prefered_security_department = department + + if ("preferred_map") + var/maplist = list() + var/default = "Default" + if (config.defaultmap) + default += " ([config.defaultmap.map_name])" + for (var/M in config.maplist) + var/datum/map_config/VM = config.maplist[M] + if(!VM.votable) + continue + var/friendlyname = "[VM.map_name] " + if (VM.voteweight <= 0) + friendlyname += " (disabled)" + maplist[friendlyname] = VM.map_name + maplist[default] = null + var/pickedmap = input(user, "Choose your preferred map. This will be used to help weight random map selection.", "Character Preference") as null|anything in sortList(maplist) + if (pickedmap) + preferred_map = maplist[pickedmap] + + if ("clientfps") + var/desiredfps = input(user, "Choose your desired fps. (0 = synced with server tick rate (currently:[world.fps]))", "Character Preference", clientfps) as null|num + if (!isnull(desiredfps)) + clientfps = desiredfps + parent.fps = desiredfps + if("ui") + var/pickedui = input(user, "Choose your UI style.", "Character Preference", UI_style) as null|anything in sortList(GLOB.available_ui_styles) + if(pickedui) + UI_style = pickedui + if (parent && parent.mob && parent.mob.hud_used) + parent.mob.hud_used.update_ui_style(ui_style2icon(UI_style)) + if("pda_style") + var/pickedPDAStyle = input(user, "Choose your PDA style.", "Character Preference", pda_style) as null|anything in GLOB.pda_styles + if(pickedPDAStyle) + pda_style = pickedPDAStyle + if("pda_color") + var/pickedPDAColor = input(user, "Choose your PDA Interface color.", "Character Preference", pda_color) as color|null + if(pickedPDAColor) + pda_color = pickedPDAColor + + if("phobia") + var/phobiaType = input(user, "What are you scared of?", "Character Preference", phobia) as null|anything in SStraumas.phobia_types + if(phobiaType) + phobia = phobiaType + + if ("max_chat_length") + var/desiredlength = input(user, "Choose the max character length of shown Runechat messages. Valid range is 1 to [CHAT_MESSAGE_MAX_LENGTH] (default: [initial(max_chat_length)]))", "Character Preference", max_chat_length) as null|num + if (!isnull(desiredlength)) + max_chat_length = clamp(desiredlength, 1, CHAT_MESSAGE_MAX_LENGTH) + + else + switch(href_list["preference"]) + if("mismatch") + mismatched_customization = !mismatched_customization + + if("adv_colors") + if(allow_advanced_colors) + var/action = alert(user, "Are you sure you want to disable advanced colors (This will reset your colors back to default)?", "", "Yes", "No") + if(action && action != "Yes") + return + allow_advanced_colors = !allow_advanced_colors + if(!allow_advanced_colors) + reset_colors() + + if("publicity") + if(unlock_content) + toggles ^= MEMBER_PUBLIC + if("gender") + var/list/friendlyGenders = list("Male" = "male", "Female" = "female", "Other" = "plural") + var/pickedGender = input(user, "Choose your gender.", "Character Preference", gender) as null|anything in friendlyGenders + if(pickedGender && friendlyGenders[pickedGender] != gender) + gender = friendlyGenders[pickedGender] + //underwear = random_underwear(gender) + //undershirt = random_undershirt(gender) + //socks = random_socks() + //facial_hairstyle = random_facial_hairstyle(gender) + //hairstyle = random_hairstyle(gender) //TODO: this is just a bandaid. Remove those restrictions later + if("body_type") + if(body_type == MALE) + body_type = FEMALE + else + body_type = MALE + if("hotkeys") + hotkeys = !hotkeys + if(hotkeys) + winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]") + else + winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_DISABLED]") + + if("keybindings_capture") + var/datum/keybinding/kb = GLOB.keybindings_by_name[href_list["keybinding"]] + var/old_key = href_list["old_key"] + CaptureKeybinding(user, kb, old_key) + return + + if("keybindings_set") + var/kb_name = href_list["keybinding"] + if(!kb_name) + user << browse(null, "window=capturekeypress") + ShowChoices(user) + return + + var/clear_key = text2num(href_list["clear_key"]) + var/old_key = href_list["old_key"] + if(clear_key) + if(key_bindings[old_key]) + key_bindings[old_key] -= kb_name + if(!length(key_bindings[old_key])) + key_bindings -= old_key + user << browse(null, "window=capturekeypress") + save_preferences() + ShowChoices(user) + return + + var/new_key = uppertext(href_list["key"]) + var/AltMod = text2num(href_list["alt"]) ? "Alt" : "" + var/CtrlMod = text2num(href_list["ctrl"]) ? "Ctrl" : "" + var/ShiftMod = text2num(href_list["shift"]) ? "Shift" : "" + var/numpad = text2num(href_list["numpad"]) ? "Numpad" : "" + // var/key_code = text2num(href_list["key_code"]) + + if(GLOB._kbMap[new_key]) + new_key = GLOB._kbMap[new_key] + + var/full_key + switch(new_key) + if("Alt") + full_key = "[new_key][CtrlMod][ShiftMod]" + if("Ctrl") + full_key = "[AltMod][new_key][ShiftMod]" + if("Shift") + full_key = "[AltMod][CtrlMod][new_key]" + else + full_key = "[AltMod][CtrlMod][ShiftMod][numpad][new_key]" + if(key_bindings[old_key]) + key_bindings[old_key] -= kb_name + if(!length(key_bindings[old_key])) + key_bindings -= old_key + key_bindings[full_key] += list(kb_name) + key_bindings[full_key] = sortList(key_bindings[full_key]) + + user << browse(null, "window=capturekeypress") + user.client.update_movement_keys() + save_preferences() + + if("keybindings_reset") + var/choice = tgalert(user, "Would you prefer 'hotkey' or 'classic' defaults?", "Setup keybindings", "Hotkey", "Classic", "Cancel") + if(choice == "Cancel") + ShowChoices(user) + return + hotkeys = (choice == "Hotkey") + key_bindings = (hotkeys) ? deepCopyList(GLOB.hotkey_keybinding_list_by_key) : deepCopyList(GLOB.classic_keybinding_list_by_key) + user.client.update_movement_keys() + + if("chat_on_map") + chat_on_map = !chat_on_map + if("see_chat_non_mob") + see_chat_non_mob = !see_chat_non_mob + if("see_rc_emotes") + see_rc_emotes = !see_rc_emotes + + if("action_buttons") + buttons_locked = !buttons_locked + if("tgui_fancy") + tgui_fancy = !tgui_fancy + if("tgui_lock") + tgui_lock = !tgui_lock + if("winflash") + windowflashing = !windowflashing + + //here lies the badmins + if("hear_adminhelps") + user.client.toggleadminhelpsound() + if("hear_prayers") + user.client.toggle_prayer_sound() + if("announce_login") + user.client.toggleannouncelogin() + if("combohud_lighting") + toggles ^= COMBOHUD_LIGHTING + if("toggle_dead_chat") + user.client.deadchat() + if("toggle_radio_chatter") + user.client.toggle_hear_radio() + if("toggle_prayers") + user.client.toggleprayers() + if("toggle_deadmin_always") + toggles ^= DEADMIN_ALWAYS + if("toggle_deadmin_antag") + toggles ^= DEADMIN_ANTAGONIST + if("toggle_deadmin_head") + toggles ^= DEADMIN_POSITION_HEAD + if("toggle_deadmin_security") + toggles ^= DEADMIN_POSITION_SECURITY + if("toggle_deadmin_silicon") + toggles ^= DEADMIN_POSITION_SILICON + if("toggle_ignore_cult_ghost") + toggles ^= ADMIN_IGNORE_CULT_GHOST + + + if("be_special") + var/be_special_type = href_list["be_special_type"] + if(be_special_type in be_special) + be_special -= be_special_type + else + be_special += be_special_type + + if("toggle_random") + var/random_type = href_list["random_type"] + if(randomise[random_type]) + randomise -= random_type + else + randomise[random_type] = TRUE + + if("persistent_scars") + persistent_scars = !persistent_scars + + if("clear_scars") + to_chat(user, "All scar slots cleared. Please save character to confirm.") + scars_list["1"] = "" + scars_list["2"] = "" + scars_list["3"] = "" + scars_list["4"] = "" + scars_list["5"] = "" + + if("hear_midis") + toggles ^= SOUND_MIDI + + if("lobby_music") + toggles ^= SOUND_LOBBY + if((toggles & SOUND_LOBBY) && user.client && isnewplayer(user)) + user.client.playtitlemusic() + else + user.stop_sound_channel(CHANNEL_LOBBYMUSIC) + + if("endofround_sounds") + toggles ^= SOUND_ENDOFROUND + + if("ghost_ears") + chat_toggles ^= CHAT_GHOSTEARS + + if("ghost_sight") + chat_toggles ^= CHAT_GHOSTSIGHT + + if("ghost_whispers") + chat_toggles ^= CHAT_GHOSTWHISPER + + if("ghost_radio") + chat_toggles ^= CHAT_GHOSTRADIO + + if("ghost_pda") + chat_toggles ^= CHAT_GHOSTPDA + + if("ghost_laws") + chat_toggles ^= CHAT_GHOSTLAWS + + if("income_pings") + chat_toggles ^= CHAT_BANKCARD + + if("pull_requests") + chat_toggles ^= CHAT_PULLR + + if("allow_midround_antag") + toggles ^= MIDROUND_ANTAG + + if("parallaxup") + parallax = WRAP(parallax + 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1) + if (parent && parent.mob && parent.mob.hud_used) + parent.mob.hud_used.update_parallax_pref(parent.mob) + + if("parallaxdown") + parallax = WRAP(parallax - 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1) + if (parent && parent.mob && parent.mob.hud_used) + parent.mob.hud_used.update_parallax_pref(parent.mob) + + if("ambientocclusion") + ambientocclusion = !ambientocclusion + if(parent && parent.screen && parent.screen.len) + var/obj/screen/plane_master/game_world/PM = locate(/obj/screen/plane_master/game_world) in parent.screen + PM.backdrop(parent.mob) + + if("auto_fit_viewport") + auto_fit_viewport = !auto_fit_viewport + if(auto_fit_viewport && parent) + parent.fit_viewport() + + if("widescreenpref") + widescreenpref = !widescreenpref + user.client.view_size.setDefault(getScreenSize(widescreenpref)) + + if("pixel_size") + switch(pixel_size) + if(PIXEL_SCALING_AUTO) + pixel_size = PIXEL_SCALING_1X + if(PIXEL_SCALING_1X) + pixel_size = PIXEL_SCALING_1_2X + if(PIXEL_SCALING_1_2X) + pixel_size = PIXEL_SCALING_2X + if(PIXEL_SCALING_2X) + pixel_size = PIXEL_SCALING_3X + if(PIXEL_SCALING_3X) + pixel_size = PIXEL_SCALING_AUTO + user.client.view_size.apply() //Let's winset() it so it actually works + + if("scaling_method") + switch(scaling_method) + if(SCALING_METHOD_NORMAL) + scaling_method = SCALING_METHOD_DISTORT + if(SCALING_METHOD_DISTORT) + scaling_method = SCALING_METHOD_BLUR + if(SCALING_METHOD_BLUR) + scaling_method = SCALING_METHOD_NORMAL + user.client.view_size.setZoomMode() + + if("save") + save_preferences() + save_character() + + if("load") + load_preferences() + load_character() + + if("changeslot") + if(!load_character(text2num(href_list["num"]))) + random_character() + real_name = random_unique_name(gender) + save_character() + + if("tab") + if (href_list["tab"]) + current_tab = text2num(href_list["tab"]) + + if("character_preview") + preview_pref = href_list["tab"] + + if("character_tab") + if (href_list["tab"]) + character_settings_tab = text2num(href_list["tab"]) + if(character_settings_tab == 4) //If we click the loadout tab, load in the defaults stuff + var/list/cats = GLOB.loadout_category_to_subcategory_to_items + for(var/category in cats) + loadout_category = category + break + var/list/subs = GLOB.loadout_category_to_subcategory_to_items[loadout_category] + for(var/subcat in subs) + loadout_subcategory = subcat + break + + if("loadout_cat") + if (href_list["tab"]) + loadout_category = href_list["tab"] + var/list/subs = GLOB.loadout_category_to_subcategory_to_items[loadout_category] + for(var/subcat in subs) + loadout_subcategory = subcat + break + + if("loadout_subcat") + if (href_list["tab"]) + loadout_subcategory = href_list["tab"] + + if("clear_heart") + hearted = FALSE + hearted_until = null + to_chat(user, "OOC Commendation Heart disabled") + save_preferences() + + ShowChoices(user) + return 1 + +/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1, roundstart_checks = TRUE, character_setup = FALSE, antagonist = FALSE, is_latejoiner = TRUE) + + hardcore_survival_score = 0 //Set to 0 to prevent you getting points from last another time. + + /*if((randomise[RANDOM_SPECIES] || randomise[RANDOM_HARDCORE]) && !character_setup) + + random_species() + + if((randomise[RANDOM_BODY] || (randomise[RANDOM_BODY_ANTAG] && antagonist) || randomise[RANDOM_HARDCORE]) && !character_setup) + slot_randomized = TRUE + random_character(gender, antagonist) + + if((randomise[RANDOM_NAME] || (randomise[RANDOM_NAME_ANTAG] && antagonist) || randomise[RANDOM_HARDCORE]) && !character_setup) + slot_randomized = TRUE + real_name = pref_species.random_name(gender) + + if(randomise[RANDOM_HARDCORE] && parent.mob.mind && !character_setup) + if(can_be_random_hardcore()) + hardcore_random_setup(character, antagonist, is_latejoiner)*/ + + if(roundstart_checks) + if(CONFIG_GET(flag/humans_need_surnames) && (pref_species.id == "human")) + var/firstspace = findtext(real_name, " ") + var/name_length = length(real_name) + if(!firstspace) //we need a surname + real_name += " [pick(GLOB.last_names)]" + else if(firstspace == name_length) + real_name += "[pick(GLOB.last_names)]" + + character.real_name = real_name + character.name = character.real_name + + character.gender = gender + character.age = age + if(gender == MALE || gender == FEMALE) + character.body_type = gender + else + character.body_type = body_type + + character.eye_color = eye_color + var/obj/item/organ/eyes/organ_eyes = character.getorgan(/obj/item/organ/eyes) + if(organ_eyes) + if(!initial(organ_eyes.eye_color)) + organ_eyes.eye_color = eye_color + organ_eyes.old_eye_color = eye_color + character.hair_color = hair_color + character.facial_hair_color = facial_hair_color + + character.skin_tone = skin_tone + character.hairstyle = hairstyle + character.facial_hairstyle = facial_hairstyle + character.underwear = underwear + character.underwear_color = underwear_color + character.undershirt = undershirt + character.undershirt_color = undershirt_color + character.socks = socks + character.socks_color = socks_color + + character.backpack = backpack + + character.jumpsuit_style = jumpsuit_style + + var/datum/species/chosen_species + chosen_species = pref_species.type + if(roundstart_checks && !(pref_species.id in GLOB.roundstart_races) && !(pref_species.id in (CONFIG_GET(keyed_list/roundstart_no_hard_check)))) + chosen_species = /datum/species/human + set_new_species(/datum/species/human) + save_character() + + character.set_species(chosen_species, icon_update = FALSE, pref_load = src) + + /*if("tail_lizard" in pref_species.default_features) + character.dna.species.mutant_bodyparts |= "tail_lizard"*/ + + if(icon_updates) + character.update_body() + character.update_hair() + character.update_body_parts() + +/datum/preferences/proc/can_be_random_hardcore() + if(parent.mob.mind.assigned_role in GLOB.command_positions) //No command staff + return FALSE + for(var/A in parent.mob.mind.antag_datums) + var/datum/antagonist/antag + if(antag.get_team()) //No team antags + return FALSE + return TRUE + +/datum/preferences/proc/get_default_name(name_id) + switch(name_id) + if("human") + return random_unique_name() + if("ai") + return pick(GLOB.ai_names) + if("cyborg") + return DEFAULT_CYBORG_NAME + if("clown") + return pick(GLOB.clown_names) + if("mime") + return pick(GLOB.mime_names) + if("religion") + return DEFAULT_RELIGION + if("deity") + return DEFAULT_DEITY + return random_unique_name() + +/datum/preferences/proc/ask_for_custom_name(mob/user,name_id) + var/namedata = GLOB.preferences_custom_names[name_id] + if(!namedata) + return + + var/raw_name = input(user, "Choose your character's [namedata["qdesc"]]:","Character Preference") as text|null + if(!raw_name) + if(namedata["allow_null"]) + custom_names[name_id] = get_default_name(name_id) + else + return + else + var/sanitized_name = reject_bad_name(raw_name,namedata["allow_numbers"]) + if(!sanitized_name) + to_chat(user, "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z,[namedata["allow_numbers"] ? ",0-9," : ""] -, ' and .") + return + else + custom_names[name_id] = sanitized_name + +/datum/preferences/proc/print_bodypart_change_line(key) + var/acc_name = mutant_bodyparts[key][MUTANT_INDEX_NAME] + var/shown_colors = 0 + var/datum/sprite_accessory/SA = GLOB.sprite_accessories[key][acc_name] + var/dat = "" + if(SA.color_src == USE_MATRIXED_COLORS) + shown_colors = 3 + else if (SA.color_src == USE_ONE_COLOR) + shown_colors = 1 + if((allow_advanced_colors || SA.always_color_customizable) && shown_colors) + dat += "R" + dat += "[acc_name]" + if(allow_advanced_colors || SA.always_color_customizable) + if(shown_colors) + var/list/colorlist = mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] + for(var/i in 1 to shown_colors) + dat += "    Set" + return dat + +/datum/preferences/proc/set_skin_tone(new_skin_tone) + skin_tone = new_skin_tone + features["skin_color"] = sanitize_hexcolor(skintone2hex(skin_tone), 3, 0) + if(!allow_advanced_colors) + reset_colors() diff --git a/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm b/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm new file mode 100644 index 00000000000..750af438dfa --- /dev/null +++ b/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm @@ -0,0 +1,605 @@ +//This is the lowest supported version, anything below this is completely obsolete and the entire savefile will be wiped. +#define SAVEFILE_VERSION_MIN 32 + +//This is the current version, anything below this will attempt to update (if it's not obsolete) +// You do not need to raise this if you are adding new values that have sane defaults. +// Only raise this value when changing the meaning/format/name/layout of an existing value +// where you would want the updater procs below to run +#define SAVEFILE_VERSION_MAX 36 + +/* +SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn + This proc checks if the current directory of the savefile S needs updating + It is to be used by the load_character and load_preferences procs. + (S.cd=="/" is preferences, S.cd=="/character[integer]" is a character slot, etc) + + if the current directory's version is below SAVEFILE_VERSION_MIN it will simply wipe everything in that directory + (if we're at root "/" then it'll just wipe the entire savefile, for instance.) + + if its version is below SAVEFILE_VERSION_MAX but above the minimum, it will load data but later call the + respective update_preferences() or update_character() proc. + Those procs allow coders to specify format changes so users do not lose their setups and have to redo them again. + + Failing all that, the standard sanity checks are performed. They simply check the data is suitable, reverting to + initial() values if necessary. +*/ +/datum/preferences/proc/savefile_needs_update(savefile/S) + var/savefile_version + READ_FILE(S["version"], savefile_version) + + if(savefile_version < SAVEFILE_VERSION_MIN) + S.dir.Cut() + return -2 + if(savefile_version < SAVEFILE_VERSION_MAX) + return savefile_version + return -1 + +//should these procs get fairly long +//just increase SAVEFILE_VERSION_MIN so it's not as far behind +//SAVEFILE_VERSION_MAX and then delete any obsolete if clauses +//from these procs. +//This only really meant to avoid annoying frequent players +//if your savefile is 3 months out of date, then 'tough shit'. + +/datum/preferences/proc/update_preferences(current_version, savefile/S) + if(current_version < 33) + toggles |= SOUND_ENDOFROUND + + if(current_version < 34) + auto_fit_viewport = TRUE + + if(current_version < 35) //makes old keybinds compatible with #52040, sets the new default + var/newkey = FALSE + for(var/list/key in key_bindings) + for(var/bind in key) + if(bind == "quick_equipbelt") + key -= "quick_equipbelt" + key |= "quick_equip_belt" + + if(bind == "bag_equip") + key -= "bag_equip" + key |= "quick_equip_bag" + + if(bind == "quick_equip_suit_storage") + newkey = TRUE + if(!newkey && !key_bindings["ShiftQ"]) + key_bindings["ShiftQ"] = list("quick_equip_suit_storage") + + if(current_version < 36) + if(key_bindings["ShiftQ"] == "quick_equip_suit_storage") + key_bindings["ShiftQ"] = list("quick_equip_suit_storage") + + +/datum/preferences/proc/update_character(current_version, savefile/S) + return + +/datum/preferences/proc/load_path(ckey,filename="preferences.sav") + if(!ckey) + return + path = "data/player_saves/[ckey[1]]/[ckey]/[filename]" + +/datum/preferences/proc/load_preferences() + if(!path) + return FALSE + if(!fexists(path)) + return FALSE + + var/savefile/S = new /savefile(path) + if(!S) + return FALSE + S.cd = "/" + + var/needs_update = savefile_needs_update(S) + if(needs_update == -2) //fatal, can't load any data + return FALSE + + //general preferences + READ_FILE(S["asaycolor"], asaycolor) + READ_FILE(S["ooccolor"], ooccolor) + READ_FILE(S["lastchangelog"], lastchangelog) + READ_FILE(S["UI_style"], UI_style) + READ_FILE(S["hotkeys"], hotkeys) + READ_FILE(S["chat_on_map"], chat_on_map) + READ_FILE(S["max_chat_length"], max_chat_length) + READ_FILE(S["see_chat_non_mob"] , see_chat_non_mob) + READ_FILE(S["see_rc_emotes"] , see_rc_emotes) + READ_FILE(S["tgui_fancy"], tgui_fancy) + READ_FILE(S["tgui_lock"], tgui_lock) + READ_FILE(S["buttons_locked"], buttons_locked) + READ_FILE(S["windowflash"], windowflashing) + READ_FILE(S["be_special"] , be_special) + + + READ_FILE(S["default_slot"], default_slot) + READ_FILE(S["chat_toggles"], chat_toggles) + READ_FILE(S["toggles"], toggles) + READ_FILE(S["ghost_form"], ghost_form) + READ_FILE(S["ghost_orbit"], ghost_orbit) + READ_FILE(S["ghost_accs"], ghost_accs) + READ_FILE(S["ghost_others"], ghost_others) + READ_FILE(S["preferred_map"], preferred_map) + READ_FILE(S["ignoring"], ignoring) + READ_FILE(S["ghost_hud"], ghost_hud) + READ_FILE(S["inquisitive_ghost"], inquisitive_ghost) + READ_FILE(S["uses_glasses_colour"], uses_glasses_colour) + READ_FILE(S["clientfps"], clientfps) + READ_FILE(S["parallax"], parallax) + READ_FILE(S["ambientocclusion"], ambientocclusion) + READ_FILE(S["auto_fit_viewport"], auto_fit_viewport) + READ_FILE(S["widescreenpref"], widescreenpref) + READ_FILE(S["pixel_size"], pixel_size) + READ_FILE(S["scaling_method"], scaling_method) + READ_FILE(S["menuoptions"], menuoptions) + READ_FILE(S["enable_tips"], enable_tips) + READ_FILE(S["tip_delay"], tip_delay) + READ_FILE(S["pda_style"], pda_style) + READ_FILE(S["pda_color"], pda_color) + + // Custom hotkeys + READ_FILE(S["key_bindings"], key_bindings) + // hearted + READ_FILE(S["hearted_until"], hearted_until) + if(hearted_until > world.realtime) + hearted = TRUE + + //try to fix any outdated data if necessary + if(needs_update >= 0) + update_preferences(needs_update, S) //needs_update = savefile_version if we need an update (positive integer) + + //Sanitize + asaycolor = sanitize_ooccolor(sanitize_hexcolor(asaycolor, 6, 1, initial(asaycolor))) + ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor))) + lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) + UI_style = sanitize_inlist(UI_style, GLOB.available_ui_styles, GLOB.available_ui_styles[1]) + hotkeys = sanitize_integer(hotkeys, FALSE, TRUE, initial(hotkeys)) + chat_on_map = sanitize_integer(chat_on_map, FALSE, TRUE, initial(chat_on_map)) + max_chat_length = sanitize_integer(max_chat_length, 1, CHAT_MESSAGE_MAX_LENGTH, initial(max_chat_length)) + see_chat_non_mob = sanitize_integer(see_chat_non_mob, FALSE, TRUE, initial(see_chat_non_mob)) + see_rc_emotes = sanitize_integer(see_rc_emotes, FALSE, TRUE, initial(see_rc_emotes)) + tgui_fancy = sanitize_integer(tgui_fancy, FALSE, TRUE, initial(tgui_fancy)) + tgui_lock = sanitize_integer(tgui_lock, FALSE, TRUE, initial(tgui_lock)) + buttons_locked = sanitize_integer(buttons_locked, FALSE, TRUE, initial(buttons_locked)) + windowflashing = sanitize_integer(windowflashing, FALSE, TRUE, initial(windowflashing)) + default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot)) + toggles = sanitize_integer(toggles, 0, (2**24)-1, initial(toggles)) + clientfps = sanitize_integer(clientfps, 0, 1000, 0) + parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null) + ambientocclusion = sanitize_integer(ambientocclusion, FALSE, TRUE, initial(ambientocclusion)) + auto_fit_viewport = sanitize_integer(auto_fit_viewport, FALSE, TRUE, initial(auto_fit_viewport)) + widescreenpref = sanitize_integer(widescreenpref, FALSE, TRUE, initial(widescreenpref)) + pixel_size = sanitize_integer(pixel_size, PIXEL_SCALING_AUTO, PIXEL_SCALING_3X, initial(pixel_size)) + scaling_method = sanitize_text(scaling_method, initial(scaling_method)) + ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form)) + ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit)) + ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION) + ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION) + menuoptions = SANITIZE_LIST(menuoptions) + be_special = SANITIZE_LIST(be_special) + pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style)) + pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color)) + key_bindings = sanitize_keybindings(key_bindings) + + + return TRUE + +/datum/preferences/proc/save_preferences() + if(!path) + return FALSE + var/savefile/S = new /savefile(path) + if(!S) + return FALSE + S.cd = "/" + + WRITE_FILE(S["version"] , SAVEFILE_VERSION_MAX) //updates (or failing that the sanity checks) will ensure data is not invalid at load. Assume up-to-date + + //general preferences + WRITE_FILE(S["asaycolor"], asaycolor) + WRITE_FILE(S["ooccolor"], ooccolor) + WRITE_FILE(S["lastchangelog"], lastchangelog) + WRITE_FILE(S["UI_style"], UI_style) + WRITE_FILE(S["hotkeys"], hotkeys) + WRITE_FILE(S["chat_on_map"], chat_on_map) + WRITE_FILE(S["max_chat_length"], max_chat_length) + WRITE_FILE(S["see_chat_non_mob"], see_chat_non_mob) + WRITE_FILE(S["see_rc_emotes"], see_rc_emotes) + WRITE_FILE(S["tgui_fancy"], tgui_fancy) + WRITE_FILE(S["tgui_lock"], tgui_lock) + WRITE_FILE(S["buttons_locked"], buttons_locked) + WRITE_FILE(S["windowflash"], windowflashing) + WRITE_FILE(S["be_special"], be_special) + WRITE_FILE(S["default_slot"], default_slot) + WRITE_FILE(S["toggles"], toggles) + WRITE_FILE(S["chat_toggles"], chat_toggles) + WRITE_FILE(S["ghost_form"], ghost_form) + WRITE_FILE(S["ghost_orbit"], ghost_orbit) + WRITE_FILE(S["ghost_accs"], ghost_accs) + WRITE_FILE(S["ghost_others"], ghost_others) + WRITE_FILE(S["preferred_map"], preferred_map) + WRITE_FILE(S["ignoring"], ignoring) + WRITE_FILE(S["ghost_hud"], ghost_hud) + WRITE_FILE(S["inquisitive_ghost"], inquisitive_ghost) + WRITE_FILE(S["uses_glasses_colour"], uses_glasses_colour) + WRITE_FILE(S["clientfps"], clientfps) + WRITE_FILE(S["parallax"], parallax) + WRITE_FILE(S["ambientocclusion"], ambientocclusion) + WRITE_FILE(S["auto_fit_viewport"], auto_fit_viewport) + WRITE_FILE(S["widescreenpref"], widescreenpref) + WRITE_FILE(S["pixel_size"], pixel_size) + WRITE_FILE(S["scaling_method"], scaling_method) + WRITE_FILE(S["menuoptions"], menuoptions) + WRITE_FILE(S["enable_tips"], enable_tips) + WRITE_FILE(S["tip_delay"], tip_delay) + WRITE_FILE(S["pda_style"], pda_style) + WRITE_FILE(S["pda_color"], pda_color) + WRITE_FILE(S["key_bindings"], key_bindings) + WRITE_FILE(S["hearted_until"], (hearted_until > world.realtime ? hearted_until : null)) + return TRUE + +/datum/preferences/proc/load_character(slot) + if(!path) + return FALSE + if(!fexists(path)) + return FALSE + var/savefile/S = new /savefile(path) + if(!S) + return FALSE + S.cd = "/" + if(!slot) + slot = default_slot + slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot)) + if(slot != default_slot) + default_slot = slot + WRITE_FILE(S["default_slot"] , slot) + + S.cd = "/character[slot]" + var/needs_update = savefile_needs_update(S) + if(needs_update == -2) //fatal, can't load any data + return FALSE + + //Species + var/species_id + READ_FILE(S["species"], species_id) + if(species_id) + var/newtype = GLOB.species_list[species_id] + if(newtype) + pref_species = new newtype + + scars_index = rand(1,5) + + /*if(!S["features["mcolor"]"] || S["features["mcolor"]"] == "#000") + WRITE_FILE(S["features["mcolor"]"] , "#FFF") + + if(!S["feature_ethcolor"] || S["feature_ethcolor"] == "#000") + WRITE_FILE(S["feature_ethcolor"] , "9c3030")*/ + + //Character + READ_FILE(S["real_name"], real_name) + READ_FILE(S["gender"], gender) + READ_FILE(S["body_type"], body_type) + READ_FILE(S["age"], age) + READ_FILE(S["hair_color"], hair_color) + READ_FILE(S["facial_hair_color"], facial_hair_color) + READ_FILE(S["eye_color"], eye_color) + READ_FILE(S["skin_tone"], skin_tone) + READ_FILE(S["hairstyle_name"], hairstyle) + READ_FILE(S["facial_style_name"], facial_hairstyle) + READ_FILE(S["underwear"], underwear) + READ_FILE(S["underwear_color"], underwear_color) + READ_FILE(S["undershirt"], undershirt) + READ_FILE(S["socks"], socks) + READ_FILE(S["backpack"], backpack) + READ_FILE(S["jumpsuit_style"], jumpsuit_style) + READ_FILE(S["uplink_loc"], uplink_spawn_loc) + READ_FILE(S["playtime_reward_cloak"], playtime_reward_cloak) + READ_FILE(S["phobia"], phobia) + READ_FILE(S["randomise"], randomise) + /*READ_FILE(S["feature_mcolor"], features["mcolor"]) + READ_FILE(S["feature_ethcolor"], features["ethcolor"]) + READ_FILE(S["feature_lizard_tail"], features["tail_lizard"]) + READ_FILE(S["feature_lizard_snout"], features["snout"]) + READ_FILE(S["feature_lizard_horns"], features["horns"]) + READ_FILE(S["feature_lizard_frills"], features["frills"]) + READ_FILE(S["feature_lizard_spines"], features["spines"]) + READ_FILE(S["feature_lizard_body_markings"], features["body_markings"]) + READ_FILE(S["feature_lizard_legs"], features["legs"]) + READ_FILE(S["feature_moth_wings"], features["moth_wings"]) + READ_FILE(S["feature_moth_markings"], features["moth_markings"])*/ + READ_FILE(S["persistent_scars"] , persistent_scars) + READ_FILE(S["scars1"], scars_list["1"]) + READ_FILE(S["scars2"], scars_list["2"]) + READ_FILE(S["scars3"], scars_list["3"]) + READ_FILE(S["scars4"], scars_list["4"]) + READ_FILE(S["scars5"], scars_list["5"]) + /*if(!CONFIG_GET(flag/join_with_mutant_humans)) + features["tail_human"] = "none" + features["ears"] = "none" + else + READ_FILE(S["feature_human_tail"], features["tail_human"]) + READ_FILE(S["feature_human_ears"], features["ears"])*/ + + //Custom names + for(var/custom_name_id in GLOB.preferences_custom_names) + var/savefile_slot_name = custom_name_id + "_name" //TODO remove this + READ_FILE(S[savefile_slot_name], custom_names[custom_name_id]) + + READ_FILE(S["preferred_ai_core_display"], preferred_ai_core_display) + READ_FILE(S["prefered_security_department"], prefered_security_department) + + //Jobs + READ_FILE(S["joblessrole"], joblessrole) + //Load prefs + READ_FILE(S["job_preferences"], job_preferences) + + //Quirks + READ_FILE(S["all_quirks"], all_quirks) + + //try to fix any outdated data if necessary + if(needs_update >= 0) + update_character(needs_update, S) //needs_update == savefile_version if we need an update (positive integer) + + //Sanitize + + real_name = reject_bad_name(real_name) + gender = sanitize_gender(gender) + body_type = sanitize_gender(body_type, FALSE, FALSE, gender) + if(!real_name) + real_name = random_unique_name(gender) + + for(var/custom_name_id in GLOB.preferences_custom_names) + var/namedata = GLOB.preferences_custom_names[custom_name_id] + custom_names[custom_name_id] = reject_bad_name(custom_names[custom_name_id],namedata["allow_numbers"]) + if(!custom_names[custom_name_id]) + custom_names[custom_name_id] = get_default_name(custom_name_id) + + /*if(!features["mcolor"] || features["mcolor"] == "#000") + features["mcolor"] = pick("FFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F") + + if(!features["ethcolor"] || features["ethcolor"] == "#000") + features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)]*/ + + randomise = SANITIZE_LIST(randomise) + + if(gender == MALE) + hairstyle = sanitize_inlist(hairstyle, GLOB.hairstyles_male_list) + facial_hairstyle = sanitize_inlist(facial_hairstyle, GLOB.facial_hairstyles_male_list) + underwear = sanitize_inlist(underwear, GLOB.underwear_m) + undershirt = sanitize_inlist(undershirt, GLOB.undershirt_m) + else if(gender == FEMALE) + hairstyle = sanitize_inlist(hairstyle, GLOB.hairstyles_female_list) + facial_hairstyle = sanitize_inlist(facial_hairstyle, GLOB.facial_hairstyles_female_list) + underwear = sanitize_inlist(underwear, GLOB.underwear_f) + undershirt = sanitize_inlist(undershirt, GLOB.undershirt_f) + else + hairstyle = sanitize_inlist(hairstyle, GLOB.hairstyles_list) + facial_hairstyle = sanitize_inlist(facial_hairstyle, GLOB.facial_hairstyles_list) + underwear = sanitize_inlist(underwear, GLOB.underwear_list) + undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list) + + socks = sanitize_inlist(socks, GLOB.socks_list) + age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) + hair_color = sanitize_hexcolor(hair_color, 3, 0) + facial_hair_color = sanitize_hexcolor(facial_hair_color, 3, 0) + underwear_color = sanitize_hexcolor(underwear_color, 3, 0) + eye_color = sanitize_hexcolor(eye_color, 3, 0) + skin_tone = sanitize_inlist(skin_tone, GLOB.skin_tones) + backpack = sanitize_inlist(backpack, GLOB.backpacklist, initial(backpack)) + jumpsuit_style = sanitize_inlist(jumpsuit_style, GLOB.jumpsuitlist, initial(jumpsuit_style)) + uplink_spawn_loc = sanitize_inlist(uplink_spawn_loc, GLOB.uplink_spawn_loc_list, initial(uplink_spawn_loc)) + playtime_reward_cloak = sanitize_integer(playtime_reward_cloak) + /*features["mcolor"] = sanitize_hexcolor(features["mcolor"], 3, 0) SKYRAT EDIT + features["ethcolor"] = copytext_char(features["ethcolor"], 1, 7) + features["tail_lizard"] = sanitize_inlist(features["tail_lizard"], GLOB.tails_list_lizard) + features["tail_human"] = sanitize_inlist(features["tail_human"], GLOB.tails_list_human, "None") + features["snout"] = sanitize_inlist(features["snout"], GLOB.snouts_list) + features["horns"] = sanitize_inlist(features["horns"], GLOB.horns_list) + features["ears"] = sanitize_inlist(features["ears"], GLOB.ears_list, "None") + features["frills"] = sanitize_inlist(features["frills"], GLOB.frills_list) + features["spines"] = sanitize_inlist(features["spines"], GLOB.spines_list) + features["body_markings"] = sanitize_inlist(features["body_markings"], GLOB.body_markings_list) + features["feature_lizard_legs"] = sanitize_inlist(features["legs"], GLOB.legs_list, "Normal Legs") + features["moth_wings"] = sanitize_inlist(features["moth_wings"], GLOB.moth_wings_list, "Plain") + features["moth_markings"] = sanitize_inlist(features["moth_markings"], GLOB.moth_markings_list, "None")*/ + + persistent_scars = sanitize_integer(persistent_scars) + scars_list["1"] = sanitize_text(scars_list["1"]) + scars_list["2"] = sanitize_text(scars_list["2"]) + scars_list["3"] = sanitize_text(scars_list["3"]) + scars_list["4"] = sanitize_text(scars_list["4"]) + scars_list["5"] = sanitize_text(scars_list["5"]) + + joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole)) + //Validate job prefs + for(var/j in job_preferences) + if(job_preferences[j] != JP_LOW && job_preferences[j] != JP_MEDIUM && job_preferences[j] != JP_HIGH) + job_preferences -= j + + all_quirks = SANITIZE_LIST(all_quirks) + + //All the new skyrat related stuff here + READ_FILE(S["features"], features) + READ_FILE(S["mutant_bodyparts"], mutant_bodyparts) + READ_FILE(S["body_markings"], body_markings) + + READ_FILE(S["loadout"], loadout) + + READ_FILE(S["ooc_prefs"], ooc_prefs) + READ_FILE(S["erp_pref"], erp_pref) + READ_FILE(S["noncon_pref"], noncon_pref) + READ_FILE(S["vore_pref"], vore_pref) + READ_FILE(S["general_record"], general_record) + READ_FILE(S["security_record"], security_record) + READ_FILE(S["medical_record"], medical_record) + READ_FILE(S["background_info"], background_info) + READ_FILE(S["exploitable_info"], exploitable_info) + + READ_FILE(S["mismatched_customization"] , mismatched_customization) + READ_FILE(S["allow_advanced_colors"] , allow_advanced_colors) + + features = SANITIZE_LIST(features) + mutant_bodyparts = SANITIZE_LIST(mutant_bodyparts) + body_markings = SANITIZE_LIST(body_markings) + + loadout = SANITIZE_LIST(loadout) + //LOADOUT POINT VALIDATION + //Here we calculate if we truly can use the loaded loadout + loadout_points = initial(loadout_points) + var/accumulated_cost = 0 + for(var/path in loadout) + var/datum/loadout_item/LI = GLOB.loadout_items[path] + if(!LI) + loadout -= path + continue + accumulated_cost += LI.cost + if(accumulated_cost > loadout_points) //Not enough points, reset loadout + loadout = list() + else + loadout_points -= accumulated_cost //We got enough points, subtract the cost + + ooc_prefs = sanitize_text(ooc_prefs) + if(!length(erp_pref)) + erp_pref = "Ask" + if(!length(noncon_pref)) + noncon_pref = "Ask" + if(!length(vore_pref)) + vore_pref = "Ask" + + general_record = sanitize_text(general_record) + security_record = sanitize_text(security_record) + medical_record = sanitize_text(medical_record) + background_info = sanitize_text(background_info) + exploitable_info = sanitize_text(exploitable_info) + + mismatched_customization = sanitize_integer(mismatched_customization, FALSE, TRUE, initial(mismatched_customization)) + allow_advanced_colors = sanitize_integer(allow_advanced_colors, FALSE, TRUE, initial(allow_advanced_colors)) + + //Validating mandatory features + for(var/key in MANDATORY_FEATURE_LIST) + if(!features[key]) + features[key] = MANDATORY_FEATURE_LIST[key] + + //validating body markings + for(var/zone in body_markings) + for(var/name in body_markings[zone]) + if(!(name in GLOB.body_markings_per_limb[zone])) + body_markings[zone] -= name + + validate_species_parts() + + return TRUE + +/datum/preferences/proc/save_character() + if(!path) + return FALSE + var/savefile/S = new /savefile(path) + if(!S) + return FALSE + S.cd = "/character[default_slot]" + + WRITE_FILE(S["version"] , SAVEFILE_VERSION_MAX) //load_character will sanitize any bad data, so assume up-to-date.) + + //Character + WRITE_FILE(S["real_name"] , real_name) + WRITE_FILE(S["gender"] , gender) + WRITE_FILE(S["body_type"] , body_type) + WRITE_FILE(S["age"] , age) + WRITE_FILE(S["hair_color"] , hair_color) + WRITE_FILE(S["facial_hair_color"] , facial_hair_color) + WRITE_FILE(S["eye_color"] , eye_color) + WRITE_FILE(S["skin_tone"] , skin_tone) + WRITE_FILE(S["hairstyle_name"] , hairstyle) + WRITE_FILE(S["facial_style_name"] , facial_hairstyle) + WRITE_FILE(S["underwear"] , underwear) + WRITE_FILE(S["underwear_color"] , underwear_color) + WRITE_FILE(S["undershirt"] , undershirt) + WRITE_FILE(S["socks"] , socks) + WRITE_FILE(S["backpack"] , backpack) + WRITE_FILE(S["jumpsuit_style"] , jumpsuit_style) + WRITE_FILE(S["uplink_loc"] , uplink_spawn_loc) + WRITE_FILE(S["playtime_reward_cloak"] , playtime_reward_cloak) + WRITE_FILE(S["randomise"] , randomise) + WRITE_FILE(S["species"] , pref_species.id) + WRITE_FILE(S["phobia"], phobia) + /*WRITE_FILE(S["feature_mcolor"] , features["mcolor"]) + WRITE_FILE(S["feature_ethcolor"] , features["ethcolor"]) + WRITE_FILE(S["feature_lizard_tail"] , features["tail_lizard"]) + WRITE_FILE(S["feature_human_tail"] , features["tail_human"]) + WRITE_FILE(S["feature_lizard_snout"] , features["snout"]) + WRITE_FILE(S["feature_lizard_horns"] , features["horns"]) + WRITE_FILE(S["feature_human_ears"] , features["ears"]) + WRITE_FILE(S["feature_lizard_frills"] , features["frills"]) + WRITE_FILE(S["feature_lizard_spines"] , features["spines"]) + WRITE_FILE(S["feature_lizard_body_markings"] , features["body_markings"]) + WRITE_FILE(S["feature_lizard_legs"] , features["legs"]) + WRITE_FILE(S["feature_moth_wings"] , features["moth_wings"]) + WRITE_FILE(S["feature_moth_markings"] , features["moth_markings"])*/ + WRITE_FILE(S["persistent_scars"] , persistent_scars) + WRITE_FILE(S["scars1"] , scars_list["1"]) + WRITE_FILE(S["scars2"] , scars_list["2"]) + WRITE_FILE(S["scars3"] , scars_list["3"]) + WRITE_FILE(S["scars4"] , scars_list["4"]) + WRITE_FILE(S["scars5"] , scars_list["5"]) + + + //Custom names + for(var/custom_name_id in GLOB.preferences_custom_names) + var/savefile_slot_name = custom_name_id + "_name" //TODO remove this + WRITE_FILE(S[savefile_slot_name],custom_names[custom_name_id]) + + WRITE_FILE(S["preferred_ai_core_display"] , preferred_ai_core_display) + WRITE_FILE(S["prefered_security_department"] , prefered_security_department) + + //Jobs + WRITE_FILE(S["joblessrole"] , joblessrole) + //Write prefs + WRITE_FILE(S["job_preferences"] , job_preferences) + + //Quirks + WRITE_FILE(S["all_quirks"] , all_quirks) + + //All the new skyrat related stuff here + WRITE_FILE(S["features"] , features) + WRITE_FILE(S["mutant_bodyparts"] , mutant_bodyparts) + WRITE_FILE(S["body_markings"] , body_markings) + + WRITE_FILE(S["loadout"] , loadout) + + WRITE_FILE(S["ooc_prefs"] , ooc_prefs) + WRITE_FILE(S["erp_pref"] , erp_pref) + WRITE_FILE(S["noncon_pref"] , noncon_pref) + WRITE_FILE(S["vore_pref"] , vore_pref) + WRITE_FILE(S["general_record"] , general_record) + WRITE_FILE(S["security_record"] , security_record) + WRITE_FILE(S["medical_record"] , medical_record) + WRITE_FILE(S["background_info"] , background_info) + WRITE_FILE(S["exploitable_info"] , exploitable_info) + + WRITE_FILE(S["mismatched_customization"] , mismatched_customization) + WRITE_FILE(S["allow_advanced_colors"] , allow_advanced_colors) + + return TRUE + + +/proc/sanitize_keybindings(value) + var/list/base_bindings = sanitize_islist(value,list()) + for(var/key in base_bindings) + base_bindings[key] = base_bindings[key] & GLOB.keybindings_by_name + if(!length(base_bindings[key])) + base_bindings -= key + return base_bindings + +#undef SAVEFILE_VERSION_MAX +#undef SAVEFILE_VERSION_MIN + +#ifdef TESTING +//DEBUG +//Some crude tools for testing savefiles +//path is the savefile path +/client/verb/savefile_export(path as text) + var/savefile/S = new /savefile(path) + S.ExportText("/",file("[path].txt")) +//path is the savefile path +/client/verb/savefile_import(path as text) + var/savefile/S = new /savefile(path) + S.ImportText("/",file("[path].txt")) + +#endif diff --git a/modular_skyrat/modules/customization/modules/clothing/clothing.dm b/modular_skyrat/modules/customization/modules/clothing/clothing.dm new file mode 100644 index 00000000000..2fa183ce23a --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/clothing.dm @@ -0,0 +1,187 @@ +/obj/item/clothing + var/mutant_variants = NONE + var/worn_icon_digi + var/worn_icon_taur_snake + var/worn_icon_taur_paw + var/worn_icon_taur_hoof + var/worn_icon_muzzled + +/obj/item/clothing/head + mutant_variants = STYLE_MUZZLE | STYLE_VOX + +/obj/item/clothing/mask + mutant_variants = STYLE_MUZZLE | STYLE_VOX + +/obj/item/clothing/glasses + mutant_variants = STYLE_VOX + +/obj/item/clothing/under + mutant_variants = STYLE_DIGITIGRADE + +/obj/item/clothing/suit + mutant_variants = STYLE_DIGITIGRADE|STYLE_TAUR_ALL + +/obj/item/clothing/shoes + mutant_variants = STYLE_DIGITIGRADE + +/obj/item/clothing/suit/armor + mutant_variants = NONE + +/obj/item/clothing/under/color/jumpskirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/engineering/chief_engineer/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/medical/chief_medical_officer/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/chaplain/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/cargo/qm/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/captain/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/chaplain/skirt + mutant_variants = NONE + +/obj/item/clothing/under/dress + mutant_variants = NONE + +/obj/item/clothing/under/rank/security/officer + mutant_variants = NONE + +/obj/item/clothing/under/suit/black/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/rnd/research_director/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/rnd/research_director/alt + mutant_variants = NONE + +/obj/item/clothing/under/rank/rnd/research_director/turtleneck/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/head_of_personnel/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/security/head_of_security + mutant_variants = NONE + +/obj/item/clothing/under/rank/security/head_of_security/alt/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/security/warden/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/prisoner/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/security/officer/skirt + mutant_variants = NONE + +/obj/item/clothing/under/syndicate/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/cargo/tech/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/bartender/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/chef/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/head_of_personnel/suit/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/hydroponics/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/janitor/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/lawyer/black/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/lawyer/female/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/lawyer/red/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/lawyer/blue/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/lawyer/bluesuit/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/lawyer/purpsuit/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/mime/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/curator/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/engineering/atmospheric_technician/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/engineering/engineer/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/medical/virologist/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/medical/doctor/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/medical/chemist + mutant_variants = NONE + +/obj/item/clothing/under/rank/medical/paramedic/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/rnd/scientist/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/rnd/roboticist/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/rnd/geneticist/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/security/detective/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/security/detective/grey/skirt + mutant_variants = NONE + +/obj/item/clothing/under/suit/white/skirt + mutant_variants = NONE + +/obj/item/clothing/under/suit/black/skirt + mutant_variants = NONE + +/obj/item/clothing/under/suit/black_really/skirt + mutant_variants = NONE + +/obj/item/clothing/under/syndicate/tacticool/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/head_of_personnel/suit/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/head_of_personnel/suit/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/head_of_personnel/suit/skirt + mutant_variants = NONE + +/obj/item/clothing/under/rank/civilian/head_of_personnel/suit/skirt + mutant_variants = NONE diff --git a/modular_skyrat/modules/customization/modules/clothing/ears/ears.dm b/modular_skyrat/modules/customization/modules/clothing/ears/ears.dm new file mode 100644 index 00000000000..8066d0dd458 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/ears/ears.dm @@ -0,0 +1,37 @@ +/obj/item/clothing/ears/headphones + name = "headphones" + desc = "Unce unce unce unce. Boop!" + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/accessories.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/ears.dmi' + icon_state = "headphones" + inhand_icon_state = "headphones" + slot_flags = ITEM_SLOT_EARS | ITEM_SLOT_HEAD | ITEM_SLOT_NECK //Fluff item, put it whereever you want! + actions_types = list(/datum/action/item_action/toggle_headphones) + var/headphones_on = FALSE + custom_price = 60 + +/obj/item/clothing/ears/headphones/Initialize() + . = ..() + update_icon() + +/obj/item/clothing/ears/headphones/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/clothing/ears/headphones/update_icon_state() + icon_state = "[initial(icon_state)]_[headphones_on? "on" : "off"]" + inhand_icon_state = "[initial(inhand_icon_state)]_[headphones_on? "on" : "off"]" + +/obj/item/clothing/ears/headphones/proc/toggle(owner) + headphones_on = !headphones_on + update_icon() + to_chat(owner, "You turn the music [headphones_on? "on. Untz Untz Untz!" : "off."]") + +/datum/action/item_action/toggle_headphones + name = "Toggle Headphones" + desc = "UNTZ UNTZ UNTZ" + +/datum/action/item_action/toggle_headphones/Trigger() + var/obj/item/clothing/ears/headphones/H = target + if(istype(H)) + H.toggle(owner) diff --git a/modular_skyrat/modules/customization/modules/clothing/hands/rings.dm b/modular_skyrat/modules/customization/modules/clothing/hands/rings.dm new file mode 100644 index 00000000000..00fd1492ffa --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/hands/rings.dm @@ -0,0 +1,33 @@ +/obj/item/clothing/gloves/ring + icon = 'modular_skyrat/modules/customization/icons/obj/ring.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/hands.dmi' + name = "gold ring" + desc = "A tiny gold ring, sized to wrap around a finger." + gender = NEUTER + w_class = WEIGHT_CLASS_TINY + icon = 'modular_skyrat/modules/customization/icons/obj/ring.dmi' + icon_state = "ringgold" + inhand_icon_state = "gring" + body_parts_covered = 0 + transfer_prints = TRUE + strip_delay = 40 + +/obj/item/clothing/gloves/ring/suicide_act(mob/living/carbon/user) + user.visible_message("\[user] is putting the [src] in [user.p_their()] mouth! It looks like [user] is trying to choke on the [src]!") + return OXYLOSS + + +/obj/item/clothing/gloves/ring/diamond + name = "diamond ring" + desc = "An expensive ring, studded with a diamond. Cultures have used these rings in courtship for a millenia." + icon_state = "ringdiamond" + inhand_icon_state = "dring" + +/obj/item/clothing/gloves/ring/diamond/attack_self(mob/user) + user.visible_message("\The [user] gets down on one knee, presenting \the [src].","You get down on one knee, presenting \the [src].") + +/obj/item/clothing/gloves/ring/silver + name = "silver ring" + desc = "A tiny silver ring, sized to wrap around a finger." + icon_state = "ringsilver" + inhand_icon_state = "sring" diff --git a/modular_skyrat/modules/customization/modules/clothing/head/head.dm b/modular_skyrat/modules/customization/modules/clothing/head/head.dm new file mode 100644 index 00000000000..f7b71c6c843 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/head/head.dm @@ -0,0 +1,44 @@ +/obj/item/clothing/head/flakhelm //Actually the M1 Helmet + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/head.dmi' + name = "flak helmet" + icon_state = "m1helm" + inhand_icon_state = "helmet" + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0.1, "bio" = 0, "rad" = 0, "fire" = -10, "acid" = -15, "wound" = 1) + desc = "A dilapidated helmet used in ancient wars. This one is brittle and essentially useless. An ace of spades is tucked into the band around the outer shell." + pocket_storage_component_path = /datum/component/storage/concrete/pockets/tiny/spacenam //So you can stuff other things in the elastic band instead of it simply being a fluff thing. + +/datum/component/storage/concrete/pockets/tiny/spacenam + attack_hand_interact = TRUE //So you can actually see what you stuff in there + +/obj/item/clothing/head/cowboyhat + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/head.dmi' + name = "cowboy hat" + desc = "A standard brown cowboy hat, yeehaw." + icon_state = "cowboyhat" + inhand_icon_state = "cowboyhat" + +/obj/item/clothing/head/cowboyhat/black + name = "black cowboy hat" + desc = "A a black cowboy hat, perfect for any outlaw" + icon_state = "cowboyhat_black" + inhand_icon_state= "cowboyhat_black" + +/obj/item/clothing/head/cowboyhat/white + name = "white cowboy hat" + desc = "A white cowboy hat, perfect for your every day rancher" + icon_state = "cowboyhat_white" + inhand_icon_state= "cowboyhat_white" + +/obj/item/clothing/head/cowboyhat/pink + name = "pink cowboy hat" + desc = "A pink cowboy? more like cowgirl hat, just don't be a buckle bunny." + icon_state = "cowboyhat_pink" + inhand_icon_state= "cowboyhat_pink" + +/obj/item/clothing/head/cowboyhat/sec + name = "security cowboy hat" + desc = "A security cowboy hat, perfect for any true lawman" + icon_state = "cowboyhat_sec" + inhand_icon_state= "cowboyhat_sec" diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm b/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm new file mode 100644 index 00000000000..3795142ac0a --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm @@ -0,0 +1,5 @@ +/obj/item/clothing/mask/breath/vox + desc = "A close-fitting mask that can be connected to an air supply. This one's got an easily accessible feeding port to be more suitable for the Vox crewmembers." + name = "vox breath mask" + actions_types = list() + flags_cover = 0 diff --git a/modular_skyrat/modules/customization/modules/clothing/neck/collars.dm b/modular_skyrat/modules/customization/modules/clothing/neck/collars.dm new file mode 100644 index 00000000000..6b33cd70dc8 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/neck/collars.dm @@ -0,0 +1,93 @@ +/datum/component/storage/concrete/pockets/small/collar + max_items = 1 + +/datum/component/storage/concrete/pockets/small/collar/Initialize() + . = ..() + can_hold = typecacheof(list( + /obj/item/reagent_containers/food/snacks/cookie, + /obj/item/reagent_containers/food/snacks/sugarcookie)) + +/datum/component/storage/concrete/pockets/small/collar/locked/Initialize() + . = ..() + can_hold = typecacheof(list( + /obj/item/reagent_containers/food/snacks/cookie, + /obj/item/reagent_containers/food/snacks/sugarcookie, + /obj/item/key/collar)) + +/obj/item/clothing/neck/human_petcollar + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/neck.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/neck.dmi' + name = "pet collar" + desc = "It's for pets. Though you probably could wear it yourself, you'd doubtless be the subject of ridicule. It seems to be made out of a polychromic material." + icon_state = "petcollar" + pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/collar + var/poly_states = 1 + var/poly_colors = list("#00BBBB") + var/tagname = null + var/treat_path = /obj/item/reagent_containers/food/snacks/cookie + +/obj/item/clothing/neck/human_petcollar/Initialize() + . = ..() + if(treat_path) + new treat_path(src) + +/obj/item/clothing/neck/human_petcollar/ComponentInitialize() + . = ..() + if(!poly_states) + return + //AddElement(/datum/element/polychromic, poly_colors, poly_states) + +/obj/item/clothing/neck/human_petcollar/attack_self(mob/user) + tagname = stripped_input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot", MAX_NAME_LEN) + name = "[initial(name)] - [tagname]" + +/obj/item/clothing/neck/human_petcollar/leather + name = "leather pet collar" + icon_state = "leathercollar" + poly_states = 2 + poly_colors = list("#222222", "#888888") + +/obj/item/clothing/neck/human_petcollar/choker + desc = "Quite fashionable... if you're somebody who's just read their first BDSM-themed erotica novel." + name = "choker" + icon_state = "choker" + poly_colors = list("#222222") + +/obj/item/clothing/neck/human_petcollar/locked + name = "locked collar" + desc = "A collar that has a small lock on it to keep it from being removed." + pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/collar/locked + treat_path = /obj/item/key/collar + var/lock = FALSE + +/obj/item/clothing/neck/human_petcollar/locked/attackby(obj/item/K, mob/user, params) + if(istype(K, /obj/item/key/collar)) + if(lock != FALSE) + to_chat(user, "With a click the collar unlocks!") + lock = FALSE + else + to_chat(user, "With a click the collar locks!") + lock = TRUE + return + +/obj/item/clothing/neck/human_petcollar/locked/attack_hand(mob/user) + if(loc == user && user.get_item_by_slot(ITEM_SLOT_NECK) && lock != FALSE) + to_chat(user, "The collar is locked! You'll need unlock the collar before you can take it off!") + return + ..() + +/obj/item/clothing/neck/human_petcollar/locked/leather + name = "leather pet collar" + icon_state = "leathercollar" + poly_states = 2 + poly_colors = list("#222222", "#888888") + +/obj/item/clothing/neck/human_petcollar/locked/choker + name = "choker" + desc = "Quite fashionable... if you're somebody who's just read their first BDSM-themed erotica novel." + icon_state = "choker" + poly_colors = list("#222222") + +/obj/item/key/collar + name = "Collar Key" + desc = "A key for a tiny lock on a collar or bag." diff --git a/modular_skyrat/modules/customization/modules/clothing/outfits/vox.dm b/modular_skyrat/modules/customization/modules/clothing/outfits/vox.dm new file mode 100644 index 00000000000..3556cac9796 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/outfits/vox.dm @@ -0,0 +1,5 @@ +/datum/outfit/vox + name = "Vox" + + r_hand= /obj/item/tank/internals/nitrogen/belt/full + mask = /obj/item/clothing/mask/breath/vox diff --git a/modular_skyrat/modules/customization/modules/clothing/shoes/shoes.dm b/modular_skyrat/modules/customization/modules/clothing/shoes/shoes.dm new file mode 100644 index 00000000000..ccad1315f01 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/shoes/shoes.dm @@ -0,0 +1,34 @@ +/obj/item/clothing/shoes/wraps + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/shoes.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/feet.dmi' + name = "gilded leg wraps" + desc = "Ankle coverings. These ones have a golden design." + icon_state = "gildedcuffs" + body_parts_covered = FALSE + +/obj/item/clothing/shoes/wraps/silver + name = "silver leg wraps" + desc = "Ankle coverings. Not made of real silver." + icon_state = "silvergildedcuffs" + +/obj/item/clothing/shoes/wraps/red + name = "red leg wraps" + desc = "Ankle coverings. Show off your style with these shiny red ones!" + icon_state = "redcuffs" + +/obj/item/clothing/shoes/wraps/blue + name = "blue leg wraps" + desc = "Ankle coverings. Hang ten, brother." + icon_state = "bluecuffs" + +/obj/item/clothing/shoes/cowboyboots + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/shoes.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/feet.dmi' + name = "cowboy boots" + desc = "A standard pair of brown cowboy boots." + icon_state = "cowboyboots" + +/obj/item/clothing/shoes/cowboyboots/black + name = "black cowboy boots" + desc = "A pair of black cowboy boots, pretty easy to scuff up." + icon_state = "cowboyboots_black" diff --git a/modular_skyrat/modules/customization/modules/clothing/suits/armor.dm b/modular_skyrat/modules/customization/modules/clothing/suits/armor.dm new file mode 100644 index 00000000000..fed7befd8b9 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/suits/armor.dm @@ -0,0 +1,25 @@ +/obj/item/clothing/suit/armor/navyblue + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "security officer's jacket" + desc = "This jacket is for those special occasions when a security officer isn't required to wear their armor." + icon_state = "officerbluejacket" + body_parts_covered = CHEST|ARMS + +/obj/item/clothing/suit/armor/hos/navyblue + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "head of security's jacket" + desc = "This piece of clothing was specifically designed for asserting superior authority." + icon_state = "hosbluejacket" + body_parts_covered = CHEST|ARMS + cold_protection = CHEST|ARMS + heat_protection = CHEST|ARMS + +/obj/item/clothing/suit/armor/vest/warden/navyblue + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "warden's jacket" + desc = "Perfectly suited for the warden that wants to leave an impression of style on those who visit the brig." + icon_state = "wardenbluejacket" + body_parts_covered = CHEST|ARMS diff --git a/modular_skyrat/modules/customization/modules/clothing/suits/coats.dm b/modular_skyrat/modules/customization/modules/clothing/suits/coats.dm new file mode 100644 index 00000000000..563bf3c0302 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/suits/coats.dm @@ -0,0 +1,165 @@ +/obj/item/clothing/suit/hooded/wintercoat + mutant_variants = NONE + +/obj/item/clothing/suit/hooded/wintercoat/paramedic + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "paramedic winter coat" + desc = "A winter coat with blue markings. Warm, but probably won't protect from biological agents. For the cozy doctor on the go." + icon_state = "coatparamed" + inhand_icon_state = "coatparamed" + allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 0, "acid" = 45, "wound" = 3) + hoodtype = /obj/item/clothing/head/hooded/winterhood/paramedic + +/obj/item/clothing/head/hooded/winterhood/paramedic + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/head.dmi' + desc = "A white winter coat hood with blue markings." + icon_state = "winterhood_paramed" + +/obj/item/clothing/suit/hooded/wintercoat/robotics + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "robotics winter coat" + desc = "A black winter coat with a badass flaming robotic skull for the zipper tab. This one has bright red designs and a few useless buttons." + icon_state = "coatrobotics" + inhand_icon_state = "coatrobotics" + allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/screwdriver, /obj/item/crowbar, /obj/item/wrench, /obj/item/stack/cable_coil, /obj/item/weldingtool, /obj/item/multitool) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 0) + hoodtype = /obj/item/clothing/head/hooded/winterhood/robotics + +/obj/item/clothing/head/hooded/winterhood/robotics + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/head.dmi' + desc = "A black winter coat hood. You can pull it down over your eyes and pretend that you're an outdated, late 1980s interpretation of a futuristic mechanized police force. They'll fix you. They fix everything." + icon_state = "winterhood_robotics" + + +/obj/item/clothing/suit/hooded/wintercoat/aformal + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "assistant's formal winter coat" + desc = "A black button up winter coat." + icon_state = "coataformal" + inhand_icon_state = "coataformal" + allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter,/obj/item/clothing/gloves/color/yellow) + hoodtype = /obj/item/clothing/head/hooded/winterhood/aformal + +/obj/item/clothing/head/hooded/winterhood/aformal + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/head.dmi' + desc = "A black winter coat hood." + icon_state = "winterhood_aformal" + +/obj/item/clothing/suit/hooded/wintercoat/ratvar + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "ratvarian winter coat" + desc = "A brass-plated button up winter coat. Instead of a zipper tab, it has a brass cog with a tiny red gemstone inset." + icon_state = "coatratvar" + inhand_icon_state = "coatratvar" + armor = list("melee" = 30, "bullet" = 45, "laser" = -10, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 60, "acid" = 60, "wound" = 10) + hoodtype = /obj/item/clothing/head/hooded/winterhood/ratvar + var/real = TRUE + +/obj/item/clothing/head/hooded/winterhood/ratvar + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/head.dmi' + icon_state = "winterhood_ratvar" + desc = "A brass-plated winter hood that glows softly, hinting at its divinity." + light_range = 3 + light_power = 1 + light_color = "#B18B25" //clockwork slab background top color + +/*/obj/item/clothing/suit/hooded/wintercoat/ratvar/equipped(mob/living/user,slot) + ..() + if (slot != SLOT_WEAR_SUIT || !real) + return + if (is_servant_of_ratvar(user)) + return + else + user.dropItemToGround(src) + to_chat(user,"\"Amusing that you think you are fit to wear this.\"") + to_chat(user,"Your skin burns where the coat touched your skin!") + user.adjustFireLoss(rand(10,16))*/ + +/obj/item/clothing/suit/hooded/wintercoat/narsie + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "narsian winter coat" + desc = "A somber button-up in tones of grey entropy and a wicked crimson zipper. When pulled all the way up, the zipper looks like a bloody gash. The zipper pull looks like a single drop of blood." + icon_state = "coatnarsie" + inhand_icon_state = "coatnarsie" + armor = list("melee" = 30, "bullet" = 20, "laser" = 30,"energy" = 10, "bomb" = 30, "bio" = 10, "rad" = 10, "fire" = 30, "acid" = 30, "wound" = 10) + allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/restraints/legcuffs/bola/cult,/obj/item/melee/cultblade,/obj/item/melee/cultblade/dagger,/obj/item/reagent_containers/glass/beaker/unholywater,/obj/item/cult_shift,/obj/item/flashlight/flare/culttorch,/obj/item/cult_spear) + hoodtype = /obj/item/clothing/head/hooded/winterhood/narsie + var/real = TRUE + +/*/obj/item/clothing/suit/hooded/wintercoat/narsie/equipped(mob/living/user,slot) + ..() + if (slot != SLOT_WEAR_SUIT || !real) + return + if (iscultist(user)) + return + else + user.dropItemToGround(src) + to_chat(user,"\"You are not fit to wear my follower's coat!\"") + to_chat(user,"Sharp spines jab you from within the coat!") + user.adjustBruteLoss(rand(10,16))*/ + +/obj/item/clothing/head/hooded/winterhood/narsie + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/head.dmi' + desc = "A black winter hood full of whispering secrets that only She shall ever know." + icon_state = "winterhood_narsie" + +/obj/item/clothing/suit/hooded/wintercoat/ratvar/fake + name = "brass winter coat" + desc = "A brass-plated button up winter coat. Instead of a zipper tab, it has a brass cog with a tiny red piece of plastic as an inset." + icon_state = "coatratvar" + inhand_icon_state = "coatratvar" + allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 0) + real = FALSE + +/obj/item/clothing/suit/hooded/wintercoat/narsie/fake + name = "runed winter coat" + desc = "A dusty button up winter coat in the tones of oblivion and ash. The zipper pull looks like a single drop of blood." + icon_state = "coatnarsie" + inhand_icon_state = "coatnarsie" + allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 0) + real = FALSE + +/obj/item/clothing/suit/flakjack + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "flak jacket" + desc = "A dilapidated jacket made of a supposedly bullet-proof material (Hint: It isn't.). Smells faintly of napalm." + icon_state = "flakjack" + inhand_icon_state = "redtag" + blood_overlay_type = "armor" + body_parts_covered = CHEST + resistance_flags = NONE + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 5, "bio" = 0, "rad" = 0, "fire" = -5, "acid" = -15, "wound" = 0) //nylon sucks against acid + mutant_variants = NONE + +/obj/item/clothing/suit/hooded/cloak/david + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/suit.dmi' + name = "red cloak" + icon_state = "goliath_cloak" + desc = "Ever wanted to look like a badass without ANY effort? Try this nanotrasen brand red cloak, perfect for kids" + hoodtype = /obj/item/clothing/head/hooded/cloakhood/david + body_parts_covered = CHEST|GROIN|ARMS + mutant_variants = NONE + +/obj/item/clothing/head/hooded/cloakhood/david + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/head.dmi' + name = "red cloak hood" + icon_state = "golhood" + desc = "conceal your face in shame with this nanotrasen brand hood" + flags_inv = HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR + mutant_variants = NONE diff --git a/modular_skyrat/modules/customization/modules/clothing/under/costumes.dm b/modular_skyrat/modules/customization/modules/clothing/under/costumes.dm new file mode 100644 index 00000000000..bfff783ffe4 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/under/costumes.dm @@ -0,0 +1,46 @@ +// Lunar Clothes +/obj/item/clothing/under/costume/qipao + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "black qipao" + desc = "A qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is black." + icon_state = "qipao" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutant_variants = NONE + +/obj/item/clothing/under/costume/qipao/white + name = "white qipao" + desc = "A qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is white." + icon_state = "qipao_white" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + +/obj/item/clothing/under/costume/qipao/red + name = "red qipao" + desc = "A qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is red." + icon_state = "qipao_red" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + +/obj/item/clothing/under/costume/cheongsam + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "black cheongsam" + desc = "A cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is black." + icon_state = "cheong" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutant_variants = NONE + +/obj/item/clothing/under/costume/cheongsam/white + name = "white cheongsam" + desc = "A cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is white." + icon_state = "cheongw" + body_parts_covered = CHEST|GROIN + +/obj/item/clothing/under/costume/cheongsam/red + name = "red cheongsam" + desc = "A cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is red.." + icon_state = "cheongr" + body_parts_covered = CHEST|GROIN diff --git a/modular_skyrat/modules/customization/modules/clothing/under/misc.dm b/modular_skyrat/modules/customization/modules/clothing/under/misc.dm new file mode 100644 index 00000000000..bef4c8aa575 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/under/misc.dm @@ -0,0 +1,33 @@ +/obj/item/clothing/under/misc/stripper + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "pink stripper outfit" + icon_state = "stripper_p" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutantrace_variation = NONE + +/obj/item/clothing/under/misc/stripper/green + name = "green stripper outfit" + icon_state = "stripper_g" + +/obj/item/clothing/under/misc/stripper/mankini + name = "pink mankini" + icon_state = "mankini" + +/obj/item/clothing/under/croptop + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "crop top" + desc = "We've saved money by giving you half a shirt!" + icon_state = "croptop" + body_parts_covered = CHEST|GROIN|ARMS + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE + +/obj/item/clothing/under/misc/gear_harness + name = "gear harness" + desc = "A simple, inconspicuous harness replacement for a jumpsuit." + icon_state = "gear_harness" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE diff --git a/modular_skyrat/modules/customization/modules/clothing/under/pants.dm b/modular_skyrat/modules/customization/modules/clothing/under/pants.dm new file mode 100644 index 00000000000..1667931b8d2 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/under/pants.dm @@ -0,0 +1,35 @@ +/obj/item/clothing/under/pants/jeanripped + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "ripped jeans" + desc = "If you're wearing this you're poor or a rebel" + icon_state = "jean_ripped" + +/obj/item/clothing/under/pants/jeanshort + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "jean shorts" + desc = "These are really just jeans cut in half" + icon_state = "jean_shorts" + +/obj/item/clothing/under/pants/denimskirt + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "denim skirt" + desc = "These are really just a jean leg hole cut from a pair" + icon_state = "denim_skirt" + +/obj/item/clothing/under/pants/chaps + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "black chaps" + body_parts_covered = LEGS + desc = "Yeehaw" + icon_state = "chaps" + +/obj/item/clothing/under/pants/yoga + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "yoga pants" + desc = "Comfy!" + icon_state = "yoga_pants" diff --git a/modular_skyrat/modules/customization/modules/clothing/under/skirts_dresses.dm b/modular_skyrat/modules/customization/modules/clothing/under/skirts_dresses.dm new file mode 100644 index 00000000000..07d94b82ac5 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/under/skirts_dresses.dm @@ -0,0 +1,97 @@ +/obj/item/clothing/under/dress/sundress/white + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "white sundress" + icon_state = "sundress_white" + +/obj/item/clothing/under/dress/green + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "green dress" + desc = "A tight green dress" + icon_state = "dress_green" + body_parts_covered = CHEST|GROIN + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE + +/obj/item/clothing/under/dress/pink + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "pink dress" + desc = "A tight pink dress" + icon_state = "dress_pink" + body_parts_covered = CHEST|GROIN + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE + +/obj/item/clothing/under/dress/blacktango + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "black tango dress" + desc = "Filled with Latin fire." + icon_state = "black_tango" + inhand_icon_state = "wcoat" + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE + +/obj/item/clothing/under/dress/westernbustle + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "western bustle dress" + desc = "Filled with Western fire." + icon_state = "western_bustle" + inhand_icon_state = "wcoat" + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE + +/obj/item/clothing/under/dress/flamenco + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "flamenco dress" + desc = "Filled with Latin fire." + icon_state = "flamenco" + inhand_icon_state = "wcoat" + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE + +/obj/item/clothing/under/dress/striped + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "striped dress" + desc = "Fashion in space." + icon_state = "striped_dress" + inhand_icon_state = "stripeddress" + body_parts_covered = CHEST|GROIN|ARMS + fitted = FEMALE_UNIFORM_FULL + can_adjust = FALSE + +/obj/item/clothing/under/dress/flower + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "flower dress" + desc = "Lovely dress." + icon_state = "flower_dress" + inhand_icon_state = "sailordress" + body_parts_covered = CHEST|GROIN|LEGS + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE + +/obj/item/clothing/under/dress/skirt/swept + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "swept skirt" + desc = "Formal skirt." + icon_state = "skirt_swept" + body_parts_covered = GROIN + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE + +/obj/item/clothing/under/dress/corset + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "black corset" + desc = "Nanotrasen is not resposible for any organ damage." + icon_state = "corset" + body_parts_covered = CHEST|GROIN + fitted = FEMALE_UNIFORM_TOP + can_adjust = FALSE diff --git a/modular_skyrat/modules/customization/modules/clothing/under/sweaters.dm b/modular_skyrat/modules/customization/modules/clothing/under/sweaters.dm new file mode 100644 index 00000000000..91965379fa8 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/under/sweaters.dm @@ -0,0 +1,35 @@ +/obj/item/clothing/under/sweater + icon = 'modular_skyrat/modules/customization/icons/obj/clothing/uniforms.dmi' + worn_icon = 'modular_skyrat/modules/customization/icons/mob/clothing/uniform.dmi' + name = "cream sweater" + desc = "Why trade style for comfort? Now you can go commando down south and still be cozy up north." + icon_state = "bb_turtle" + body_parts_covered = CHEST|GROIN|ARMS + can_adjust = TRUE + mutant_variants = NONE + +/obj/item/clothing/under/sweater/black + name = "black sweater" + icon_state = "bb_turtleblk" + +/obj/item/clothing/under/sweater/purple + name = "purple sweater" + icon_state = "bb_turtlepur" + +/obj/item/clothing/under/sweater/green + name = "green sweater" + icon_state = "bb_turtlegrn" + +/obj/item/clothing/under/sweater/red + name = "red sweater" + icon_state = "bb_turtlered" + +/obj/item/clothing/under/sweater/blue + name = "blue sweater" + icon_state = "bb_turtleblu" + +/obj/item/clothing/under/sweater/keyhole + name = "keyhole sweater" + desc = "What is the point of this, anyway?" + icon_state = "keyholesweater" + can_adjust = FALSE diff --git a/modular_skyrat/modules/customization/modules/jobs/_job.dm b/modular_skyrat/modules/customization/modules/jobs/_job.dm new file mode 100644 index 00000000000..f48aeb8b931 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/jobs/_job.dm @@ -0,0 +1,7 @@ +/datum/job + ///With this set to TRUE, the loadout will be applied before a job clothing will be + var/no_dresscode + + +/datum/job/assistant + no_dresscode = TRUE diff --git a/modular_skyrat/modules/customization/modules/language/dwarf.dm b/modular_skyrat/modules/customization/modules/language/dwarf.dm new file mode 100644 index 00000000000..f60f06e6581 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/language/dwarf.dm @@ -0,0 +1,12 @@ +// The language of the Dwarves, based on Dwarf Fortress +/datum/language/dwarf + name = "Dwarvish" + desc = "The language of the dwarves" + space_chance = 100 // Each 'syllable' is its own word + key = "D" + flags = TONGUELESS_SPEECH + //Yeah I axed like 90% of those syllables, ain't letting anything iterate over that + syllables = list("kulet", "alak", "bidok", "nicol", "anam", "gatal", "mabdug", "kun", "kiror", "nicat", "onshen", "r%rith", "mafol", "sid", "ntdn", "kontuth", "letmos", "mishim", "losush", "othbem", "b^ngeng", "lasgan", "utal", "sedur", "engig", "sunggor", "thistun", "k''shdes", "ngefel", "umer", "uleb", "n shas", "r''mab", "sezom", "shashdon", "m%bnith", "k n", "gitnuk", "daros", "nokim", "mostib", "thethrus", "kagmel", "bidnoz", "elbost", "oten", "ushdish", "kitung", "nubam", "onget", "d%ngstam", "nimar", "gelut", "nis-n", "tarem", "nam", "kozoth", "tokmek", "ed", "et", "thunen", "shokmug", "vutok", "zanos", "torad", "berdan", "nal", "mosol", "othduk", "kinem", "zatthud", "nabtr", "rirn''l", "lised", "danman", "nirk£n", "mubun") + default_priority = 90 + icon_state = "dwarf" + icon = 'modular_skyrat/modules/customization/icons/misc/language.dmi' diff --git a/modular_skyrat/modules/customization/modules/language/language_holder.dm b/modular_skyrat/modules/customization/modules/language/language_holder.dm new file mode 100644 index 00000000000..0c244cc0e72 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/language/language_holder.dm @@ -0,0 +1,11 @@ +/datum/language_holder/dwarf + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/dwarf = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/dwarf = list(LANGUAGE_ATOM)) + +/datum/language_holder/vox + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/vox = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/vox = list(LANGUAGE_ATOM)) diff --git a/modular_skyrat/modules/customization/modules/language/vox.dm b/modular_skyrat/modules/customization/modules/language/vox.dm new file mode 100644 index 00000000000..afbf2ca4e3d --- /dev/null +++ b/modular_skyrat/modules/customization/modules/language/vox.dm @@ -0,0 +1,9 @@ +/datum/language/vox + name = "Vox-pidgin" + desc = "The common tongue of the various Vox ships making up the Shoal. It sounds like chaotic shrieking to everyone else." + key = "vox" + flags = TONGUELESS_SPEECH + space_chance = 40 + syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya", "yi", "chi","cha","kah","SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA") + icon_state = "swarmer" + default_priority = 99 diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_marking_sets.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_marking_sets.dm new file mode 100644 index 00000000000..bc42dc97898 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_marking_sets.dm @@ -0,0 +1,173 @@ +/datum/body_marking_set + ///The preview name of the body marking set. HAS to be unique + var/name + ///List of the body markings in this set + var/body_marking_list + ///Which species is this marking recommended to. Important for randomisations. + var/recommended_species = list("mammal") + +/datum/body_marking_set/none + name = "None" + body_marking_list = list() + +/datum/body_marking_set/tajaran + name = "Tajaran" + body_marking_list = list("Tajaran") + +/datum/body_marking_set/sergal + name = "Sergal" + body_marking_list = list("Sergal") + +/datum/body_marking_set/husky + name = "Husky" + body_marking_list = list("Husky") + +/datum/body_marking_set/fennec + name = "Fennec" + body_marking_list = list("Fennec") + +/datum/body_marking_set/redpanda + name = "Red Panda" + body_marking_list = list("Red Panda", "Red Panda Head") + +/datum/body_marking_set/dalmatian + name = "Dalmatian" + body_marking_list = list("Dalmatian") + +/datum/body_marking_set/shepherd + name = "Shepherd" + body_marking_list = list("Shepherd", "Shepherd Spot") + +/datum/body_marking_set/wolf + name = "Wolf" + body_marking_list = list("Wolf", "Wolf Spot") + +/datum/body_marking_set/raccoon + name = "Raccoon" + body_marking_list = list("Raccoon") + +/datum/body_marking_set/bovine + name = "Bovine" + body_marking_list = list("Bovine", "Bovine Spot") + +/datum/body_marking_set/possum + name = "Possum" + body_marking_list = list("Possum") + +/datum/body_marking_set/corgi + name = "Corgi" + body_marking_list = list("Corgi") + +/datum/body_marking_set/skunk + name = "Skunk" + body_marking_list = list("Skunk") + +/datum/body_marking_set/panther + name = "Panther" + body_marking_list = list("Panther") + +/datum/body_marking_set/tiger + name = "Tiger" + body_marking_list = list("Tiger Spot", "Tiger Stripe") + +/datum/body_marking_set/otter + name = "Otter" + body_marking_list = list("Otter", "Otter Head") + +/datum/body_marking_set/otie + name = "Otie" + body_marking_list = list("Otie", "Otie Spot") + +/datum/body_marking_set/sabresune + name = "Sabresune" + body_marking_list = list("Sabresune") + +/datum/body_marking_set/orca + name = "Orca" + body_marking_list = list("Orca") + +/datum/body_marking_set/hawk + name = "Hawk" + body_marking_list = list("Hawk", "Hawk Talon") + +/datum/body_marking_set/corvid + name = "Corvid" + body_marking_list = list("Corvid", "Corvid Talon") + +/datum/body_marking_set/eevee + name = "Eevee" + body_marking_list = list("Eevee") + +/datum/body_marking_set/deer + name = "Deer" + body_marking_list = list("Deer", "Deer Hoof") + +/datum/body_marking_set/hyena + name = "Hyena" + body_marking_list = list("Hyena", "Hyena Side") + +/datum/body_marking_set/dog + name = "Dog" + body_marking_list = list("Dog", "Dog Spot") + +/datum/body_marking_set/bat + name = "Bat" + body_marking_list = list("Bat Mark", "Bat") + +/datum/body_marking_set/goat + name = "Goat" + body_marking_list = list("Goat Hoof") + +/datum/body_marking_set/floof + name = "Floof" + body_marking_list = list("Floof") + +/datum/body_marking_set/floofer + name = "Floofer" + body_marking_list = list("Floofer", "Floofer Sock") + +/datum/body_marking_set/rat + name = "Rat" + body_marking_list = list("Rat Paw", "Rat Spot") + +/datum/body_marking_set/sloth + name = "Sloth" + body_marking_list = list("Rat Paw", "Sloth Head") //Yes we're re-using the rat bits as they'd be identical + +/datum/body_marking_set/vox + recommended_species = list("vox") + +/datum/body_marking_set/vox/vox + name = "Vox" + body_marking_list = list("Vox Talon") + +/datum/body_marking_set/vox/vox_tiger + name = "Vox Tiger" + body_marking_list = list("Vox Talon", "Vox Tiger Tattoo") + +/datum/body_marking_set/vox/vox_hive + name = "Vox Hive" + body_marking_list = list("Vox Talon", "Vox Hive Tattoo") + +/datum/body_marking_set/vox/vox_nightling + name = "Vox Nightling" + body_marking_list = list("Vox Talon", "Vox Nightling Tattoo") + +/datum/body_marking_set/vox/vox_heart + name = "Vox Heart" + body_marking_list = list("Vox Talon", "Vox Heart Tattoo") + +/datum/body_marking_set/synthliz + recommended_species = list("synthliz") + +/datum/body_marking_set/synthliz/scutes + name = "Synth Scutes" + body_marking_list = list("Synth Scutes") + +/datum/body_marking_set/synthliz/pecs + name = "Synth Pecs" + body_marking_list = list("Synth Pecs") + +/datum/body_marking_set/synthliz/pecs_light + name = "Synth Pecs Lights" + body_marking_list = list("Synth Pecs", "Synth Collar Lights") diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings.dm new file mode 100644 index 00000000000..e8d44be2aea --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings.dm @@ -0,0 +1,304 @@ +//This datum is quite close to the sprite accessory one, containing a bit of copy pasta code +//Those DO NOT have a customizable cases for rendering, or any special stuff, and are meant to be simpler than accessories +//One definition can stand for a whole set of accessories, make sure to set affected bodyparts +/datum/body_marking + ///The icon file the body markign is located in + var/icon + ///The icon_state of the body marking + var/icon_state + ///The preview name of the body marking. NEEDS A UNIQUE NAME + var/name + ///The color the marking defaults to, important for randomisations. either a hex color ie."FFF" or a define like DEFAULT_PRIMARY + var/default_color + ///Which bodyparts does the marking affect in BITFLAGS!! (HEAD, CHEST, ARM_LEFT, ARM_RIGHT, HAND_LEFT, HAND_RIGHT, LEG_RIGHT, LEG_LEFT) + var/affected_bodyparts + ///Which species is this marking recommended to. Important for randomisations. + var/recommended_species = list("mammal") + ///If this is on the color customization will show up despite the pref settings, it will also cause the marking to not reset colors to match the defaults + var/always_color_customizable + +/datum/body_marking/New() + if(!default_color) + default_color = "FFF" + +/datum/body_marking/proc/get_default_color(var/list/features, var/datum/species/pref_species) //Needs features for the color information + var/list/colors + switch(default_color) + if(DEFAULT_PRIMARY) + colors = features["mcolor"] + if(DEFAULT_SECONDARY) + colors = features["mcolor2"] + if(DEFAULT_TERTIARY) + colors = features["mcolor3"] + if(DEFAULT_SKIN_OR_PRIMARY) + if(pref_species && pref_species.use_skintones) + colors = features["skin_color"] + else + colors = features["mcolor"] + else + colors = default_color + + return colors + +/datum/body_marking/secondary + icon = 'modular_skyrat/modules/customization/icons/mob/body_markings/secondary_markings.dmi' + default_color = DEFAULT_SECONDARY + +/datum/body_marking/secondary/tajaran + name = "Tajaran" + icon_state = "tajaran" + affected_bodyparts = HEAD | CHEST //The legs were literally one pixel so I removed them + +/datum/body_marking/secondary/sergal + name = "Sergal" + icon_state = "sergal" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/husky + name = "Husky" + icon_state = "husky" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/fennec + name = "Fennec" + icon_state = "fennec" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/redpanda + name = "Red Panda" + icon_state = "redpanda" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/dalmatian + name = "Dalmatian" + icon_state = "dalmation" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/shepherd + name = "Shepherd" + icon_state = "shepherd" + affected_bodyparts = CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/wolf + name = "Wolf" + icon_state = "wolf" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/fox + name = "Fox" + icon_state = "fox" + affected_bodyparts = HEAD | CHEST | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/raccoon + name = "Raccoon" + icon_state = "raccoon" + affected_bodyparts = HEAD | CHEST | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/bovine + name = "Bovine" + icon_state = "bovine" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/possum + name = "Possum" + icon_state = "possum" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/corgi + name = "Corgi" + icon_state = "corgi" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/skunk + name = "Skunk" + icon_state = "skunk" + affected_bodyparts = HEAD | CHEST | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/panther + name = "Panther" + icon_state = "panther" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/tiger + name = "Tiger Spot" + icon_state = "tiger" + affected_bodyparts = HEAD | CHEST | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/otter + name = "Otter" + icon_state = "otter" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/otie + name = "Otie" + icon_state = "otie" + affected_bodyparts = HEAD | CHEST | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/sabresune + name = "Sabresune" + icon_state = "sabresune" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/orca + name = "Orca" + icon_state = "orca" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/hawk + name = "Hawk" + icon_state = "hawk" + affected_bodyparts = HEAD | CHEST | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/corvid + name = "Corvid" + icon_state = "corvid" + affected_bodyparts = HEAD | CHEST | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/eevee + name = "Eevee" + icon_state = "eevee" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/shark + name = "Shark" + icon_state = "shark" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/deer + name = "Deer" + icon_state = "deer" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/hyena + name = "Hyena" + icon_state = "hyena" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/dog + name = "Dog" + icon_state = "dog" + affected_bodyparts = CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/secondary/bat + name = "Bat" + icon_state = "bat" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/floof + name = "Floof" + icon_state = "floof" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/floofer + name = "Floofer" + icon_state = "floofer" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/secondary/rat + name = "Rat Paw" + icon_state = "rat" + affected_bodyparts = ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary + icon = 'modular_skyrat/modules/customization/icons/mob/body_markings/tertiary_markings.dmi' + default_color = DEFAULT_TERTIARY + +/datum/body_marking/tertiary/redpanda + name = "Red Panda Head" + icon_state = "redpanda" + affected_bodyparts = HEAD + +/datum/body_marking/tertiary/shepherd + name = "Shepherd Spot" + icon_state = "redpanda" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/tertiary/wolf + name = "Wolf Spot" + icon_state = "wolf" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/fox + name = "Fox Sock" + icon_state = "fox" + affected_bodyparts = ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/goat + name = "Goat Hoof" + icon_state = "goat" + affected_bodyparts = HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/raccoon + name = "Raccoon Spot" + icon_state = "raccoon" + affected_bodyparts = HEAD | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/bovine + name = "Bovine Spot" + icon_state = "bovine" + affected_bodyparts = HEAD | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/possum + name = "Possum Sock" + icon_state = "possum" + affected_bodyparts = HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/tiger + name = "Tiger Stripe" + icon_state = "tiger" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/otter + name = "Otter Head" + icon_state = "otter" + affected_bodyparts = HEAD + +/datum/body_marking/tertiary/otie + name = "Otie Spot" + icon_state = "otie" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/hawk + name = "Hawk Talon" + icon_state = "hawk" + affected_bodyparts = LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/corvid + name = "Corvid Talon" + icon_state = "corvid" + affected_bodyparts = LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/deer + name = "Deer Hoof" + icon_state = "deer" + affected_bodyparts = HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/hyena + name = "Hyena Side" + icon_state = "hyena" + affected_bodyparts = HEAD | CHEST + +/datum/body_marking/tertiary/dog + name = "Dog Spot" + icon_state = "dog" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/bat + name = "Bat Mark" + icon_state = "bat" + affected_bodyparts = CHEST + +/datum/body_marking/tertiary/floofer + name = "Floofer Sock" + icon_state = "floofer" + affected_bodyparts = ARM_LEFT | ARM_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/rat + name = "Rat Spot" + icon_state = "rat" + affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/sloth + name = "Sloth Head" + icon_state = "sloth" + affected_bodyparts = HEAD diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings_synthliz.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings_synthliz.dm new file mode 100644 index 00000000000..81640c23cc6 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings_synthliz.dm @@ -0,0 +1,37 @@ +/datum/body_marking/secondary/synthliz + icon = 'modular_skyrat/modules/customization/icons/mob/body_markings/synthliz_secondary.dmi' + recommended_species = list("synthliz") + +/datum/body_marking/secondary/synthliz/scutes + name = "Synth Scutes" + icon_state = "synthlizscutes" + affected_bodyparts = CHEST + +/datum/body_marking/secondary/synthliz/lights + name = "Synth Lights" + icon_state = "synthlizlights" + affected_bodyparts = CHEST + +/datum/body_marking/secondary/synthliz/pecs + name = "Synth Pecs" + icon_state = "synthlizpecs" + affected_bodyparts = CHEST + +/datum/body_marking/tertiary/synthliz + icon = 'modular_skyrat/modules/customization/icons/mob/body_markings/synthliz_tertiary.dmi' + recommended_species = list("synthliz") + +/datum/body_marking/tertiary/synthliz/plates + name = "Synth Plates" + icon_state = "synthlizplates" + affected_bodyparts = CHEST + +/datum/body_marking/tertiary/synthliz/chestlights + name = "Synth Chest Lights" + icon_state = "synthlizlights" + affected_bodyparts = CHEST + +/datum/body_marking/tertiary/synthliz/collarlights + name = "Synth Collar Lights" + icon_state = "synthlizpecslight" + affected_bodyparts = CHEST | ARM_LEFT | ARM_RIGHT diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings_vox.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings_vox.dm new file mode 100644 index 00000000000..210c987a181 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/body_markings/body_markings_vox.dm @@ -0,0 +1,31 @@ +/datum/body_marking/secondary/vox + icon = 'modular_skyrat/modules/customization/icons/mob/body_markings/vox_secondary.dmi' + recommended_species = list("vox") + +/datum/body_marking/secondary/vox/vox + name = "Vox Talon" + icon_state = "vox" + affected_bodyparts = ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT + +/datum/body_marking/tertiary/vox + icon = 'modular_skyrat/modules/customization/icons/mob/body_markings/vox_tertiary.dmi' + +/datum/body_marking/tertiary/vox/tiger + name = "Vox Tiger Tattoo" + icon_state = "voxtiger" + affected_bodyparts = CHEST | LEG_RIGHT | LEG_LEFT | ARM_LEFT | ARM_RIGHT + +/datum/body_marking/tertiary/vox/hive + name = "Vox Hive Tattoo" + icon_state = "voxhive" + affected_bodyparts = CHEST + +/datum/body_marking/tertiary/vox/nightling + name = "Vox Nightling Tattoo" + icon_state = "voxnightling" + affected_bodyparts = CHEST | ARM_LEFT | ARM_RIGHT + +/datum/body_marking/tertiary/vox/heart + name = "Vox Heart Tattoo" + icon_state = "voxheart" + affected_bodyparts = ARM_RIGHT diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/preferences_setup.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/preferences_setup.dm new file mode 100644 index 00000000000..966f2bf131d --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/preferences_setup.dm @@ -0,0 +1,193 @@ + + //The mob should have a gender you want before running this proc. Will run fine without H +/datum/preferences/proc/random_character(gender_override, antag_override = FALSE) + if(randomise[RANDOM_SPECIES]) + random_species() + else if(randomise[RANDOM_NAME]) + real_name = pref_species.random_name(gender,1) + if(gender_override && !(randomise[RANDOM_GENDER] || randomise[RANDOM_GENDER_ANTAG] && antag_override)) + gender = gender_override + else + gender = pick(MALE,FEMALE,PLURAL) + if(randomise[RANDOM_AGE] || randomise[RANDOM_AGE_ANTAG] && antag_override) + age = rand(AGE_MIN,AGE_MAX) + /*if(randomise[RANDOM_UNDERWEAR]) + underwear = random_underwear(gender) + if(randomise[RANDOM_UNDERWEAR_COLOR]) + underwear_color = random_short_color() + if(randomise[RANDOM_UNDERSHIRT]) + undershirt = random_undershirt(gender) + if(randomise[RANDOM_SOCKS]) + socks = random_socks()*/ + if(randomise[RANDOM_BACKPACK]) + backpack = random_backpack() + if(randomise[RANDOM_JUMPSUIT_STYLE]) + jumpsuit_style = pick(GLOB.jumpsuitlist) + if(randomise[RANDOM_HAIRSTYLE]) + hairstyle = random_hairstyle(gender) + if(randomise[RANDOM_FACIAL_HAIRSTYLE]) + facial_hairstyle = random_facial_hairstyle(gender) + if(randomise[RANDOM_HAIR_COLOR]) + hair_color = random_short_color() + if(randomise[RANDOM_FACIAL_HAIR_COLOR]) + facial_hair_color = random_short_color() + if(randomise[RANDOM_SKIN_TONE]) + set_skin_tone(random_skin_tone()) + if(randomise[RANDOM_EYE_COLOR]) + eye_color = random_eye_color() + if(!pref_species) + var/rando_race = pick(GLOB.roundstart_races) + set_new_species(rando_race) + if(gender in list(MALE, FEMALE)) + body_type = gender + else + body_type = pick(MALE, FEMALE) + //features = pref_species.get_random_features() + var/list/new_features = pref_species.get_random_features() //We do this to keep flavor text, genital sizes etc. + for(var/key in new_features) + features[key] = new_features[key] + mutant_bodyparts = pref_species.get_random_mutant_bodyparts(features) + body_markings = pref_species.get_random_body_markings(features) + +//This proc makes sure that we only have the parts that the species should have, add missing ones, remove extra ones(should any be changed) +//Also, this handles missing color keys +/datum/preferences/proc/validate_species_parts() + if(!pref_species) + return + + var/list/target_bodyparts = pref_species.default_mutant_bodyparts.Copy() + + //Remove all "extra" accessories + for(var/key in mutant_bodyparts) + if(!GLOB.sprite_accessories[key]) //That accessory no longer exists, remove it + mutant_bodyparts -= key + continue + if(!pref_species.default_mutant_bodyparts[key]) + mutant_bodyparts -= key + continue + if(!GLOB.sprite_accessories[key][mutant_bodyparts[key][MUTANT_INDEX_NAME]]) //The individual accessory no longer exists + mutant_bodyparts[key][MUTANT_INDEX_NAME] = pref_species.default_mutant_bodyparts[key] + validate_color_keys_for_part(key) //Validate the color count of each accessory that wasnt removed + + //Add any missing accessories + for(var/key in target_bodyparts) + if(!mutant_bodyparts[key]) + var/datum/sprite_accessory/SA + if(target_bodyparts[key] == ACC_RANDOM) + SA = random_accessory_of_key_for_species(key, pref_species) + else + SA = GLOB.sprite_accessories[key][target_bodyparts[key]] + var/final_list = list() + final_list[MUTANT_INDEX_NAME] = SA.name + final_list[MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(features, pref_species) + mutant_bodyparts[key] = final_list + + if(!allow_advanced_colors) + reset_colors() + +/datum/preferences/proc/validate_color_keys_for_part(key) + var/datum/sprite_accessory/SA = GLOB.sprite_accessories[key][mutant_bodyparts[key][MUTANT_INDEX_NAME]] + var/list/colorlist = mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] + if(SA.color_src == USE_MATRIXED_COLORS && colorlist.len != 3) + mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(features, pref_species) + else if (SA.color_src == USE_ONE_COLOR && colorlist.len != 1) + mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(features, pref_species) + +/datum/preferences/proc/set_new_species(new_species_path) + pref_species = new new_species_path() + var/list/new_features = pref_species.get_random_features() //We do this to keep flavor text, genital sizes etc. + for(var/key in new_features) + features[key] = new_features[key] + mutant_bodyparts = pref_species.get_random_mutant_bodyparts(features) + body_markings = pref_species.get_random_body_markings(features) + +/datum/preferences/proc/reset_colors() + for(var/key in mutant_bodyparts) + var/datum/sprite_accessory/SA = GLOB.sprite_accessories[key][mutant_bodyparts[key][MUTANT_INDEX_NAME]] + if(SA.always_color_customizable) + continue + mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(features, pref_species) + + for(var/zone in body_markings) + var/list/bml = body_markings[zone] + for(var/key in bml) + var/datum/body_marking/BM = GLOB.body_markings[key] + bml[key] = BM.get_default_color(features, pref_species) + +/datum/preferences/proc/random_species() + var/random_species_type = GLOB.species_list[pick(GLOB.roundstart_races)] + set_new_species(random_species_type) + if(randomise[RANDOM_NAME]) + real_name = pref_species.random_name(gender,1) + +/datum/preferences/proc/update_preview_icon() + // Determine what job is marked as 'High' priority, and dress them up as such. + var/datum/job/previewJob + var/highest_pref = 0 + for(var/job in job_preferences) + if(job_preferences[job] > highest_pref) + previewJob = SSjob.GetJob(job) + highest_pref = job_preferences[job] + + if(previewJob) + // Silicons only need a very basic preview since there is no customization for them. + if(istype(previewJob,/datum/job/ai)) + parent.show_character_previews(image('icons/mob/ai.dmi', icon_state = resolve_ai_icon(preferred_ai_core_display), dir = SOUTH)) + return + if(istype(previewJob,/datum/job/cyborg)) + parent.show_character_previews(image('icons/mob/robots.dmi', icon_state = "robot", dir = SOUTH)) + return + + // Set up the dummy for its photoshoot + var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES) + copy_to(mannequin, 1, TRUE, TRUE) + + switch(preview_pref) + if(PREVIEW_PREF_JOB) + if(previewJob) + mannequin.job = previewJob.title + previewJob.equip(mannequin, TRUE, preference_source = parent) + mannequin.underwear_visibility = NONE + mannequin.update_body() //Unfortunately, due to a certain case we need to update this just in case + if(PREVIEW_PREF_LOADOUT) + mannequin.underwear_visibility = NONE + equip_preference_loadout(mannequin, TRUE, previewJob) + mannequin.underwear_visibility = NONE + mannequin.update_body() + if(PREVIEW_PREF_NAKED) + mannequin.underwear_visibility = UNDERWEAR_HIDE_UNDIES | UNDERWEAR_HIDE_SHIRT | UNDERWEAR_HIDE_SOCKS + mannequin.update_body() //Unfortunately, due to a certain case we need to update this just in case + + COMPILE_OVERLAYS(mannequin) + parent.show_character_previews(new /mutable_appearance(mannequin)) + unset_busy_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES) + +/datum/preferences/proc/equip_preference_loadout(mob/living/carbon/human/H, just_preview = FALSE, datum/job/choosen_job) + if(!ishuman(H)) + return + var/list/items_to_pack = list() + for(var/item_name in loadout) + var/datum/loadout_item/LI = GLOB.loadout_items[item_name] + var/obj/item/ITEM = LI.get_spawned_item(loadout[item_name]) + //Skip the item if the job doesn't match, but only if that not used for the preview + if(!just_preview && (choosen_job && LI.restricted_roles && !(choosen_job.title in LI.restricted_roles))) + continue + if(!H.equip_to_appropriate_slot(ITEM)) + if(!just_preview) + items_to_pack += ITEM + //Here we stick it into a bag, if possible + if(!H.equip_to_slot_if_possible(ITEM, ITEM_SLOT_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) + //Otherwise - on the ground + ITEM.forceMove(get_turf(H)) + else + qdel(ITEM) + return items_to_pack + +//This needs to be a seperate proc because the character could not have the proper backpack during the moment of loadout equip +/datum/preferences/proc/add_packed_items(mob/living/carbon/human/H, list/packed_items) + //Here we stick loadout items that couldn't be equipped into a bag. + for(var/item in packed_items) + var/obj/item/ITEM = item + if(!H.equip_to_slot_if_possible(ITEM, ITEM_SLOT_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) + //Otherwise - on the ground + ITEM.forceMove(get_turf(H)) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm new file mode 100644 index 00000000000..2440e21ff1c --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm @@ -0,0 +1,548 @@ +/datum/sprite_accessory + ///Unique key of an accessroy. All tails should have "tail", ears "ears" etc. + var/key = null + ///If an accessory is special, it wont get included in the normal accessory lists + var/special = FALSE + var/list/recommended_species + ///Which color we default to on acquisition of the accessory (such as switching species, default color for character customization etc) + ///You can also put down a a HEX color, to be used instead as the default + var/default_color + ///Set this to a name, then the accessory will be shown in preferences, if a species can have it. Most accessories have this + ///Notable things that have it set to FALSE are things that need special setup, such as genitals + var/generic + + var/special_render_case + + color_src = USE_ONE_COLOR + + ///This is used to determine whether an accessory gets added to someone. This is important for accessories that are "None", which should have this set to false + var/factual = TRUE + + ///Use this as a typepath to an organ that this sprite_accessory will be associated. Make sure the organ has 'mutantpart_info' set properly. + var/organ_type + + ///Set this to true to make an accessory appear as color customizable in preferences despite advanced color settings being off, will also prevent the accessory from being reset + var/always_color_customizable + + var/special_x_dimension + + var/special_icon_case + + var/extra = FALSE + var/extra_color_src + var/extra2 = FALSE + var/extra2_color_src + +/datum/sprite_accessory/New() + if(!default_color) + switch(color_src) + if(USE_ONE_COLOR) + default_color = DEFAULT_PRIMARY + if(USE_MATRIXED_COLORS) + default_color = DEFAULT_MATRIXED + else + default_color = "FFF" + if(name == "None") + factual = FALSE + if(color_src == USE_MATRIXED_COLORS && default_color != DEFAULT_MATRIXED) + default_color = DEFAULT_MATRIXED + +/datum/sprite_accessory/proc/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/BP) + return FALSE + +/datum/sprite_accessory/proc/get_special_render_state(mob/living/carbon/human/H, icon_state) + return null + +/datum/sprite_accessory/proc/get_special_icon(mob/living/carbon/human/H) + return null + +/datum/sprite_accessory/proc/get_special_x_dimension(mob/living/carbon/human/H) + return 0 + +/datum/sprite_accessory/proc/get_default_color(var/list/features, var/datum/species/pref_species) //Needs features for the color information + var/list/colors + switch(default_color) + if(DEFAULT_PRIMARY) + colors = list(features["mcolor"]) + if(DEFAULT_SECONDARY) + colors = list(features["mcolor2"]) + if(DEFAULT_TERTIARY) + colors = list(features["mcolor3"]) + if(DEFAULT_MATRIXED) + colors = list(features["mcolor"], features["mcolor2"], features["mcolor3"]) + if(DEFAULT_SKIN_OR_PRIMARY) + if(pref_species && pref_species.use_skintones) + colors = list(features["skin_color"]) + else + colors = list(features["mcolor"]) + else + colors = list(default_color) + + return colors + +/datum/sprite_accessory/moth_wings + key = "moth_wings" + generic = "Moth wings" + +/datum/sprite_accessory/moth_wings/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if((H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(H.dna.species, H.wear_suit.species_exception)))) + return TRUE + return FALSE + +/datum/sprite_accessory/moth_markings + key = "moth_markings" + generic = "Moth markings" + +/datum/sprite_accessory/spines + key = "spines" + generic = "Spines" + icon = 'modular_skyrat/modules/customization/icons/mob/mutant_bodyparts.dmi' + special_render_case = TRUE + recommended_species = list("lizard") + default_color = DEFAULT_SECONDARY + +/datum/sprite_accessory/spines/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)) + return TRUE + return FALSE + +/datum/sprite_accessory/spines/get_special_render_state(mob/living/carbon/human/H, icon_state) + var/obj/item/organ/tail/T = H.getorganslot(ORGAN_SLOT_TAIL) + if(T && T.wagging) + icon_state += "_wagging" + return icon_state + +/datum/sprite_accessory/caps + key = "caps" + generic = "Caps" + +/datum/sprite_accessory/frills + key = "frills" + generic = "Frills" + default_color = DEFAULT_SECONDARY + +/datum/sprite_accessory/frills/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.head && (H.head.flags_inv & HIDEEARS) || !HD || HD.status == BODYPART_ROBOTIC) + return TRUE + return FALSE + +/datum/sprite_accessory/horns + key = "horns" + generic = "Horns" + +/datum/sprite_accessory/horns/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC) + return TRUE + return FALSE + +/datum/sprite_accessory/body_markings + key = "body_markings" + generic = "Body Markings" + default_color = DEFAULT_TERTIARY + +/datum/sprite_accessory/legs + key = "legs" + generic = "Leg Type" + color_src = null + +/datum/sprite_accessory/socks + icon = 'modular_skyrat/modules/customization/icons/mob/clothing/underwear.dmi' + use_static = TRUE + +/datum/sprite_accessory/socks/socks_knee + name = "Knee-high" + icon_state = "socks_knee" + use_static = null + +/datum/sprite_accessory/socks/striped_knee + name = "Knee-high - Striped" + icon_state = "striped_knee" + use_static = null + +/datum/sprite_accessory/socks/thin_knee + name = "Knee-high - Thin" + icon_state = "thin_knee" + use_static = null + +/datum/sprite_accessory/socks/socks_norm + name = "Normal" + icon_state = "socks_norm" + use_static = null + +/datum/sprite_accessory/socks/socks_short + name = "Short" + icon_state = "socks_short" + use_static = null + +/datum/sprite_accessory/socks/socks_thigh + name = "Thigh-high" + icon_state = "socks_thigh" + use_static = null + +/datum/sprite_accessory/socks/bee_thigh + name = "Thigh-high - Bee (Old)" + icon_state = "bee_thigh_old" + +/datum/sprite_accessory/socks/bee_knee + name = "Knee-high - Bee (Old)" + icon_state = "bee_knee_old" + +/datum/sprite_accessory/underwear/socks/christmas_norm + name = "Normal - Christmas" + icon_state = "christmas_norm" + +/datum/sprite_accessory/underwear/socks/candycaner_norm + name = "Normal - Red Candy Cane" + icon_state = "candycaner_norm" + +/datum/sprite_accessory/underwear/socks/candycaneg_norm + name = "Normal - Green Candy Cane" + icon_state = "candycaneg_norm" + +/datum/sprite_accessory/socks/christmas_knee + name = "Knee-High - Christmas" + icon_state = "christmas_knee" + +/datum/sprite_accessory/socks/candycaner_knee + name = "Knee-High - Red Candy Cane" + icon_state = "candycaner_knee" + +/datum/sprite_accessory/socks/candycaneg_knee + name = "Knee-High - Green Candy Cane" + icon_state = "candycaneg_knee" + +/datum/sprite_accessory/socks/christmas_thigh + name = "Thigh-high - Christmas" + icon_state = "christmas_thigh" + +/datum/sprite_accessory/socks/candycaner_thigh + name = "Thigh-high - Red Candy Cane" + icon_state = "candycaner_thigh" + +/datum/sprite_accessory/socks/candycaneg_thigh + name = "Thigh-high - Green Candy Cane" + icon_state = "candycaneg_thigh" + +/datum/sprite_accessory/socks/rainbow_knee + name = "Knee-high - Rainbow" + icon_state = "rainbow_knee" + +/datum/sprite_accessory/socks/rainbow_thigh + name = "Thigh-high - Rainbow" + icon_state = "rainbow_thigh" + + +/datum/sprite_accessory/underwear + icon = 'modular_skyrat/modules/customization/icons/mob/clothing/underwear.dmi' + ///Whether the underwear uses a special sprite for digitigrade style (i.e. briefs, not panties). Adds a "_d" suffix to the icon state + var/has_digitigrade = FALSE + +/datum/sprite_accessory/underwear/male_bee + name = "Boxers - Bee" + icon_state = "bee_shorts" + has_digitigrade = TRUE + gender = MALE + use_static = TRUE + +/datum/sprite_accessory/underwear/female_beekini + name = "Panties - Bee-kini" + icon_state = "panties_bee-kini" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/panties + name = "Panties" + icon_state = "panties" + gender = FEMALE + +/datum/sprite_accessory/underwear/panties_alt + name = "Panties - Alt" + icon_state = "panties_alt" + gender = FEMALE + +/datum/sprite_accessory/underwear/fishnet_lower + name = "Panties - Fishnet" + icon_state = "fishnet_lower" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/female_beekini + name = "Panties - Bee-kini" + icon_state = "panties_bee-kini" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/female_commie + name = "Panties - Commie" + icon_state = "panties_commie" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/female_usastripe + name = "Panties - Freedom" + icon_state = "panties_assblastusa" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/female_kinky + name = "Panties - Kinky Black" + icon_state = "panties_kinky" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/panties_uk + name = "Panties - UK" + icon_state = "panties_uk" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/panties_neko + name = "Panties - Neko" + icon_state = "panties_neko" + gender = FEMALE + +/datum/sprite_accessory/underwear/panties_slim + name = "Panties - Slim" + icon_state = "panties_slim" + gender = FEMALE + +/datum/sprite_accessory/underwear/striped_panties + name = "Panties - Striped" + icon_state = "striped_panties" + gender = FEMALE + +/datum/sprite_accessory/underwear/panties_swimsuit + name = "Panties - Swimsuit" + icon_state = "panties_swimming" + gender = FEMALE + +/datum/sprite_accessory/underwear/panties_thin + name = "Panties - Thin" + icon_state = "panties_thin" + gender = FEMALE + +/datum/sprite_accessory/underwear/longjon + name = "Long John Bottoms" + icon_state = "ljonb" + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/swimsuit_red + name = "Swimsuit, One Piece - Red" + icon_state = "swimming_red" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/swimsuit + name = "Swimsuit, One Piece - Black" + icon_state = "swimming_black" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/swimsuit_blue + name = "Swimsuit, One Piece - Striped Blue" + icon_state = "swimming_blue" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/thong + name = "Thong" + icon_state = "thong" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/underwear/thong_babydoll + name = "Thong - Alt" + icon_state = "thong_babydoll" + gender = FEMALE + + +/datum/sprite_accessory/underwear/male_briefs + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/male_boxers + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/male_stripe + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/male_midway + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/male_longjohns + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/male_hearts + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/male_commie + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/male_usastripe + has_digitigrade = TRUE + +/datum/sprite_accessory/underwear/male_uk + has_digitigrade = TRUE + + +/datum/sprite_accessory/undershirt + icon = 'modular_skyrat/modules/customization/icons/mob/clothing/underwear.dmi' + use_static = TRUE + +/datum/sprite_accessory/undershirt/tanktop_alt + name = "Tank Top - Alt" + icon_state = "tanktop_alt" + use_static = null + +/datum/sprite_accessory/undershirt/tanktop_midriff + name = "Tank Top - Midriff" + icon_state = "tank_midriff" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/tanktop_midriff_alt + name = "Tank Top - Midriff Halterneck" + icon_state = "tank_midriff_alt" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/tankstripe + name = "Tank Top - Striped" + icon_state = "tank_stripes" + use_static = TRUE + +/datum/sprite_accessory/undershirt/tank_top_sun + name = "Tank top - Sun" + icon_state = "tank_sun" + use_static = TRUE + +/datum/sprite_accessory/undershirt/babydoll + name = "Baby-Doll" + icon_state = "babydoll" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/bra + name = "Bra" + icon_state = "bra" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/bra_alt + name = "Bra - Alt" + icon_state = "bra_alt" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/bra_thin + name = "Bra - Thin" + icon_state = "bra_thin" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/bra_kinky + name = "Bra - Kinky Black" + icon_state = "bra_kinky" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/undershirt/bra_freedom + name = "Bra - Freedom" + icon_state = "bra_assblastusa" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/undershirt/bra_commie + name = "Bra - Commie" + icon_state = "bra_commie" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/undershirt/bra_beekini + name = "Bra - Bee-kini" + icon_state = "bra_bee-kini" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/undershirt/bra_uk + name = "Bra - UK" + icon_state = "bra_uk" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/undershirt/bra_neko + name = "Bra - Neko" + icon_state = "bra_neko" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/halterneck_bra + name = "Bra - Halterneck" + icon_state = "halterneck_bra" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/sports_bra + name = "Bra, Sports" + icon_state = "sports_bra" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/sports_bra_alt + name = "Bra, Sports - Alt" + icon_state = "sports_bra_alt" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/bra_strapless + name = "Bra, Strapless" + icon_state = "bra_strapless" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/bra_strapless_alt + name = "Bra, Strapless - Alt" + icon_state = "bra_blue" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/striped_bra + name = "Bra - Striped" + icon_state = "striped_bra" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/fishnet_sleeves + name = "Fishnet - sleeves" + icon_state = "fishnet_sleeves" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/undershirt/fishnet_gloves + name = "Fishnet - gloves" + icon_state = "fishnet_gloves" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/undershirt/fishnet_base + name = "Fishnet - top" + icon_state = "fishnet_body" + gender = FEMALE + use_static = TRUE + +/datum/sprite_accessory/undershirt/swimsuit + name = "Swimsuit Top" + icon_state = "bra_swimming" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/swimsuit_alt + name = "Swimsuit Top - Strapless" + icon_state = "bra_swimming_alt" + gender = FEMALE + use_static = null + +/datum/sprite_accessory/undershirt/tubetop + name = "Tube Top" + icon_state = "tubetop" + gender = FEMALE + use_static = null diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ears.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ears.dm new file mode 100644 index 00000000000..fd1f00a256c --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ears.dm @@ -0,0 +1,184 @@ +/datum/sprite_accessory/ears + key = "ears" + generic = "Ears" + organ_type = /obj/item/organ/ears/mutant + +/datum/sprite_accessory/ears/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC) + return TRUE + return FALSE + +/datum/sprite_accessory/ears/mutant + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/ears.dmi' + organ_type = /obj/item/organ/ears/mutant + color_src = USE_MATRIXED_COLORS + recommended_species = list("mammal", "human", "felinid") + +/datum/sprite_accessory/ears/mutant/none + name = "None" + icon_state = "none" + color_src = null + factual = FALSE + +/datum/sprite_accessory/ears/mutant/axolotl + name = "Axolotl" + icon_state = "axolotl" + +/datum/sprite_accessory/ears/mutant/bat + name = "Bat" + icon_state = "bat" + +/datum/sprite_accessory/ears/mutant/bear + name = "Bear" + icon_state = "bear" + +/datum/sprite_accessory/ears/mutant/bigwolf + name = "Big Wolf" + icon_state = "bigwolf" + +/datum/sprite_accessory/ears/mutant/bigwolfinner + name = "Big Wolf (ALT)" + icon_state = "bigwolfinner" + extra = TRUE + extra_color_src = NONE + +/datum/sprite_accessory/ears/mutant/bigwolfdark //alphabetical sort ignored here for ease-of-use + name = "Dark Big Wolf" + icon_state = "bigwolfdark" + +/datum/sprite_accessory/ears/mutant/bigwolfinnerdark + name = "Dark Big Wolf (ALT)" + icon_state = "bigwolfinnerdark" + extra = TRUE + extra_color_src = NONE + +/datum/sprite_accessory/ears/mutant/bunny + name = "Bunny" + icon_state = "bunny" + +/datum/sprite_accessory/ears/mutant/catbig + name = "Cat, Big" + icon_state = "catbig" + +/datum/sprite_accessory/ears/mutant/cow + name = "Cow" + icon_state = "cow" + +/datum/sprite_accessory/ears/mutant/curled + name = "Curled Horn" + icon_state = "horn1" + color_src = USE_ONE_COLOR + default_color = DEFAULT_TERTIARY + +/datum/sprite_accessory/ears/mutant/deer + name = "Deer" + icon_state = "deer" + color_src = USE_ONE_COLOR + default_color = DEFAULT_TERTIARY + +/datum/sprite_accessory/ears/mutant/eevee + name = "Eevee" + icon_state = "eevee" + +/datum/sprite_accessory/ears/mutant/elf + name = "Elf" + icon_state = "elf" + color_src = USE_ONE_COLOR + default_color = DEFAULT_SKIN_OR_PRIMARY + +/datum/sprite_accessory/ears/mutant/elephant + name = "Elephant" + icon_state = "elephant" + +/datum/sprite_accessory/ears/mutant/fennec + name = "Fennec" + icon_state = "fennec" + +/datum/sprite_accessory/ears/mutant/fish + name = "Fish" + icon_state = "fish" + +/datum/sprite_accessory/ears/mutant/fox + name = "Fox" + icon_state = "fox" + +/datum/sprite_accessory/ears/mutant/husky + name = "Husky" + icon_state = "wolf" + +/datum/sprite_accessory/ears/mutant/jellyfish + name = "Jellyfish" + icon_state = "jellyfish" + color_src = HAIR + +/datum/sprite_accessory/ears/mutant/kangaroo + name = "kangaroo" + icon_state = "kangaroo" + +/datum/sprite_accessory/ears/mutant/lab + name = "Dog, Long" + icon_state = "lab" + +/datum/sprite_accessory/ears/mutant/murid + name = "Murid" + icon_state = "murid" + +/datum/sprite_accessory/ears/mutant/otie + name = "Otusian" + icon_state = "otie" + +/datum/sprite_accessory/ears/mutant/rabbit + name = "Rabbit" + icon_state = "rabbit" + +/datum/sprite_accessory/ears/mutant/pede + name = "Scolipede" + icon_state = "pede" + +/datum/sprite_accessory/ears/mutant/sergal + name = "Sergal" + icon_state = "sergal" + +/datum/sprite_accessory/ears/mutant/skunk + name = "skunk" + icon_state = "skunk" + +/datum/sprite_accessory/ears/mutant/squirrel + name = "Squirrel" + icon_state = "squirrel" + +/datum/sprite_accessory/ears/mutant/wolf + name = "Wolf" + icon_state = "wolf" + +/datum/sprite_accessory/ears/mutant/antenna_simple1 + name = "Insect antenna (coloring 2)" + icon_state = "antenna_simple1" + +/datum/sprite_accessory/ears/mutant/antenna_simple1_v2 + name = "Insect antenna (coloring 3)" + icon_state = "antenna_simple1v2" + +/datum/sprite_accessory/ears/mutant/antenna_simple2 + name = "Insect antenna 2 (coloring 2)" + icon_state = "antenna_simple2" + +/datum/sprite_accessory/ears/mutant/antenna_simple2_v2 + name = "Insect antenna 2 (coloring 3)" + icon_state = "antenna_simple2v2" + +/datum/sprite_accessory/ears/mutant/antenna_fuzzball + name = "Fuzzball antenna (coloring 2+3)" + icon_state = "antenna_fuzzball" + +/datum/sprite_accessory/ears/mutant/antenna_fuzzball_v2 + name = "Fuzzball antenna (coloring 3+1)" + icon_state = "antenna_fuzzballv2" + +/datum/sprite_accessory/ears/mutant/cobrahood + name = "Cobra Hood" + icon_state = "cobrahood" + +/datum/sprite_accessory/ears/mutant/cobrahoodears + name = "Cobra Hood (Ears)" + icon_state = "cobraears" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/frills.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/frills.dm new file mode 100644 index 00000000000..84768a740db --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/frills.dm @@ -0,0 +1,11 @@ +/datum/sprite_accessory/frills/cobrahood + name = "Cobra Hood" + icon_state = "cobrahood" + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/frills.dmi' + color_src = USE_MATRIXED_COLORS + +/datum/sprite_accessory/frills/cobrahoodears + name = "Cobra Hood (Ears)" + icon_state = "cobraears" + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/frills.dmi' + color_src = USE_MATRIXED_COLORS diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm new file mode 100644 index 00000000000..88a08fb636c --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm @@ -0,0 +1,230 @@ +/datum/sprite_accessory/genital + special_render_case = TRUE + var/associated_organ_slot + +/datum/sprite_accessory/genital/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + var/obj/item/organ/genital/badonkers = H.getorganslot(associated_organ_slot) + if(!badonkers) + return TRUE + switch(badonkers.visibility_preference) + if(GENITAL_ALWAYS_SHOW) + return FALSE + if(GENITAL_HIDDEN_BY_CLOTHES) + if(H.w_uniform || H.wear_suit) + return TRUE + else + return FALSE + else + return TRUE + +/datum/sprite_accessory/genital/get_special_render_state(mob/living/carbon/human/H, icon_state) + var/obj/item/organ/genital/gen = H.getorganslot(associated_organ_slot) + if(gen) + return "[icon_state]_[gen.sprite_suffix]" + else + return null + +/datum/sprite_accessory/genital/penis + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/penis_onmob.dmi' + organ_type = /obj/item/organ/genital/penis + associated_organ_slot = ORGAN_SLOT_PENIS + key = "penis" + always_color_customizable = TRUE + center = TRUE + special_icon_case = TRUE + special_x_dimension = TRUE + default_color = DEFAULT_SKIN_OR_PRIMARY + +/datum/sprite_accessory/genital/penis/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.underwear != "Nude" && !(H.underwear_visibility & UNDERWEAR_HIDE_UNDIES)) + return TRUE + . = ..() + +/datum/sprite_accessory/genital/penis/get_special_icon(mob/living/carbon/human/H) + var/returned = icon + if(H.dna.species.mutant_bodyparts["taur"] && H.dna.features["penis_taur_mode"]) + var/datum/sprite_accessory/taur/SP = GLOB.sprite_accessories["taur"][H.dna.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]] + if(!(SP.taur_mode & STYLE_TAUR_SNAKE)) + returned = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/taur_penis_onmob.dmi' + return returned + +/datum/sprite_accessory/genital/penis/get_special_x_dimension(mob/living/carbon/human/H) + var/returned = dimension_x + if(H.dna.species.mutant_bodyparts["taur"] && H.dna.features["penis_taur_mode"]) + var/datum/sprite_accessory/taur/SP = GLOB.sprite_accessories["taur"][H.dna.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]] + if(!(SP.taur_mode & STYLE_TAUR_SNAKE)) + returned = 64 + return returned + +/datum/sprite_accessory/genital/penis/none + icon_state = "none" + name = "None" + factual = FALSE + color_src = null + +/datum/sprite_accessory/genital/penis/human + icon_state = "human" + name = "Human" + default_color = DEFAULT_SKIN_OR_PRIMARY + +/datum/sprite_accessory/genital/penis/knotted + icon_state = "knotted" + name = "Knotted" + +/datum/sprite_accessory/genital/penis/flared + icon_state = "flared" + name = "Flared" + +/datum/sprite_accessory/genital/penis/barbknot + icon_state = "barbknot" + name = "Barbed, Knotted" + +/datum/sprite_accessory/genital/penis/tapered + icon_state = "tapered" + name = "Tapered" + +/datum/sprite_accessory/genital/penis/tentacle + icon_state = "tentacle" + name = "Tentacled" + +/datum/sprite_accessory/genital/penis/hemi + icon_state = "hemi" + name = "Hemi" + +/datum/sprite_accessory/genital/penis/hemiknot + icon_state = "hemiknot" + name = "Knotted Hemi" + +/datum/sprite_accessory/genital/testicles + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/testicles_onmob.dmi' + organ_type = /obj/item/organ/genital/testicles + associated_organ_slot = ORGAN_SLOT_TESTICLES + key = "testicles" + var/has_size = TRUE + +/datum/sprite_accessory/genital/testicles/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.underwear != "Nude" && !(H.underwear_visibility & UNDERWEAR_HIDE_UNDIES)) + return TRUE + . = ..() + +/datum/sprite_accessory/genital/testicles/none + icon_state = "none" + name = "None" + factual = FALSE + color_src = null + +/datum/sprite_accessory/genital/testicles/pair + name = "Pair" + icon_state = "pair" + +/datum/sprite_accessory/genital/testicles/internal + name = "Internal" + icon_state = "none" + color_src = null + has_size = FALSE + +/datum/sprite_accessory/genital/vagina + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/vagina_onmob.dmi' + organ_type = /obj/item/organ/genital/vagina + associated_organ_slot = ORGAN_SLOT_VAGINA + key = "vagina" + always_color_customizable = TRUE + default_color = "fcc" + var/alt_aroused = TRUE + +/datum/sprite_accessory/genital/vagina/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.underwear != "Nude" && !(H.underwear_visibility & UNDERWEAR_HIDE_UNDIES)) + return TRUE + . = ..() + + +/datum/sprite_accessory/genital/vagina/get_special_render_state(mob/living/carbon/human/H, icon_state) + var/obj/item/organ/genital/gen = H.getorganslot(associated_organ_slot) + if(gen) + return "[icon_state]_[gen.aroused]" + else + return null + +/datum/sprite_accessory/genital/vagina/none + icon_state = "none" + name = "None" + factual = FALSE + color_src = null + +/datum/sprite_accessory/genital/vagina/human + icon_state = "human" + name = "Human" + +/datum/sprite_accessory/genital/vagina/tentacles + icon_state = "tentacle" + name = "Tentacle" + +/datum/sprite_accessory/genital/vagina/dentata + icon_state = "dentata" + name = "Dentata" + +/datum/sprite_accessory/genital/vagina/hairy + icon_state = "hairy" + name = "Hairy" + alt_aroused = FALSE + +/datum/sprite_accessory/genital/vagina/spade + icon_state = "spade" + name = "Spade" + alt_aroused = FALSE + +/datum/sprite_accessory/genital/vagina/furred + icon_state = "furred" + name = "Furred" + alt_aroused = FALSE + +/datum/sprite_accessory/genital/vagina/gaping + icon_state = "gaping" + name = "Gaping" + + +/datum/sprite_accessory/genital/womb + organ_type = /obj/item/organ/genital/womb + associated_organ_slot = ORGAN_SLOT_WOMB + key = "womb" + +/datum/sprite_accessory/genital/womb/none + icon_state = "none" + name = "None" + factual = FALSE + color_src = null + +/datum/sprite_accessory/genital/womb/normal + icon_state = "none" + name = "Normal" + color_src = null + +/datum/sprite_accessory/genital/breasts + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/genitals/breasts_onmob.dmi' + organ_type = /obj/item/organ/genital/breasts + associated_organ_slot = ORGAN_SLOT_BREASTS + key = "breasts" + default_color = DEFAULT_SKIN_OR_PRIMARY + +/datum/sprite_accessory/genital/breasts/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.undershirt != "Nude" && !(H.underwear_visibility & UNDERWEAR_HIDE_SHIRT)) + return TRUE + . = ..() + +/datum/sprite_accessory/genital/breasts/none + icon_state = "none" + name = "None" + factual = FALSE + color_src = null + +/datum/sprite_accessory/genital/breasts/pair + icon_state = "pair" + name = "Pair" + +/datum/sprite_accessory/genital/breasts/quad + icon_state = "quad" + name = "Quad" + +/datum/sprite_accessory/genital/breasts/sextuple + icon_state = "sextuple" + name = "Sextuple" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ipc.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ipc.dm new file mode 100644 index 00000000000..edbe35a2c93 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ipc.dm @@ -0,0 +1,215 @@ + +/****************************************** +************** IPC SCREENS **************** +*******************************************/ +/datum/sprite_accessory/screen + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/ipc_screens.dmi' + color_src = null + key = "ipc_screen" + generic = "Screen" + +/datum/sprite_accessory/screen/blank + name = "Blank" + icon_state = "blank" + +/datum/sprite_accessory/screen/pink + name = "Pink" + icon_state = "pink" + +/datum/sprite_accessory/screen/green + name = "Green" + icon_state = "green" + +/datum/sprite_accessory/screen/red + name = "Red" + icon_state = "red" + +/datum/sprite_accessory/screen/blue + name = "Blue" + icon_state = "blue" + +/datum/sprite_accessory/screen/yellow + name = "Yellow" + icon_state = "yellow" + +/datum/sprite_accessory/screen/shower + name = "Shower" + icon_state = "shower" + +/datum/sprite_accessory/screen/nature + name = "Nature" + icon_state = "nature" + +/datum/sprite_accessory/screen/eight + name = "Eight" + icon_state = "eight" + +/datum/sprite_accessory/screen/goggles + name = "Goggles" + icon_state = "goggles" + +/datum/sprite_accessory/screen/heart + name = "Heart" + icon_state = "heart" + +/datum/sprite_accessory/screen/monoeye + name = "Mono eye" + icon_state = "monoeye" + +/datum/sprite_accessory/screen/breakout + name = "Breakout" + icon_state = "breakout" + +/datum/sprite_accessory/screen/purple + name = "Purple" + icon_state = "purple" + +/datum/sprite_accessory/screen/scroll + name = "Scroll" + icon_state = "scroll" + +/datum/sprite_accessory/screen/console + name = "Console" + icon_state = "console" + +/datum/sprite_accessory/screen/rgb + name = "RGB" + icon_state = "rgb" + +/datum/sprite_accessory/screen/golglider + name = "Gol Glider" + icon_state = "golglider" + +/datum/sprite_accessory/screen/rainbow + name = "Rainbow" + icon_state = "rainbow" + +/datum/sprite_accessory/screen/sunburst + name = "Sunburst" + icon_state = "sunburst" + +/datum/sprite_accessory/screen/static + name = "Static" + icon_state = "static" + +//Oracle Station sprites + +/datum/sprite_accessory/screen/bsod + name = "BSOD" + icon_state = "bsod" + +/datum/sprite_accessory/screen/redtext + name = "Red Text" + icon_state = "retext" + +/datum/sprite_accessory/screen/sinewave + name = "Sine wave" + icon_state = "sinewave" + +/datum/sprite_accessory/screen/squarewave + name = "Square wave" + icon_state = "squarwave" + +/datum/sprite_accessory/screen/ecgwave + name = "ECG wave" + icon_state = "ecgwave" + +/datum/sprite_accessory/screen/eyes + name = "Eyes" + icon_state = "eyes" + +/datum/sprite_accessory/screen/textdrop + name = "Text drop" + icon_state = "textdrop" + +/datum/sprite_accessory/screen/stars + name = "Stars" + icon_state = "stars" + + +/****************************************** +************** IPC Antennas *************** +*******************************************/ + +/datum/sprite_accessory/antenna + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/ipc_antennas.dmi' + color_src = USE_ONE_COLOR + default_color = DEFAULT_SECONDARY + recommended_species = list("ipc") + key = "ipc_antenna" + generic = "Antenna" + +/datum/sprite_accessory/antenna/none + name = "None" + icon_state = "None" + recommended_species = null + +/datum/sprite_accessory/antenna/antennae + name = "Angled Antennae" + icon_state = "antennae" + +/datum/sprite_accessory/antenna/tvantennae + name = "TV Antennae" + icon_state = "tvantennae" + +/datum/sprite_accessory/antenna/cyberhead + name = "Cyberhead" + icon_state = "cyberhead" + +/datum/sprite_accessory/antenna/antlers + name = "Antlers" + icon_state = "antlers" + +/datum/sprite_accessory/antenna/crowned + name = "Crowned" + icon_state = "crowned" + +//Chasises - snowflake phantom accessory for choosing chassises +/datum/sprite_accessory/ipc_chassis + icon = null + icon_state = "ipc" + color_src = null + factual = FALSE + key = "ipc_chassis" + generic = "Chassis Type" + +/datum/sprite_accessory/ipc_chassis/mcgreyscale + name = "Morpheus Cyberkinetics(Greyscale)" + icon_state = "mcgipc" + color_src = 1 //Here it's used to tell apart greyscalling + +/datum/sprite_accessory/ipc_chassis/bishopcyberkinetics + name = "Bishop Cyberkinetics" + icon_state = "bshipc" + +/datum/sprite_accessory/ipc_chassis/bishopcyberkinetics2 + name = "Bishop Cyberkinetics 2.0" + icon_state = "bs2ipc" + +/datum/sprite_accessory/ipc_chassis/hephaestussindustries + name = "Hephaestus Industries" + icon_state = "hsiipc" + +/datum/sprite_accessory/ipc_chassis/hephaestussindustries2 + name = "Hephaestus Industries 2.0" + icon_state = "hi2ipc" + +/datum/sprite_accessory/ipc_chassis/shellguardmunitions + name = "Shellguard Munitions Standard Series" + icon_state = "sgmipc" + +/datum/sprite_accessory/ipc_chassis/wardtakahashimanufacturing + name = "Ward-Takahashi Manufacturing" + icon_state = "wtmipc" + +/datum/sprite_accessory/ipc_chassis/xionmanufacturinggroup + name = "Xion Manufacturing Group" + icon_state = "xmgipc" + +/datum/sprite_accessory/ipc_chassis/xionmanufacturinggroup2 + name = "Xion Manufacturing Group 2.0" + icon_state = "xm2ipc" + +/datum/sprite_accessory/ipc_chassis/zenghupharmaceuticals + name = "Zeng-Hu Pharmaceuticals" + icon_state = "zhpipc" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm new file mode 100644 index 00000000000..66bde2e0573 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm @@ -0,0 +1,292 @@ +/datum/sprite_accessory/snouts + key = "snout" + generic = "Snout" + var/use_muzzled_sprites = TRUE + +/datum/sprite_accessory/snouts/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) || (H.head && (H.head.flags_inv & HIDEFACE)) || !HD || HD.status == BODYPART_ROBOTIC) + return TRUE + return FALSE + +/datum/sprite_accessory/snouts/none + name = "None" + icon_state = "none" + use_muzzled_sprites = FALSE + factual = FALSE + +/datum/sprite_accessory/snouts/mammal + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/snouts.dmi' + color_src = USE_MATRIXED_COLORS + recommended_species = list("mammal") + +/datum/sprite_accessory/snouts/mammal/bird + name = "Beak" + icon_state = "bird" + +/datum/sprite_accessory/snouts/mammal/bigbeak + name = "Big Beak" + icon_state = "bigbeak" + +/datum/sprite_accessory/snouts/mammal/bug + name = "Bug" + icon_state = "bug" + color_src = USE_ONE_COLOR + extra2 = TRUE + extra2_color_src = MUTCOLORS3 + +/datum/sprite_accessory/snouts/mammal/elephant + name = "Elephant" + icon_state = "elephant" + extra = TRUE + extra_color_src = MUTCOLORS3 + +/datum/sprite_accessory/snouts/mammal/husky + name = "Husky" + icon_state = "husky" + +/datum/sprite_accessory/snouts/mammal/rhino + name = "Horn" + icon_state = "rhino" + extra = TRUE + extra = MUTCOLORS3 + +/datum/sprite_accessory/snouts/mammal/rodent + name = "Rodent" + icon_state = "rodent" + +/datum/sprite_accessory/snouts/mammal/lcanid + name = "Mammal, Long" + icon_state = "lcanid" + +/datum/sprite_accessory/snouts/mammal/lcanidalt + name = "Mammal, Long ALT" + icon_state = "lcanidalt" + +/datum/sprite_accessory/snouts/mammal/scanid + name = "Mammal, Short" + icon_state = "scanid" + +/datum/sprite_accessory/snouts/mammal/scanidalt + name = "Mammal, Short ALT" + icon_state = "scanidalt" + +/datum/sprite_accessory/snouts/mammal/scanidalt2 + name = "Mammal, Short ALT 2" + icon_state = "scanidalt2" + +/datum/sprite_accessory/snouts/mammal/wolf + name = "Mammal, Thick" + icon_state = "wolf" + +/datum/sprite_accessory/snouts/mammal/wolfalt + name = "Mammal, Thick ALT" + icon_state = "wolfalt" + +/datum/sprite_accessory/snouts/mammal/otie + name = "Otie" + icon_state = "otie" + +/*/datum/sprite_accessory/snouts/mammal/round + name = "Mammal Round" + icon_state = "round" + color_src = USE_ONE_COLOR + +/datum/sprite_accessory/snouts/mammal/roundlight + name = "Mammal Round + Light" + icon_state = "roundlight" + color_src = USE_ONE_COLOR*/ + +/datum/sprite_accessory/snouts/mammal/pede + name = "Scolipede" + icon_state = "pede" + +/datum/sprite_accessory/snouts/mammal/sergal + name = "Sergal" + icon_state = "sergal" + +/datum/sprite_accessory/snouts/mammal/shark + name = "Shark" + icon_state = "shark" + +/datum/sprite_accessory/snouts/mammal/hshark + name = "hShark" + icon_state = "hshark" + +/*/datum/sprite_accessory/snouts/mammal/sharp + name = "Mammal Sharp" + icon_state = "sharp" + color_src = USE_ONE_COLOR + +/datum/sprite_accessory/snouts/mammal/sharplight + name = "Mammal Sharp + Light" + icon_state = "sharplight" + color_src = USE_ONE_COLOR*/ + +/datum/sprite_accessory/snouts/mammal/toucan + name = "Toucan" + icon_state = "toucan" + +/datum/sprite_accessory/snouts/mammal/redpanda + name = "WahCoon" + icon_state = "wah" + +/datum/sprite_accessory/snouts/mammal/redpandaalt + name = "WahCoon ALT" + icon_state = "wahalt" + +/****************************************** +**************** Snouts ******************* +*************but higher up*****************/ + +/datum/sprite_accessory/snouts/mammal/fbird + name = "Beak (Top)" + icon_state = "fbird" + +/datum/sprite_accessory/snouts/mammal/fbigbeak + name = "Big Beak (Top)" + icon_state = "fbigbeak" + +/datum/sprite_accessory/snouts/mammal/fbug + name = "Bug (Top)" + icon_state = "fbug" + color_src = USE_ONE_COLOR + extra2 = TRUE + extra2_color_src = MUTCOLORS3 + +/datum/sprite_accessory/snouts/mammal/felephant + name = "Elephant (Top)" + icon_state = "felephant" + extra = TRUE + extra_color_src = MUTCOLORS3 + +/datum/sprite_accessory/snouts/mammal/frhino + name = "Horn (Top)" + icon_state = "frhino" + extra = TRUE + extra = MUTCOLORS3 + +/datum/sprite_accessory/snouts/mammal/fhusky + name = "Husky (Top)" + icon_state = "fhusky" + +/datum/sprite_accessory/snouts/mammal/flcanid + name = "Mammal, Long (Top)" + icon_state = "flcanid" + +/datum/sprite_accessory/snouts/mammal/flcanidalt + name = "Mammal, Long ALT (Top)" + icon_state = "flcanidalt" + +/datum/sprite_accessory/snouts/mammal/fscanid + name = "Mammal, Short (Top)" + icon_state = "fscanid" + +/datum/sprite_accessory/snouts/mammal/fscanidalt + name = "Mammal, Short ALT (Top)" + icon_state = "fscanidalt" + +/datum/sprite_accessory/snouts/mammal/fscanidalt2 + name = "Mammal, Short ALT 2 (Top)" + icon_state = "fscanidalt2" + +/datum/sprite_accessory/snouts/mammal/fwolf + name = "Mammal, Thick (Top)" + icon_state = "fwolf" + +/datum/sprite_accessory/snouts/mammal/fwolfalt + name = "Mammal, Thick ALT (Top)" + icon_state = "fwolfalt" + +/datum/sprite_accessory/snouts/mammal/fotie + name = "Otie (Top)" + icon_state = "fotie" + +/datum/sprite_accessory/snouts/mammal/frodent + name = "Rodent (Top)" + icon_state = "frodent" + +/*/datum/sprite_accessory/snouts/mammal/fround + name = "Mammal Round (Top)" + icon_state = "fround" + color_src = USE_ONE_COLOR + +/datum/sprite_accessory/snouts/mammal/froundlight + name = "Mammal Round + Light (Top)" + icon_state = "froundlight" + color_src = USE_ONE_COLOR*/ + +/datum/sprite_accessory/snouts/mammal/fpede + name = "Scolipede (Top)" + icon_state = "fpede" + +/datum/sprite_accessory/snouts/mammal/fsergal + name = "Sergal (Top)" + icon_state = "fsergal" + +/datum/sprite_accessory/snouts/mammal/fshark + name = "Shark (Top)" + icon_state = "fshark" + +/*/datum/sprite_accessory/snouts/mammal/fsharp + name = "Mammal Sharp (Top)" + icon_state = "fsharp" + color_src = USE_ONE_COLOR + +/datum/sprite_accessory/snouts/mammal/fsharplight + name = "Mammal Sharp + Light (Top)" + icon_state = "fsharplight" + color_src = USE_ONE_COLOR*/ + +/datum/sprite_accessory/snouts/mammal/ftoucan + name = "Toucan (Top)" + icon_state = "ftoucan" + +/datum/sprite_accessory/snouts/mammal/fredpanda + name = "WahCoon (Top)" + icon_state = "fwah" + +/datum/sprite_accessory/snouts/mammal/skulldog + name = "Skulldog" + icon_state = "skulldog" + extra = TRUE + //extra_color_src = MATRIXED + +/datum/sprite_accessory/snouts/mammal/hanubus + name = "Anubus" + icon_state = "hanubus" + +/datum/sprite_accessory/snouts/mammal/hpanda + name = "Panda" + icon_state = "hpanda" + +/datum/sprite_accessory/snouts/mammal/hjackal + name = "Jackal" + icon_state = "hjackal" + +/datum/sprite_accessory/snouts/mammal/hspots + name = "Hyena" + icon_state = "hspots" + +/datum/sprite_accessory/snouts/mammal/hhorse + name = "Horse" + icon_state = "hhorse" + +/datum/sprite_accessory/snouts/mammal/hzebra + name = "Zebra" + icon_state = "hzebra" + +/datum/sprite_accessory/snouts/mammal/sbeak + name = "Corvid Beak" + icon_state = "sbeak" + extra = TRUE + //extra_color_src = MATRIXED + +/datum/sprite_accessory/snouts/mammal/shark_light + name = "Shark Light" + icon_state = "sharkblubber" + color_src = USE_MATRIXED_COLORS + +/datum/sprite_accessory/snouts/mammal/rat + name = "Rat" + icon_state = "rat" + color_src = USE_MATRIXED_COLORS diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/synthliz.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/synthliz.dm new file mode 100644 index 00000000000..662071face1 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/synthliz.dm @@ -0,0 +1,142 @@ +//Synth snouts (This is the most important part) +/datum/sprite_accessory/snouts/synthliz + recommended_species = list("synthliz") + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_snouts.dmi' + color_src = USE_ONE_COLOR + default_color = null + name = "Synthetic Lizard - Snout" + icon_state = "synthliz_basic" + +/datum/sprite_accessory/snouts/synthliz/synthliz_under + color_src = USE_MATRIXED_COLORS + name = "Synthetic Lizard - Snout Under" + icon_state = "synthliz_under" + +/datum/sprite_accessory/snouts/synthliz/synthliz_tert + color_src = USE_MATRIXED_COLORS + name = "Synthetic Lizard - Snout Tertiary" + icon_state = "synthliz_tert" + +/datum/sprite_accessory/snouts/synthliz/synthliz_tertunder + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Snout Tertiary Under" + icon_state = "synthliz_tertunder" + +/datum/sprite_accessory/snouts/synthliz/synthliz_long + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Snout Long" + icon_state = "synthliz_long" + +/datum/sprite_accessory/snouts/synthliz/synthliz_thicklong + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Snout Long & Thick" + icon_state = "synthliz_thicklong" + +//Synth tails +/datum/sprite_accessory/tails/synthliz + recommended_species = list("synthliz") + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_tails.dmi' + color_src = USE_ONE_COLOR + name = "Synthetic Lizard" + icon_state = "synthliz" + +//Synth Antennae +/datum/sprite_accessory/antenna/synthliz + recommended_species = list("synthliz") + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/synthliz_antennas.dmi' + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Antennae" + icon_state = "synth_antennae" + default_color = null + +/datum/sprite_accessory/antenna/synthliz/synthliz_curled + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Curled" + icon_state = "synth_curled" + +/datum/sprite_accessory/antenna/synthliz/synthliz_thick + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Thick" + icon_state = "synth_thick" + +/datum/sprite_accessory/antenna/synthliz/synth_thicklight + color_src = USE_MATRIXED_COLORS + name = "Synthetic Lizard - Thick Light" + icon_state = "synth_thicklight" + +/datum/sprite_accessory/antenna/synthliz/synth_short + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Short" + icon_state = "synth_short" + +/datum/sprite_accessory/antenna/synthliz/synth_sharp + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Sharp" + icon_state = "synth_sharp" + +/datum/sprite_accessory/antenna/synthliz/synth_sharplight + color_src = USE_MATRIXED_COLORS + name = "Synthetic Lizard - Sharp Light" + icon_state = "synth_sharplight" + +/datum/sprite_accessory/antenna/synthliz/synth_horns + color_src = USE_ONE_COLOR + name = "Synthetic Lizard - Horns" + icon_state = "synth_horns" + +/datum/sprite_accessory/antenna/synthliz/synth_hornslight + color_src = USE_MATRIXED_COLORS + name = "Synthetic Lizard - Horns Light" + icon_state = "synth_hornslight" + +/datum/sprite_accessory/antenna/synthliz/cobrahood + name = "Synthetic Lizard - Cobra Hood" + icon_state = "cobrahood" + color_src = USE_MATRIXED_COLORS + +/datum/sprite_accessory/antenna/synthliz/cobrahoodears + name = "Synthetic Lizard - Cobra Hood (Ears)" + icon_state = "cobraears" + color_src = USE_MATRIXED_COLORS + +//Synth Taurs (Ported from Virgo) +/datum/sprite_accessory/taur/synthliz + name = "Cybernetic Lizard" + icon_state = "synthlizard" + taur_mode = STYLE_TAUR_PAW + recommended_species = list("synthliz") + +/datum/sprite_accessory/taur/synthliz/inv + name = "Cybernetic Lizard (Inverted)" + icon_state = "synthlizardinv" + +/datum/sprite_accessory/taur/synthliz/feline + name = "Cybernetic Feline" + icon_state = "synthfeline" + +/datum/sprite_accessory/taur/synthliz/feline/inv + name = "Cybernetic Feline (Inverted)" + icon_state = "synthfelineinv" + +/datum/sprite_accessory/taur/synthliz/horse + name = "Cybernetic Horse" + icon_state = "synthhorse" + taur_mode = STYLE_TAUR_HOOF + alt_taur_mode = STYLE_TAUR_PAW + +/datum/sprite_accessory/taur/synthliz/horse/inv + name = "Cybernetic Horse (Inverted)" + icon_state = "synthhorseinv" + +/datum/sprite_accessory/taur/synthliz/wolf + name = "Cybernetic Wolf" + icon_state = "synthwolf" + +/datum/sprite_accessory/taur/synthliz/wolf/inv + name = "Cybernetic Wolf (Inverted)" + icon_state = "synthwolfinv" + +/datum/sprite_accessory/taur/synthliz/synthnaga + name = "Cybernetic Naga" + icon_state = "synthnaga" + taur_mode = STYLE_TAUR_SNAKE diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm new file mode 100644 index 00000000000..aa017cc4369 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm @@ -0,0 +1,209 @@ +/datum/sprite_accessory/tails + key = "tail" + generic = "Tail" + organ_type = /obj/item/organ/tail + icon = 'modular_skyrat/modules/customization/icons/mob/mutant_bodyparts.dmi' + special_render_case = TRUE + +/datum/sprite_accessory/tails/get_special_render_state(mob/living/carbon/human/H, icon_state) + var/obj/item/organ/tail/T = H.getorganslot(ORGAN_SLOT_TAIL) + if(T && T.wagging) + icon_state += "_wagging" + return icon_state + +/datum/sprite_accessory/tails/lizard + recommended_species = list("lizard", "ashwalker", "mammal") + organ_type = /obj/item/organ/tail/lizard + +/datum/sprite_accessory/tails/human + recommended_species = list("human", "felinid", "mammal") + organ_type = /obj/item/organ/tail/cat + +/datum/sprite_accessory/tails/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) + if(H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)) + return TRUE + return FALSE + +/datum/sprite_accessory/tails/none + name = "None" + icon_state = "none" + recommended_species = list("mammal", "human") + color_src = null + factual = FALSE + +/datum/sprite_accessory/tails/mammal + icon_state = "none" + recommended_species = list("mammal", "human") + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/tails.dmi' + organ_type = /obj/item/organ/tail/fluffy/no_wag + color_src = USE_MATRIXED_COLORS + +/datum/sprite_accessory/tails/mammal/wagging + organ_type = /obj/item/organ/tail/fluffy + +/datum/sprite_accessory/tails/mammal/wagging/axolotl + name = "Axolotl" + icon_state = "axolotl" + +/datum/sprite_accessory/tails/mammal/wagging/batl + name = "Bat (Long)" + icon_state = "batl" + +/datum/sprite_accessory/tails/mammal/wagging/bats + name = "Bat (Short)" + icon_state = "bats" + +/datum/sprite_accessory/tails/mammal/wagging/bee + name = "Bee" + icon_state = "bee" + +/datum/sprite_accessory/tails/mammal/wagging/catbig + name = "Cat, Big" + icon_state = "catbig" + +/datum/sprite_accessory/tails/mammal/wagging/twocat + name = "Cat, Double" + icon_state = "twocat" + +/datum/sprite_accessory/tails/mammal/wagging/corvid + name = "Corvid" + icon_state = "crow" + +/datum/sprite_accessory/tails/mammal/wagging/cow + name = "Cow" + icon_state = "cow" + +/*/datum/sprite_accessory/tails/mammal/wagging/dtiger //icon = 'icons/mob/mutant_bodyparts.dmi' + name = "Dark Tiger" + icon_state = "dtiger" + color_src = USE_ONE_COLOR + default_color = DEFAULT_PRIMARY*/ + +/datum/sprite_accessory/tails/mammal/wagging/eevee + name = "Eevee" + icon_state = "eevee" + +/datum/sprite_accessory/tails/mammal/wagging/fennec + name = "Fennec" + icon_state = "fennec" + +/datum/sprite_accessory/tails/mammal/wagging/fish + name = "Fish" + icon_state = "fish" + +/datum/sprite_accessory/tails/mammal/wagging/fox + name = "Fox" + icon_state = "fox" + +/datum/sprite_accessory/tails/mammal/wagging/hawk + name = "Hawk" + icon_state = "hawk" + +/datum/sprite_accessory/tails/mammal/wagging/horse + name = "Horse" + icon_state = "horse" + color_src = USE_ONE_COLOR + default_color = HAIR + +/datum/sprite_accessory/tails/mammal/wagging/husky + name = "Husky" + icon_state = "husky" + +/datum/sprite_accessory/tails/mammal/wagging/insect + name = "Insect" + icon_state = "insect" + +/datum/sprite_accessory/tails/mammal/wagging/kangaroo + name = "kangaroo" + icon_state = "kangaroo" + +/datum/sprite_accessory/tails/mammal/wagging/kitsune + name = "Kitsune" + icon_state = "kitsune" + +/datum/sprite_accessory/tails/mammal/wagging/lab + name = "Lab" + icon_state = "lab" + +/*/datum/sprite_accessory/tails/mammal/wagging/ltiger //icon = 'icons/mob/mutant_bodyparts.dmi' + name = "Light Tiger" + icon_state = "ltiger" + color_src = USE_ONE_COLOR + default_color = DEFAULT_PRIMARY*/ + +/datum/sprite_accessory/tails/mammal/wagging/murid + name = "Murid" + icon_state = "murid" + +/datum/sprite_accessory/tails/mammal/wagging/orca + name = "Orca" + icon_state = "orca" + +/datum/sprite_accessory/tails/mammal/wagging/otie + name = "Otusian" + icon_state = "otie" + +/datum/sprite_accessory/tails/mammal/wagging/rabbit + name = "Rabbit" + icon_state = "rabbit" + +/datum/sprite_accessory/tails/mammal/wagging/ailurus + name = "Red Panda" + icon_state = "wah" + extra = TRUE + +/datum/sprite_accessory/tails/mammal/wagging/pede + name = "Scolipede" + icon_state = "pede" + +/datum/sprite_accessory/tails/mammal/wagging/sergal + name = "Sergal" + icon_state = "sergal" + +/datum/sprite_accessory/tails/mammal/wagging/shark + name = "Shark" + icon_state = "shark" + +/datum/sprite_accessory/tails/mammal/wagging/shepherd + name = "Shepherd" + icon_state = "shepherd" + +/datum/sprite_accessory/tails/mammal/wagging/skunk + name = "Skunk" + icon_state = "skunk" + +/datum/sprite_accessory/tails/mammal/wagging/straighttail + name = "Straight Tail" + icon_state = "straighttail" + +/datum/sprite_accessory/tails/mammal/wagging/squirrel + name = "Squirrel" + icon_state = "squirrel" + +/datum/sprite_accessory/tails/mammal/wagging/tamamo_kitsune + name = "Tamamo Kitsune Tails" + icon_state = "9sune" + +/datum/sprite_accessory/tails/mammal/wagging/tentacle + name = "Tentacle" + icon_state = "tentacle" + +/datum/sprite_accessory/tails/mammal/wagging/tiger + name = "Tiger" + icon_state = "tiger" + +/datum/sprite_accessory/tails/mammal/wagging/wolf + name = "Wolf" + icon_state = "wolf" + +/datum/sprite_accessory/tails/mammal/wagging/guilmon + name = "Guilmon" + icon_state = "guilmon" + +/datum/sprite_accessory/tails/mammal/wagging/sharknofin + name = "Shark no fin" + icon_state = "sharknofin" + +/datum/sprite_accessory/tails/mammal/raptor + name = "Raptor" + icon_state = "raptor" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm new file mode 100644 index 00000000000..14d3fa8a55a --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm @@ -0,0 +1,111 @@ +/datum/sprite_accessory/taur + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/taur.dmi' + key = "taur" + generic = "Taur Type" + color_src = USE_MATRIXED_COLORS + dimension_x = 64 + center = TRUE + var/taur_mode = NONE //Must be a single specific tauric suit variation bitflag. Don't do FLAG_1|FLAG_2 + var/alt_taur_mode = NONE //Same as above. + var/hide_legs = TRUE + var/hide_markings = FALSE //Any taur part that has "legs" should not hide markings + +/datum/sprite_accessory/taur/none + name = "None" + dimension_x = 32 + center = FALSE + hide_legs = FALSE + factual = FALSE + color_src = null + +/datum/sprite_accessory/taur/cow + name = "Cow" + icon_state = "cow" + taur_mode = STYLE_TAUR_HOOF + alt_taur_mode = STYLE_TAUR_PAW + color_src = USE_ONE_COLOR + +/datum/sprite_accessory/taur/cow/spotted + name = "Cow (Spotted)" + icon_state = "cow_spotted" + color_src = USE_MATRIXED_COLORS + +/datum/sprite_accessory/taur/deer + name = "Deer" + icon_state = "deer" + taur_mode = STYLE_TAUR_HOOF + alt_taur_mode = STYLE_TAUR_PAW + color_src = USE_ONE_COLOR + extra = TRUE + +/datum/sprite_accessory/taur/drake + name = "Drake" + icon_state = "drake" + taur_mode = STYLE_TAUR_PAW + color_src = USE_ONE_COLOR + extra = TRUE + +/datum/sprite_accessory/taur/drake/old + name = "Drake (Old)" + icon_state = "drake_old" + color_src = USE_MATRIXED_COLORS + extra = FALSE + +/datum/sprite_accessory/taur/drider + name = "Drider" + icon_state = "drider" + color_src = USE_ONE_COLOR + extra = TRUE + +/datum/sprite_accessory/taur/eevee + name = "Eevee" + icon_state = "eevee" + taur_mode = STYLE_TAUR_PAW + color_src = USE_ONE_COLOR + extra = TRUE + +/datum/sprite_accessory/taur/horse + name = "Horse" + icon_state = "horse" + taur_mode = STYLE_TAUR_HOOF + alt_taur_mode = STYLE_TAUR_PAW + +/datum/sprite_accessory/taur/naga + name = "Naga" + icon_state = "naga" + taur_mode = STYLE_TAUR_SNAKE + hide_legs = TRUE + +/datum/sprite_accessory/taur/otie + name = "Otie" + icon_state = "otie" + taur_mode = STYLE_TAUR_PAW + +/datum/sprite_accessory/taur/pede + name = "Scolipede" + icon_state = "pede" + taur_mode = STYLE_TAUR_PAW + color_src = USE_ONE_COLOR + extra = TRUE + extra2 = TRUE + +/datum/sprite_accessory/taur/tentacle + name = "Tentacle" + icon_state = "tentacle" + taur_mode = STYLE_TAUR_SNAKE + color_src = USE_ONE_COLOR + hide_legs = TRUE + +/datum/sprite_accessory/taur/canine + name = "Canine" + icon_state = "canine" + taur_mode = STYLE_TAUR_PAW + color_src = USE_ONE_COLOR + extra = TRUE + +/datum/sprite_accessory/taur/feline + name = "Feline" + icon_state = "feline" + taur_mode = STYLE_TAUR_PAW + color_src = USE_ONE_COLOR + extra = TRUE diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/vox.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/vox.dm new file mode 100644 index 00000000000..025b92b2826 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/vox.dm @@ -0,0 +1,114 @@ +//The snouts +/datum/sprite_accessory/snouts/vox + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_snouts.dmi' + default_color = DEFAULT_SECONDARY + name = "Vox" + icon_state = "vox" + recommended_species = list("vox") + +//The hairstyles +/datum/sprite_accessory/hair/vox + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_hair.dmi' + recommended_species = list("vox") + +/datum/sprite_accessory/hair/vox/vox_afro + name = "Vox Afro" + icon_state = "hair_vox_afro" + +/datum/sprite_accessory/hair/vox/vox_crestedquills + name = "Vox Crested Quills" + icon_state = "hair_vox_crestedquills" + +/datum/sprite_accessory/hair/vox/vox_emperorquills + name = "Vox Emperor Quills" + icon_state = "hair_vox_emperorquills" + +/datum/sprite_accessory/hair/vox/vox_horns + name = "Vox Horns" + icon_state = "hair_vox_horns" + +/datum/sprite_accessory/hair/vox/vox_keelquills + name = "Vox Keel Quills" + icon_state = "hair_vox_keelquills" + +/datum/sprite_accessory/hair/vox/vox_keetquills + name = "Vox Keet Quills" + icon_state = "hair_vox_keetquills" + +/datum/sprite_accessory/hair/vox/vox_kingly + name = "Vox Kingly" + icon_state = "hair_vox_kingly" + +/datum/sprite_accessory/hair/vox/vox_mohawk + name = "Vox Mohawk" + icon_state = "hair_vox_mohawk" + +/datum/sprite_accessory/hair/vox/vox_nights + name = "Vox Nights" + icon_state = "hair_vox_nights" + +/datum/sprite_accessory/hair/vox/vox_razorclipped + name = "Vox Razor Clipped" + icon_state = "hair_vox_razorclipped" + +/datum/sprite_accessory/hair/vox/vox_razor + name = "Vox Razor" + icon_state = "hair_vox_razor" + +/datum/sprite_accessory/hair/vox/vox_shortquills + name = "Vox Short Quills" + icon_state = "hair_vox_shortquills" + +/datum/sprite_accessory/hair/vox/vox_tielquills + name = "Vox Tiel Quills" + icon_state = "hair_vox_tielquills" + +/datum/sprite_accessory/hair/vox/vox_yasu + name = "Vox Yasu" + icon_state = "hair_vox_yasu" + +//The facial hairstyles +/datum/sprite_accessory/facial_hair/vox + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_facial_hair.dmi' + recommended_species = list("vox") + +/datum/sprite_accessory/facial_hair/vox/vox_beard + name = "Vox Beard" + icon_state = "facial_vox_beard" + +/datum/sprite_accessory/facial_hair/vox/vox_colonel + name = "Vox Beard (Colonel)" + icon_state = "facial_vox_colonel" + +/datum/sprite_accessory/facial_hair/vox/vox_fu + name = "Vox Beard (Fu)" + icon_state = "facial_vox_fu" + +/datum/sprite_accessory/facial_hair/vox/vox_neck + name = "Vox Neck Quills" + icon_state = "facial_vox_neck" + +//The tail +/datum/sprite_accessory/tails/vox + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_tails.dmi' + name = "Vox" + icon_state = "vox" + recommended_species = list("vox") + +//The tail markings +/datum/sprite_accessory/spines/vox + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/vox_spines.dmi' + default_color = DEFAULT_TERTIARY + recommended_species = list("vox") + +/datum/sprite_accessory/spines/vox/vox_bands + name = "Vox Bands" + icon_state = "vox_bands" + +/datum/sprite_accessory/spines/vox/vox_tip + name = "Vox Tip" + icon_state = "vox_tip" + +/datum/sprite_accessory/spines/vox/vox_stripe + name = "Vox Stripe" + icon_state = "vox_stripe" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm new file mode 100644 index 00000000000..e47200fa378 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm @@ -0,0 +1,128 @@ +/datum/sprite_accessory/wings + icon = 'icons/mob/clothing/wings.dmi' + generic = "Wings" + key = "wings" + color_src = USE_ONE_COLOR + recommended_species = list("human", "felinid", "lizard", "mammal") + organ_type = /obj/item/organ/wings + +/datum/sprite_accessory/wings/none + name = "None" + icon_state = "none" + factual = FALSE + +/datum/sprite_accessory/wings/angel + color_src = USE_ONE_COLOR + default_color = "FFF" + +/datum/sprite_accessory/wings/megamoth + color_src = USE_ONE_COLOR + default_color = "FFF" + +/datum/sprite_accessory/wings/dragon + color_src = USE_ONE_COLOR + +//TODO: seperate moth wings from moth fluff +/datum/sprite_accessory/wings/moth + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/moth_wings.dmi' //Needs new icon to suit new naming convention + default_color = "FFF" + recommended_species = list("moth", "mammal") //Mammals too, I guess. They wont get flight though, see the wing organs for that logic + organ_type = /obj/item/organ/wings/moth + +/datum/sprite_accessory/wings/moth/plain + name = "Plain" + icon_state = "plain" + +/datum/sprite_accessory/wings/moth/monarch + name = "Monarch" + icon_state = "monarch" + +/datum/sprite_accessory/wings/moth/luna + name = "Luna" + icon_state = "luna" + +/datum/sprite_accessory/wings/moth/atlas + name = "Atlas" + icon_state = "atlas" + +/datum/sprite_accessory/wings/moth/reddish + name = "Reddish" + icon_state = "redish" + +/datum/sprite_accessory/wings/moth/royal + name = "Royal" + icon_state = "royal" + +/datum/sprite_accessory/wings/moth/gothic + name = "Gothic" + icon_state = "gothic" + +/datum/sprite_accessory/wings/moth/lovers + name = "Lovers" + icon_state = "lovers" + +/datum/sprite_accessory/wings/moth/whitefly + name = "White Fly" + icon_state = "whitefly" + +/datum/sprite_accessory/wings/moth/punished + name = "Burnt Off" + icon_state = "punished" + locked = TRUE + +/datum/sprite_accessory/wings/moth/firewatch + name = "Firewatch" + icon_state = "firewatch" + +/datum/sprite_accessory/wings/moth/deathhead + name = "Deathshead" + icon_state = "deathhead" + +/datum/sprite_accessory/wings/moth/poison + name = "Poison" + icon_state = "poison" + +/datum/sprite_accessory/wings/moth/ragged + name = "Ragged" + icon_state = "ragged" + +/datum/sprite_accessory/wings/moth/moonfly + name = "Moon Fly" + icon_state = "moonfly" + +/datum/sprite_accessory/wings/moth/snow + name = "Snow" + icon_state = "snow" + +/datum/sprite_accessory/wings/moth/oakworm + name = "Oak Worm" + icon_state = "oakworm" + +/datum/sprite_accessory/wings/moth/jungle + name = "Jungle" + icon_state = "jungle" + +/datum/sprite_accessory/wings/moth/witchwing + name = "Witch Wing" + icon_state = "witchwing" + +/datum/sprite_accessory/wings/mammal + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/wings.dmi' + default_color = DEFAULT_PRIMARY + recommended_species = list("mammal", "lizard") + +/datum/sprite_accessory/wings/mammal/bat //TODO: port my sprite from hyper for this one + name = "Bat" + icon_state = "bat" + +/datum/sprite_accessory/wings/mammal/fairy + name = "Fairy" + icon_state = "fairy" + +/datum/sprite_accessory/wings/mammal/feathery + name = "Feathery" + icon_state = "feathery" + +/datum/sprite_accessory/wings/mammal/bee + name = "Bee" + icon_state = "bee" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/xeno.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/xeno.dm new file mode 100644 index 00000000000..bcfbab94a2f --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/xeno.dm @@ -0,0 +1,46 @@ +/datum/sprite_accessory/xenodorsal + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/xeno_parts.dmi' + generic = "Dorsal Spines" + key = "xenodorsal" + color_src = USE_ONE_COLOR + +/datum/sprite_accessory/xenodorsal/standard + name = "Standard" + icon_state = "standard" + +/datum/sprite_accessory/xenodorsal/royal + name = "Royal" + icon_state = "royal" + +/datum/sprite_accessory/xenodorsal/down + name = "Dorsal Down" + icon_state = "down" + +//TAILS +/datum/sprite_accessory/tails/xeno_tail + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/xeno_parts.dmi' + name = "Xenomorph Tail" + icon_state = "xeno" + recommended_species = list("xeno") + +//HEADS +/datum/sprite_accessory/xenohead + icon = 'modular_skyrat/modules/customization/icons/mob/sprite_accessory/xeno_parts.dmi' + generic = "Caste Head" + key = "xenohead" + +/datum/sprite_accessory/xenohead/standard + name = "Standard" + icon_state = "standard" + +/datum/sprite_accessory/xenohead/royal + name = "Royal" + icon_state = "royal" + +/datum/sprite_accessory/xenohead/hollywood + name = "Hollywood" + icon_state = "hollywood" + +/datum/sprite_accessory/xenohead/warrior + name = "Warrior" + icon_state = "warrior" diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/carbon_update_icons.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/carbon_update_icons.dm new file mode 100644 index 00000000000..15e751c6850 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/carbon_update_icons.dm @@ -0,0 +1,118 @@ +/mob/living/carbon/proc/update_body_parts() + //CHECK FOR UPDATE + var/oldkey = icon_render_key + icon_render_key = generate_icon_render_key() + if(oldkey == icon_render_key) + return + + remove_overlay(BODYPARTS_LAYER) + + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + BP.update_limb() + + //LOAD ICONS + if(limb_icon_cache[icon_render_key]) + load_limb_from_cache() + return + + var/is_taur = FALSE + if(dna?.species.mutant_bodyparts["taur"]) + var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]] + if(S.hide_legs) + is_taur = TRUE + + //GENERATE NEW LIMBS + var/list/new_limbs = list() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if(is_taur && (BP.body_part == LEG_LEFT || BP.body_part == LEG_RIGHT)) + continue + + new_limbs += BP.get_limb_icon() + if(new_limbs.len) + overlays_standing[BODYPARTS_LAYER] = new_limbs + limb_icon_cache[icon_render_key] = new_limbs + + apply_overlay(BODYPARTS_LAYER) + update_damage_overlays() + +/mob/living/carbon/proc/generate_icon_render_key() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + . += "-[BP.body_zone]" + if(BP.use_digitigrade) + . += "-digitigrade[BP.use_digitigrade]" + if(BP.animal_origin) + . += "-[BP.animal_origin]" + if(BP.status == BODYPART_ORGANIC) + . += "-organic" + else + . += "-robotic" + + if(HAS_TRAIT(src, TRAIT_HUSK)) + . += "-husk" + + if(dna?.species.mutant_bodyparts["taur"]) + . += "-taur" + +/mob/living/carbon/update_inv_head() + remove_overlay(HEAD_LAYER) + + if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated + return + + if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1]) + var/obj/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_HEAD) + 1] + inv.update_icon() + + if(head) + var/desired_icon = head.worn_icon + var/used_style = NONE + if(dna?.species.id == "vox") + used_style = STYLE_VOX + else if(dna?.species.mutant_bodyparts["snout"]) + var/datum/sprite_accessory/snouts/S = GLOB.sprite_accessories["snout"][dna.species.mutant_bodyparts["snout"][MUTANT_INDEX_NAME]] + if(S.use_muzzled_sprites && head.mutant_variants & STYLE_MUZZLE) + used_style = STYLE_MUZZLE + switch(used_style) + if(STYLE_MUZZLE) + desired_icon = head.worn_icon_muzzled || 'modular_skyrat/master_files/icons/mob/clothing/head_muzzled.dmi' + if(STYLE_VOX) + desired_icon = 'modular_skyrat/master_files/icons/mob/clothing/head_vox.dmi' + + overlays_standing[HEAD_LAYER] = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/clothing/head.dmi', override_icon = desired_icon) + update_hud_head(head) + + apply_overlay(HEAD_LAYER) + +/mob/living/carbon/update_inv_wear_mask() + remove_overlay(FACEMASK_LAYER) + + if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated + return + + if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_MASK) + 1]) + var/obj/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_MASK) + 1] + inv.update_icon() + + if(wear_mask) + var/desired_icon = wear_mask.worn_icon + var/used_style = NONE + if(dna?.species.id == "vox") + used_style = STYLE_VOX + else if(dna?.species.mutant_bodyparts["snout"]) + var/datum/sprite_accessory/snouts/S = GLOB.sprite_accessories["snout"][dna.species.mutant_bodyparts["snout"][MUTANT_INDEX_NAME]] + if(S.use_muzzled_sprites && wear_mask.mutant_variants & STYLE_MUZZLE) + used_style = STYLE_MUZZLE + switch(used_style) + if(STYLE_MUZZLE) + desired_icon = wear_mask.worn_icon_muzzled || 'modular_skyrat/master_files/icons/mob/clothing/mask_muzzled.dmi' + if(STYLE_VOX) + desired_icon = 'modular_skyrat/master_files/icons/mob/clothing/mask_vox.dmi' + + if(!(ITEM_SLOT_MASK in check_obscured_slots())) + overlays_standing[FACEMASK_LAYER] = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/clothing/mask.dmi', override_icon = desired_icon) + update_hud_wear_mask(wear_mask) + + apply_overlay(FACEMASK_LAYER) diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human.dm new file mode 100644 index 00000000000..293dc6c0372 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human.dm @@ -0,0 +1,124 @@ +/mob/living/carbon/human/Topic(href, href_list) + . = ..() + if(href_list["lookup_info"]) + switch(href_list["lookup_info"]) + if("genitals") + var/list/line = list() + for(var/genital in list("penis", "testicles", "vagina", "breasts")) + if(!dna.species.mutant_bodyparts[genital]) + continue + var/datum/sprite_accessory/genital/G = GLOB.sprite_accessories[genital][dna.species.mutant_bodyparts[genital][MUTANT_INDEX_NAME]] + if(!G) + continue + if(G.is_hidden(src)) + continue + var/obj/item/organ/genital/ORG = getorganslot(G.associated_organ_slot) + if(!ORG) + continue + line += ORG.get_description_string(G) + if(length(line)) + to_chat(usr, "[jointext(line, "\n")]") + if("flavor_text") + if(length(dna.features["flavor_text"])) + var/datum/browser/popup = new(usr, "[name]'s flavor text", "[name]'s Flavor Text", 500, 200) + popup.set_content(text("[][]", "[name]'s flavor text", replacetext(dna.features["flavor_text"], "\n", "
"))) + popup.open() + return + + if("ooc_prefs") + if(client) + var/str = "[src]'s OOC Notes :
ERP : [client.prefs.erp_pref] | Non-Con : [client.prefs.noncon_pref] | Vore : [client.prefs.vore_pref]" + str += "
[html_encode(client.prefs.ooc_prefs)]" + var/datum/browser/popup = new(usr, "[name]'s ooc info", "[name]'s OOC Information", 500, 200) + popup.set_content(text("[][]", "[name]'s OOC information", replacetext(str, "\n", "
"))) + popup.open() + return + + if("general_record") + if(client && usr.client.holder) + var/datum/browser/popup = new(usr, "[name]'s gen rec", "[name]'s General Record", 500, 200) + popup.set_content(text("[][]", "[name]'s general record", replacetext(client.prefs.general_record, "\n", "
"))) + popup.open() + return + + if("security_record") + if(client && usr.client.holder) + var/datum/browser/popup = new(usr, "[name]'s sec rec", "[name]'s Security Record", 500, 200) + popup.set_content(text("[][]", "[name]'s security record", replacetext(client.prefs.security_record, "\n", "
"))) + popup.open() + return + + if("medical_record") + if(client && usr.client.holder) + var/datum/browser/popup = new(usr, "[name]'s med rec", "[name]'s Medical Record", 500, 200) + popup.set_content(text("[][]", "[name]'s medical record", replacetext(client.prefs.medical_record, "\n", "
"))) + popup.open() + return + + if("background_info") + if(client && usr.client.holder) + var/datum/browser/popup = new(usr, "[name]'s flav bg", "[name]'s Background", 500, 200) + popup.set_content(text("[][]", "[name]'s background flavor", replacetext(client.prefs.background_info, "\n", "
"))) + popup.open() + return + + if("exploitable_info") + if(client && usr.client.holder) + var/datum/browser/popup = new(usr, "[name]'s exp info", "[name]'s Exploitable Info", 500, 200) + popup.set_content(text("[][]", "[name]'s exploitable information", replacetext(client.prefs.exploitable_info, "\n", "
"))) + popup.open() + return + +/mob/living/carbon/human/species/synthliz + race = /datum/species/synthliz + +/mob/living/carbon/human/species/vox + race = /datum/species/vox + +/mob/living/carbon/human/species/ipc + race = /datum/species/ipc + +/mob/living/carbon/human/species/mammal + race = /datum/species/mammal + +/mob/living/carbon/human/species/podweak + race = /datum/species/pod/podweak + +/mob/living/carbon/human/species/xeno + race = /datum/species/xeno + +/mob/living/carbon/human/species/dwarf + race = /datum/species/dwarf + +/mob/living/carbon/human/species/roundstartslime + race = /datum/species/jelly/roundstartslime + +/mob/living/carbon/human/verb/toggle_undies() + set category = "IC" + set name = "Toggle underwear visibility" + set desc = "Allows you to toggle which underwear should show or be hidden. Underwear will obscure genitals." + + if(stat != CONSCIOUS) + to_chat(usr, "You can't toggle underwear visibility right now...") + return + + var/underwear_button = underwear_visibility & UNDERWEAR_HIDE_UNDIES ? "Show underwear" : "Hide underwear" + var/undershirt_button = underwear_visibility & UNDERWEAR_HIDE_SHIRT ? "Show shirt" : "Hide shirt" + var/socks_button = underwear_visibility & UNDERWEAR_HIDE_SOCKS ? "Show socks" : "Hide socks" + var/list/choice_list = list("[underwear_button]" = 1,"[undershirt_button]" = 2,"[socks_button]" = 3,"Show all" = 4, "Hide all" = 5) + var/picked_visibility = input(src, "Choose visibility setting", "Show/Hide underwear") as null|anything in choice_list + if(picked_visibility) + var/picked_choice = choice_list[picked_visibility] + switch(picked_choice) + if(1) + underwear_visibility ^= UNDERWEAR_HIDE_UNDIES + if(2) + underwear_visibility ^= UNDERWEAR_HIDE_SHIRT + if(3) + underwear_visibility ^= UNDERWEAR_HIDE_SOCKS + if(4) + underwear_visibility = NONE + if(5) + underwear_visibility = UNDERWEAR_HIDE_UNDIES | UNDERWEAR_HIDE_SHIRT | UNDERWEAR_HIDE_SOCKS + update_body() + return diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_defines.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_defines.dm new file mode 100644 index 00000000000..f4ce31e50a3 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_defines.dm @@ -0,0 +1,7 @@ +/mob/living/carbon/human + ///Color of the undershirt + var/undershirt_color = "FFF" + ///Color of the socks + var/socks_color = "FFF" + ///Flags for showing/hiding underwear, toggleabley by a verb + var/underwear_visibility = NONE diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_update_icons.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_update_icons.dm new file mode 100644 index 00000000000..5776cc67f0c --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_update_icons.dm @@ -0,0 +1,269 @@ +/mob/living/carbon/human/update_inv_w_uniform() + remove_overlay(UNIFORM_LAYER) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_ICLOTHING) + 1] + inv.update_icon() + + if(istype(w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/U = w_uniform + U.screen_loc = ui_iclothing + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += w_uniform + update_observer_view(w_uniform,1) + + if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT)) + return + + var/applied_style = NONE + var/icon_file = w_uniform.worn_icon + if(dna.species.mutant_bodyparts["taur"]) + var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]] + if(w_uniform.mutant_variants & S.taur_mode) + applied_style = S.taur_mode + else if(w_uniform.mutant_variants & S.alt_taur_mode) + applied_style = S.alt_taur_mode + if(!applied_style) + if((DIGITIGRADE in dna.species.species_traits) && (w_uniform.mutant_variants & STYLE_DIGITIGRADE)) + applied_style = STYLE_DIGITIGRADE + + var/x_override + switch(applied_style) + if(STYLE_DIGITIGRADE) + icon_file = w_uniform.worn_icon_digi || 'modular_skyrat/master_files/icons/mob/clothing/under/uniform_digi.dmi' + if(STYLE_TAUR_SNAKE) + icon_file = w_uniform.worn_icon_taur_snake || 'modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_snake.dmi' + if(STYLE_TAUR_HOOF) + icon_file = w_uniform.worn_icon_taur_hoof || 'modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_hoof.dmi' + if(STYLE_TAUR_PAW) + icon_file = w_uniform.worn_icon_taur_paw || 'modular_skyrat/master_files/icons/mob/clothing/under/uniform_taur_paw.dmi' + + if(applied_style & STYLE_TAUR_ALL) + x_override = 64 + + var/target_overlay = U.icon_state + if(U.adjusted == ALT_STYLE) + target_overlay = "[target_overlay]_d" + + + var/mutable_appearance/uniform_overlay + + if(dna && dna.species.sexes && !applied_style) + if(body_type == FEMALE && U.fitted != NO_FEMALE_UNIFORM) + uniform_overlay = U.build_worn_icon(default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, femaleuniform = U.fitted, override_state = target_overlay, override_icon = icon_file, override_x_center = x_override) + + if(!uniform_overlay) + uniform_overlay = U.build_worn_icon(default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, override_state = target_overlay, override_icon = icon_file, override_x_center = x_override) + + if(OFFSET_UNIFORM in dna.species.offset_features) + uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1] + uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2] + overlays_standing[UNIFORM_LAYER] = uniform_overlay + + apply_overlay(UNIFORM_LAYER) + update_mutant_bodyparts() + +/mob/living/carbon/human/update_inv_wear_suit() + remove_overlay(SUIT_LAYER) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_OCLOTHING) + 1] + inv.update_icon() + + if(istype(wear_suit, /obj/item/clothing/suit)) + wear_suit.screen_loc = ui_oclothing + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += wear_suit + update_observer_view(wear_suit,1) + var/icon_file = wear_suit.worn_icon + var/applied_style = NONE + if(dna.species.mutant_bodyparts["taur"]) + var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]] + if(wear_suit.mutant_variants & S.taur_mode) + applied_style = S.taur_mode + else if(wear_suit.mutant_variants & S.alt_taur_mode) + applied_style = S.alt_taur_mode + if(!applied_style) + if((DIGITIGRADE in dna.species.species_traits) && (wear_suit.mutant_variants & STYLE_DIGITIGRADE)) + applied_style = STYLE_DIGITIGRADE + + var/x_override + switch(applied_style) + if(STYLE_DIGITIGRADE) + icon_file = wear_suit.worn_icon_digi || 'modular_skyrat/master_files/icons/mob/clothing/suit_digi.dmi' + if(STYLE_TAUR_SNAKE) + icon_file = wear_suit.worn_icon_taur_snake || 'modular_skyrat/master_files/icons/mob/clothing/suit_taur_snake.dmi' + if(STYLE_TAUR_HOOF) + icon_file = wear_suit.worn_icon_taur_hoof || 'modular_skyrat/master_files/icons/mob/clothing/suit_taur_hoof.dmi' + if(STYLE_TAUR_PAW) + icon_file = wear_suit.worn_icon_taur_paw || 'modular_skyrat/master_files/icons/mob/clothing/suit_taur_paw.dmi' + + if(applied_style & STYLE_TAUR_ALL) + x_override = 64 + + overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(default_layer = SUIT_LAYER, default_icon_file = 'icons/mob/clothing/suit.dmi', override_icon = icon_file, override_x_center = x_override) + var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER] + if(OFFSET_SUIT in dna.species.offset_features) + suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1] + suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2] + overlays_standing[SUIT_LAYER] = suit_overlay + update_hair() + update_mutant_bodyparts() + + apply_overlay(SUIT_LAYER) + +/mob/living/carbon/human/update_inv_shoes() + remove_overlay(SHOES_LAYER) + + if(dna.species.mutant_bodyparts["taur"]) + var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]] + if(S.hide_legs) + return + + if(num_legs<2) + return + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_FEET) + 1] + inv.update_icon() + + if(shoes) + shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open + client.screen += shoes //add it to client's screen + update_observer_view(shoes,1) + var/icon_file = shoes.worn_icon + if((DIGITIGRADE in dna.species.species_traits) && (shoes.mutant_variants & STYLE_DIGITIGRADE)) + icon_file = shoes.worn_icon_digi || 'modular_skyrat/master_files/icons/mob/clothing/feet_digi.dmi' + + overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/clothing/feet.dmi', override_icon = icon_file) + var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER] + if(OFFSET_SHOES in dna.species.offset_features) + shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1] + shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2] + overlays_standing[SHOES_LAYER] = shoes_overlay + + apply_overlay(SHOES_LAYER) + +/obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state = null, override_icon = null, override_x_center = null, override_y_center = null) + + //Find a valid icon_state from variables+arguments + var/t_state + if(override_state) + t_state = override_state + else + t_state = !isinhands ? (worn_icon_state ? worn_icon_state : icon_state) : (inhand_icon_state ? inhand_icon_state : icon_state) + + //Find a valid icon file from variables+arguments + var/file2use + if(override_icon) + file2use = override_icon + else + file2use = !isinhands ? (worn_icon ? worn_icon : default_icon_file) : default_icon_file + + //Find a valid layer from variables+arguments + var/layer2use = alternate_worn_layer ? alternate_worn_layer : default_layer + + var/mutable_appearance/standing + if(femaleuniform) + standing = wear_female_version(t_state,file2use,layer2use,femaleuniform) //should layer2use be in sync with the adjusted value below? needs testing - shiz + if(!standing) + standing = mutable_appearance(file2use, t_state, -layer2use) + + //Get the overlays for this item when it's being worn + //eg: ammo counters, primed grenade flashes, etc. + var/list/worn_overlays = worn_overlays(isinhands, file2use) + if(worn_overlays && worn_overlays.len) + standing.overlays.Add(worn_overlays) + + var/x_center + var/y_center + if(override_x_center) + x_center = override_x_center + else + x_center = isinhands ? inhand_x_dimension : worn_x_dimension + if(override_y_center) + y_center = override_y_center + else + y_center = isinhands ? inhand_y_dimension : worn_y_dimension + standing = center_image(standing, x_center, y_center) + + //Handle held offsets + var/mob/M = loc + if(istype(M)) + var/list/L = get_held_offsets() + if(L) + standing.pixel_x += L["x"] //+= because of center()ing + standing.pixel_y += L["y"] + + standing.alpha = alpha + standing.color = color + + return standing + +//Removed the icon cache from this, as its not feasible to make a cache for the plathora of customizable species and markings +/mob/living/carbon/human/update_body_parts() + //CHECK FOR UPDATE + var/oldkey = icon_render_key + icon_render_key = generate_icon_render_key() + if(oldkey == icon_render_key) + return + + remove_overlay(BODYPARTS_LAYER) + + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + BP.update_limb() + + var/is_taur = FALSE + if(dna?.species.mutant_bodyparts["taur"]) + var/datum/sprite_accessory/taur/S = GLOB.sprite_accessories["taur"][dna.species.mutant_bodyparts["taur"][MUTANT_INDEX_NAME]] + if(S.hide_legs) + is_taur = TRUE + + //GENERATE NEW LIMBS + var/list/new_limbs = list() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if(is_taur && (BP.body_part == LEG_LEFT || BP.body_part == LEG_RIGHT)) + continue + + new_limbs += BP.get_limb_icon() + if(new_limbs.len) + overlays_standing[BODYPARTS_LAYER] = new_limbs + + apply_overlay(BODYPARTS_LAYER) + update_damage_overlays() + +/mob/living/carbon/human/update_inv_glasses() + remove_overlay(GLASSES_LAYER) + + if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated + return + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_EYES) + 1] + inv.update_icon() + + if(glasses) + glasses.screen_loc = ui_glasses //...draw the item in the inventory screen + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + client.screen += glasses //Either way, add the item to the HUD + update_observer_view(glasses,1) + if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES))) + var/icon_file = glasses.worn_icon + if(dna.species.id == "vox") + icon_file = 'modular_skyrat/master_files/icons/mob/clothing/eyes_vox.dmi' + overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/clothing/eyes.dmi', override_icon = icon_file) + + var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER] + if(glasses_overlay) + if(OFFSET_GLASSES in dna.species.offset_features) + glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1] + glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2] + overlays_standing[GLASSES_LAYER] = glasses_overlay + apply_overlay(GLASSES_LAYER) diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm new file mode 100644 index 00000000000..2cd008faf72 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm @@ -0,0 +1,485 @@ +/datum/species + mutant_bodyparts = list() + ///Self explanatory + var/can_have_genitals = TRUE + ///Override of icon file of which we're taking the icons from for our limbs + var/limbs_icon + ///A list of actual body markings on the owner of the species. Associative lists with keys named by limbs defines, pointing to a list with names and colors for the marking to be rendered. This is also stored in the DNA + var/list/list/body_markings = list() + ///Override of the eyes icon file, used for Vox and maybe more in the future + var/eyes_icon + +/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) + var/list/relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER) + var/list/standing = list() + + H.remove_overlay(BODY_BEHIND_LAYER) + H.remove_overlay(BODY_ADJ_LAYER) + H.remove_overlay(BODY_FRONT_LAYER) + + if(!mutant_bodyparts) + return + + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + + //Digitigrade legs are stuck in the phantom zone between true limbs and mutant bodyparts. Mainly it just needs more agressive updating than most limbs. + var/update_needed = FALSE + var/not_digitigrade = TRUE + for(var/X in H.bodyparts) + var/obj/item/bodypart/O = X + if(!O.use_digitigrade) + continue + not_digitigrade = FALSE + if(!(DIGITIGRADE in species_traits)) //Someone cut off a digitigrade leg and tacked it on + species_traits += DIGITIGRADE + var/should_be_squished = FALSE + if((H.wear_suit && H.wear_suit.flags_inv & HIDEJUMPSUIT && !(H.wear_suit.mutant_variants & STYLE_DIGITIGRADE) && (H.wear_suit.body_parts_covered & LEGS)) || (H.w_uniform && (H.w_uniform.body_parts_covered & LEGS) && !(H.w_uniform.mutant_variants & STYLE_DIGITIGRADE))) + should_be_squished = TRUE + if(O.use_digitigrade == FULL_DIGITIGRADE && should_be_squished) + O.use_digitigrade = SQUISHED_DIGITIGRADE + update_needed = TRUE + else if(O.use_digitigrade == SQUISHED_DIGITIGRADE && !should_be_squished) + O.use_digitigrade = FULL_DIGITIGRADE + update_needed = TRUE + if(update_needed) + H.update_body_parts() + if(not_digitigrade && (DIGITIGRADE in species_traits)) //Curse is lifted + species_traits -= DIGITIGRADE + + var/list/bodyparts_to_add = mutant_bodyparts.Copy() + + if(!length(bodyparts_to_add)) + return + + var/g = (H.body_type == FEMALE) ? "f" : "m" + + for(var/layer in relevent_layers) + var/layertext = mutant_bodyparts_layertext(layer) + + for(var/bodypart in bodyparts_to_add) + var/datum/sprite_accessory/S = GLOB.sprite_accessories[bodypart][bodyparts_to_add[bodypart][MUTANT_INDEX_NAME]] + if(!S || S.icon_state == "none") + continue + if(S.is_hidden(H, HD)) + continue + + var/icon_to_use + var/x_shift + if(S.special_icon_case) + icon_to_use = S.get_special_icon(H, S.icon) + else + icon_to_use = S.icon + + if(S.special_x_dimension) + x_shift = S.get_special_x_dimension(H, S.icon) + else + x_shift = S.dimension_x + + var/mutable_appearance/accessory_overlay = mutable_appearance(icon_to_use, layer = -layer) + + if(S.special_render_case) + var/special_state = S.get_special_render_state(H, S.icon_state) + if(!special_state) + continue + accessory_overlay.icon_state = "m_[bodypart]_[special_state]_[layertext]" + else if(S.gender_specific) + accessory_overlay.icon_state = "[g]_[bodypart]_[S.icon_state]_[layertext]" + else + accessory_overlay.icon_state = "m_[bodypart]_[S.icon_state]_[layertext]" + + if(S.center) + accessory_overlay = center_image(accessory_overlay, x_shift, S.dimension_y) + + if(!forced_colour) + if(HAS_TRAIT(H, TRAIT_HUSK)) + if(S.color_src == USE_MATRIXED_COLORS) //Matrixed+husk needs special care, otherwise we get sparkle dogs + accessory_overlay.color = HUSK_COLOR_LIST + else + accessory_overlay.color = "#AAA" //The gray husk color + else + switch(S.color_src) + if(USE_ONE_COLOR) + accessory_overlay.color = "#"+bodyparts_to_add[bodypart][MUTANT_INDEX_COLOR_LIST][1] + if(USE_MATRIXED_COLORS) + var/list/color_list = bodyparts_to_add[bodypart][MUTANT_INDEX_COLOR_LIST] + var/list/finished_list = list() + finished_list += ReadRGB("[color_list[1]]0") + finished_list += ReadRGB("[color_list[2]]0") + finished_list += ReadRGB("[color_list[3]]0") + finished_list += list(0,0,0,255) + for(var/index in 1 to finished_list.len) + finished_list[index] /= 255 + accessory_overlay.color = finished_list + if(MUTCOLORS) + if(fixed_mut_color) + accessory_overlay.color = "#[fixed_mut_color]" + else + accessory_overlay.color = "#[H.dna.features["mcolor"]]" + if(HAIR) + if(hair_color == "mutcolor") + accessory_overlay.color = "#[H.dna.features["mcolor"]]" + else if(hair_color == "fixedmutcolor") + accessory_overlay.color = "#[fixed_mut_color]" + else + accessory_overlay.color = "#[H.hair_color]" + if(FACEHAIR) + accessory_overlay.color = "#[H.facial_hair_color]" + if(EYECOLOR) + accessory_overlay.color = "#[H.eye_color]" + else + accessory_overlay.color = forced_colour + standing += accessory_overlay + + if(S.hasinner) + var/mutable_appearance/inner_accessory_overlay = mutable_appearance(S.icon, layer = -layer) + if(S.gender_specific) + inner_accessory_overlay.icon_state = "[g]_[bodypart]inner_[S.icon_state]_[layertext]" + else + inner_accessory_overlay.icon_state = "m_[bodypart]inner_[S.icon_state]_[layertext]" + + if(S.center) + inner_accessory_overlay = center_image(inner_accessory_overlay, S.dimension_x, S.dimension_y) + + standing += inner_accessory_overlay + + //Here's EXTRA parts of accessories which I should get rid of sometime TODO i guess + if(S.extra) //apply the extra overlay, if there is one + var/mutable_appearance/extra_accessory_overlay = mutable_appearance(S.icon, layer = -layer) + if(S.gender_specific) + extra_accessory_overlay.icon_state = "[g]_[bodypart]_extra_[S.icon_state]_[layertext]" + else + extra_accessory_overlay.icon_state = "m_[bodypart]_extra_[S.icon_state]_[layertext]" + if(S.center) + extra_accessory_overlay = center_image(extra_accessory_overlay, S.dimension_x, S.dimension_y) + + + switch(S.extra_color_src) //change the color of the extra overlay + if(MUTCOLORS) + if(fixed_mut_color) + extra_accessory_overlay.color = "#[fixed_mut_color]" + else + extra_accessory_overlay.color = "#[H.dna.features["mcolor"]]" + if(MUTCOLORS2) + extra_accessory_overlay.color = "#[H.dna.features["mcolor2"]]" + if(MUTCOLORS3) + extra_accessory_overlay.color = "#[H.dna.features["mcolor3"]]" + if(HAIR) + if(hair_color == "mutcolor") + extra_accessory_overlay.color = "#[H.dna.features["mcolor3"]]" + else + extra_accessory_overlay.color = "#[H.hair_color]" + if(FACEHAIR) + extra_accessory_overlay.color = "#[H.facial_hair_color]" + if(EYECOLOR) + extra_accessory_overlay.color = "#[H.eye_color]" + + standing += extra_accessory_overlay + + if(S.extra2) //apply the extra overlay, if there is one + var/mutable_appearance/extra2_accessory_overlay = mutable_appearance(S.icon, layer = -layer) + if(S.gender_specific) + extra2_accessory_overlay.icon_state = "[g]_[bodypart]_extra2_[S.icon_state]_[layertext]" + else + extra2_accessory_overlay.icon_state = "m_[bodypart]_extra2_[S.icon_state]_[layertext]" + if(S.center) + extra2_accessory_overlay = center_image(extra2_accessory_overlay, S.dimension_x, S.dimension_y) + + switch(S.extra2_color_src) //change the color of the extra overlay + if(MUTCOLORS) + if(fixed_mut_color) + extra2_accessory_overlay.color = "#[fixed_mut_color]" + else + extra2_accessory_overlay.color = "#[H.dna.features["mcolor"]]" + if(MUTCOLORS2) + extra2_accessory_overlay.color = "#[H.dna.features["mcolor2"]]" + if(MUTCOLORS3) + extra2_accessory_overlay.color = "#[H.dna.features["mcolor3"]]" + if(HAIR) + if(hair_color == "mutcolor3") + extra2_accessory_overlay.color = "#[H.dna.features["mcolor"]]" + else + extra2_accessory_overlay.color = "#[H.hair_color]" + + standing += extra2_accessory_overlay + + H.overlays_standing[layer] = standing.Copy() + standing = list() + + H.apply_overlay(BODY_BEHIND_LAYER) + H.apply_overlay(BODY_ADJ_LAYER) + H.apply_overlay(BODY_FRONT_LAYER) + +/datum/species + ///This holds 3 lists. Each of the list is possible colors to choose for randomization of a species, first list is primary, second secondary, third tertiary + default_features = null + ///What accessories can a species have aswell as their default accessory of such type e.g. "frills" = "Aquatic". Default accessory colors is dictated by the accessory properties and mutcolors of the specie + var/list/default_mutant_bodyparts = list() + +/datum/species/New() + . = ..() + if(can_have_genitals) + default_mutant_bodyparts["vagina"] = "None" + default_mutant_bodyparts["womb"] = "None" + default_mutant_bodyparts["testicles"] = "None" + default_mutant_bodyparts["breasts"] = "None" + default_mutant_bodyparts["penis"] = "None" + +/datum/species/dullahan + default_features = null + mutant_bodyparts = list() + +/datum/species/human/felinid + default_features = null + mutant_bodyparts = list() + default_mutant_bodyparts = list("tail" = "Cat", "ears" = "Cat") + +/datum/species/human + default_features = null + mutant_bodyparts = list() + default_mutant_bodyparts = list("ears" = "None", "tail" = "None", "wings" = "None") + +/datum/species/moth + default_features = null + mutant_bodyparts = list() + default_mutant_bodyparts = list("moth_markings" = ACC_RANDOM, "wings" = ACC_RANDOM) + +/datum/species/mush + default_features = null + mutant_bodyparts = list() + +/datum/species/vampire + default_features = null + mutant_bodyparts = list() + +/datum/species/plasmaman + default_features = null + mutant_bodyparts = list() + can_have_genitals = FALSE + +/datum/species/ethereal + default_features = null + mutant_bodyparts = list() + can_have_genitals = FALSE + +/datum/species/proc/get_random_features() + var/list/returned = MANDATORY_FEATURE_LIST + returned["mcolor"] = random_short_color() + returned["mcolor2"] = random_short_color() + returned["mcolor3"] = random_short_color() + return returned + +/datum/species/proc/get_random_mutant_bodyparts(list/features) //Needs features to base the colour off of + var/list/mutantpart_list = list() + var/list/bodyparts_to_add = default_mutant_bodyparts.Copy() + for(var/key in bodyparts_to_add) + var/datum/sprite_accessory/SP + if(bodyparts_to_add[key] == ACC_RANDOM) + SP = random_accessory_of_key_for_species(key, src) + else + SP = GLOB.sprite_accessories[key][bodyparts_to_add[key]] + if(!SP) + CRASH("Cant find accessory of [key] key, [bodyparts_to_add[key]] name, for species [id]") + var/list/color_list = SP.get_default_color(features, src) + var/list/final_list = list() + final_list[MUTANT_INDEX_NAME] = SP.name + final_list[MUTANT_INDEX_COLOR_LIST] = color_list + mutantpart_list[key] = final_list + + return mutantpart_list + +/datum/species/proc/get_random_body_markings(list/features) //Needs features to base the colour off of + return list() + +/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) + // Drop the items the new species can't wear + if((AGENDER in species_traits)) + C.gender = PLURAL + for(var/slot_id in no_equip) + var/obj/item/thing = C.get_item_by_slot(slot_id) + if(thing && (!thing.species_exception || !is_type_in_list(src,thing.species_exception))) + C.dropItemToGround(thing) + if(C.hud_used) + C.hud_used.update_locked_slots() + + // this needs to be FIRST because qdel calls update_body which checks if we have DIGITIGRADE legs or not and if not then removes DIGITIGRADE from species_traits + if(C.dna.species.mutant_bodyparts["legs"] && C.dna.species.mutant_bodyparts["legs"][MUTANT_INDEX_NAME] == "Digitigrade Legs") + species_traits += DIGITIGRADE + if(DIGITIGRADE in species_traits) + C.Digitigrade_Leg_Swap(FALSE) + + C.mob_biotypes = inherent_biotypes + + regenerate_organs(C,old_species) + + if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype) + C.dna.blood_type = exotic_bloodtype + + if(old_species.mutanthands) + for(var/obj/item/I in C.held_items) + if(istype(I, old_species.mutanthands)) + qdel(I) + + if(mutanthands) + // Drop items in hands + // If you're lucky enough to have a TRAIT_NODROP item, then it stays. + for(var/V in C.held_items) + var/obj/item/I = V + if(istype(I)) + C.dropItemToGround(I) + else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand + C.put_in_hands(new mutanthands()) + + for(var/X in inherent_traits) + ADD_TRAIT(C, X, SPECIES_TRAIT) + + if(TRAIT_VIRUSIMMUNE in inherent_traits) + for(var/datum/disease/A in C.diseases) + A.cure(FALSE) + + if(TRAIT_TOXIMMUNE in inherent_traits) + C.setToxLoss(0, TRUE, TRUE) + + if(TRAIT_NOMETABOLISM in inherent_traits) + C.reagents.end_metabolization(C, keep_liverless = TRUE) + + if(TRAIT_GENELESS in inherent_traits) + C.dna.remove_all_mutations() // Radiation immune mobs can't get mutations normally + + if(inherent_factions) + for(var/i in inherent_factions) + C.faction += i //Using +=/-= for this in case you also gain the faction from a different source. + + if(flying_species && isnull(fly)) + fly = new + fly.Grant(C) + + C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, multiplicative_slowdown=speedmod) + + SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) + +/datum/species/proc/handle_body(mob/living/carbon/human/H) + H.remove_overlay(BODY_LAYER) + + var/list/standing = list() + + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + + if(HD && !(HAS_TRAIT(H, TRAIT_HUSK))) + // lipstick + if(H.lip_style && (LIPS in species_traits)) + var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER) + lip_overlay.color = H.lip_color + if(OFFSET_FACE in H.dna.species.offset_features) + lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1] + lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2] + standing += lip_overlay + + // eyes + if(!(NOEYESPRITES in species_traits)) + var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES) + var/mutable_appearance/eye_overlay + var/eye_icon = eyes_icon || 'icons/mob/human_face.dmi' + if(!E) + eye_overlay = mutable_appearance(eye_icon, "eyes_missing", -BODY_LAYER) + else + eye_overlay = mutable_appearance(eye_icon, E.eye_icon_state, -BODY_LAYER) + if((EYECOLOR in species_traits) && E) + eye_overlay.color = "#" + H.eye_color + if(OFFSET_FACE in H.dna.species.offset_features) + eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1] + eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2] + standing += eye_overlay + + //Underwear, Undershirts & Socks + if(!(NO_UNDERWEAR in species_traits)) + if(H.underwear && !(H.underwear_visibility & UNDERWEAR_HIDE_UNDIES)) + var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[H.underwear] + var/mutable_appearance/underwear_overlay + if(underwear) + var/icon_state = underwear.icon_state + if(underwear.has_digitigrade && (DIGITIGRADE in species_traits)) + icon_state += "_d" + underwear_overlay = mutable_appearance(underwear.icon, icon_state, -BODY_LAYER) + if(!underwear.use_static) + underwear_overlay.color = "#" + H.underwear_color + standing += underwear_overlay + + if(H.undershirt && !(H.underwear_visibility & UNDERWEAR_HIDE_SHIRT)) + var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt] + if(undershirt) + var/mutable_appearance/undershirt_overlay + if(H.dna.species.sexes && H.gender == FEMALE) + undershirt_overlay = wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER) + else + undershirt_overlay = mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER) + if(!undershirt.use_static) + undershirt_overlay.color = "#" + H.undershirt_color + standing += undershirt_overlay + + if(H.socks && H.num_legs >= 2 && !(mutant_bodyparts["taur"]) && !(H.underwear_visibility & UNDERWEAR_HIDE_SOCKS)) + var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks] + if(socks) + var/mutable_appearance/socks_overlay + var/icon_state = socks.icon_state + if(DIGITIGRADE in species_traits) + icon_state += "_d" + socks_overlay = mutable_appearance(socks.icon, icon_state, -BODY_LAYER) + if(!socks.use_static) + socks_overlay.color = "#" + H.socks_color + standing += socks_overlay + + if(standing.len) + H.overlays_standing[BODY_LAYER] = standing + + H.apply_overlay(BODY_LAYER) + handle_mutant_bodyparts(H) + +//I wag in death +/datum/species/spec_death(gibbed, mob/living/carbon/human/H) + if(H) + stop_wagging_tail(H) + +/datum/species/spec_stun(mob/living/carbon/human/H,amount) + if(H) + stop_wagging_tail(H) + . = ..() + +//////////////// +//Tail Wagging// +//////////////// + +/datum/species/proc/can_wag_tail(mob/living/carbon/human/H) + if(!H) //Somewhere in the core code we're getting those procs with H being null + return FALSE + var/obj/item/organ/tail/T = H.getorganslot(ORGAN_SLOT_TAIL) + if(!T) + return FALSE + if(T.can_wag) + return TRUE + return FALSE + +/datum/species/proc/is_wagging_tail(mob/living/carbon/human/H) + if(!H) //Somewhere in the core code we're getting those procs with H being null + return FALSE + var/obj/item/organ/tail/T = H.getorganslot(ORGAN_SLOT_TAIL) + if(!T) + return FALSE + return T.wagging + +/datum/species/proc/start_wagging_tail(mob/living/carbon/human/H) + if(!H) //Somewhere in the core code we're getting those procs with H being null + return + var/obj/item/organ/tail/T = H.getorganslot(ORGAN_SLOT_TAIL) + if(!T) + return FALSE + T.wagging = TRUE + H.update_body() + +/datum/species/proc/stop_wagging_tail(mob/living/carbon/human/H) + if(!H) //Somewhere in the core code we're getting those procs with H being null + return + var/obj/item/organ/tail/T = H.getorganslot(ORGAN_SLOT_TAIL) + if(!T) + return + T.wagging = FALSE + H.update_body() diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/dwarf.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/dwarf.dm new file mode 100644 index 00000000000..2f8165ec7a3 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/dwarf.dm @@ -0,0 +1,17 @@ +/datum/species/dwarf + name = "Dwarf" + id = "dwarf" + limbs_id = "human" + default_color = "FFFFFF" + say_mod = "bellows" + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) + inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB) + use_skintones = 1 + skinned_type = /obj/item/stack/sheet/animalhide/human + disliked_food = GROSS | RAW + liked_food = JUNKFOOD | FRIED + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT + payday_modifier = 1 + liked_food = ALCOHOL | MEAT | DAIRY //Dwarves like alcohol, meat, and dairy products. + disliked_food = JUNKFOOD | FRIED //Dwarves hate foods that have no nutrition other than alcohol. + species_language_holder = /datum/language_holder/dwarf diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ipc.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ipc.dm new file mode 100644 index 00000000000..9d395b855c6 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ipc.dm @@ -0,0 +1,49 @@ +/datum/species/ipc + name = "I.P.C." + id = "ipc" + say_mod = "beeps" + default_color = "00FF00" + species_traits = list(MUTCOLORS_PARTSONLY,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE,HAIR,NOEYESPRITES) + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID + default_features = null + mutant_bodyparts = list() + default_mutant_bodyparts = list("ipc_antenna" = ACC_RANDOM, "ipc_screen" = ACC_RANDOM, "ipc_chassis" = ACC_RANDOM) + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT + limbs_icon = 'modular_skyrat/modules/customization/icons/mob/species/ipc_parts.dmi' + hair_alpha = 210 + sexes = 0 + var/datum/action/innate/monitor_change/screen + +/datum/species/ipc/on_species_gain(mob/living/carbon/human/C) + . = ..() + if(!screen) + screen = new + screen.Grant(C) + var/chassis = C.dna.mutant_bodyparts["ipc_chassis"] + if(!chassis) + return + var/datum/sprite_accessory/ipc_chassis/chassis_of_choice = GLOB.sprite_accessories["ipc_chassis"][chassis[MUTANT_INDEX_NAME]] + if(chassis_of_choice) + limbs_id = chassis_of_choice.icon_state + if(chassis_of_choice.color_src) + species_traits += MUTCOLORS + C.update_body() + +/datum/species/ipc/on_species_loss(mob/living/carbon/human/C) + if(screen) + screen.Remove(C) + ..() + +/datum/action/innate/monitor_change + name = "Screen Change" + check_flags = AB_CHECK_CONSCIOUS + icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon_state = "drone_vision" + +/datum/action/innate/monitor_change/Activate() + var/mob/living/carbon/human/H = owner + var/new_ipc_screen = input(usr, "Choose your character's screen:", "Monitor Display") as null|anything in GLOB.sprite_accessories["ipc_screen"] + if(!new_ipc_screen) + return + H.dna.species.mutant_bodyparts["ipc_screen"][MUTANT_INDEX_NAME] = new_ipc_screen + H.update_body() diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/lizard.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/lizard.dm new file mode 100644 index 00000000000..f304e610bc1 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/lizard.dm @@ -0,0 +1,26 @@ +/datum/species/lizard + default_features = null + mutant_bodyparts = list() + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE,HAIR,FACEHAIR) + default_mutant_bodyparts = list("tail" = ACC_RANDOM, "snout" = ACC_RANDOM, "spines" = ACC_RANDOM, "horns" = ACC_RANDOM, "frills" = ACC_RANDOM, "body_markings" = ACC_RANDOM, "legs" = "Digitigrade Legs", "taur" = "None", "wings" = "None") + +/datum/species/lizard/get_random_features() + var/list/returned = MANDATORY_FEATURE_LIST + var/main_color = random_short_color() + var/second_color + var/third_color + var/random = rand(1,3) + switch(random) + if(1) //First random case - all is the same + second_color = main_color + third_color = main_color + if(2) //Second case, derrivatory shades, except there's no helpers for that and I dont feel like writing them + second_color = main_color + third_color = main_color + if(3) //Third case, more randomisation + second_color = random_short_color() + third_color = random_short_color() + returned["mcolor"] = main_color + returned["mcolor2"] = second_color + returned["mcolor3"] = third_color + return returned diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/mammal.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/mammal.dm new file mode 100644 index 00000000000..10dacbb37d6 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/mammal.dm @@ -0,0 +1,70 @@ +/datum/species/mammal + name = "Anthromorph" //Called so because the species is so much more universal than just mammals + id = "mammal" + default_color = "4B4B4B" + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE,HAIR,FACEHAIR) + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID + default_features = null + mutant_bodyparts = list() + default_mutant_bodyparts = list("tail" = ACC_RANDOM, "snout" = ACC_RANDOM, "horns" = "None", "ears" = ACC_RANDOM, "legs" = ACC_RANDOM, "taur" = "None", "wings" = "None") + attack_verb = "slash" + attack_sound = 'sound/weapons/slash.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + liked_food = GROSS | MEAT | FRIED + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT + limbs_icon = 'modular_skyrat/modules/customization/icons/mob/species/mammal_parts_greyscale.dmi' + +/datum/species/mammal/get_random_features() + var/list/returned = MANDATORY_FEATURE_LIST + var/main_color + var/second_color + var/third_color + var/random = rand(1,7) + switch(random) + if(1) + main_color = "FFF" + second_color = "333" + third_color = "333" + if(2) + main_color = "FFD" + second_color = "D61" + third_color = "A52" + if(3) + main_color = "D61" + second_color = "FFF" + third_color = "D61" + if(4) + main_color = "CCC" + second_color = "FFF" + third_color = "FFF" + if(5) + main_color = "A52" + second_color = "C83" + third_color = "FFF" + if(6) + main_color = "FFD" + second_color = "FEC" + third_color = "FDB" + if(7) //Oh no you've rolled the sparkle dog + main_color = random_short_color() + second_color = random_short_color() + third_color = random_short_color() + returned["mcolor"] = main_color + returned["mcolor2"] = second_color + returned["mcolor3"] = third_color + return returned + +/datum/species/mammal/get_random_body_markings(list/passed_features) + var/name = "None" + var/list/candidates = GLOB.body_marking_sets.Copy() + for(var/candi in candidates) + var/datum/body_marking_set/setter = GLOB.body_marking_sets[candi] + if(setter.recommended_species && !(id in setter.recommended_species)) + candidates -= candi + if(length(candidates)) + name = pick(candidates) + var/datum/body_marking_set/BMS = GLOB.body_marking_sets[name] + var/list/markings = list() + if(BMS) + markings = assemble_body_markings_from_set(BMS, passed_features, src) + return markings diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/podweak.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/podweak.dm new file mode 100644 index 00000000000..fee2865b338 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/podweak.dm @@ -0,0 +1,7 @@ +/datum/species/pod/podweak + name = "Podperson" + id = "podweak" + limbs_id = "pod" + species_traits = list(MUTCOLORS,EYECOLOR, HAS_FLESH, HAS_BONE, HAIR, FACEHAIR) + mutant_bodyparts = list() + default_mutant_bodyparts = list() diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm new file mode 100644 index 00000000000..c468661470b --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm @@ -0,0 +1,14 @@ +/datum/species/jelly/roundstartslime + name = "Xenobiological Slime Hybrid" + id = "slimeperson" + limbs_id = "slime" + default_color = "00FFFF" + species_traits = list(MUTCOLORS,EYECOLOR,NOBLOOD, HAIR, FACEHAIR) + mutant_bodyparts = list() + default_mutant_bodyparts = list("tail" = "None", "snout" = "None", "ears" = "None", "taur" = "None", "wings" = "None") + say_mod = "says" + hair_color = "mutcolor" + hair_alpha = 160 //a notch brighter so it blends better. + coldmod = 3 + heatmod = 1 + burnmod = 1 diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/synthliz.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/synthliz.dm new file mode 100644 index 00000000000..5b60fdcf1f2 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/synthliz.dm @@ -0,0 +1,20 @@ +/datum/species/synthliz + name = "Synthetic Lizardperson" + id = "synthliz" + say_mod = "beeps" + default_color = "00FF00" + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE,HAIR) + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID + default_features = null + mutant_bodyparts = list() + default_mutant_bodyparts = list("ipc_antenna" = ACC_RANDOM, "tail" = ACC_RANDOM, "snout" = ACC_RANDOM, "legs" = "Digitigrade Legs", "taur" = "None") + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT + limbs_icon = 'modular_skyrat/modules/customization/icons/mob/species/synthliz_parts_greyscale.dmi' + +/datum/species/synthliz/get_random_body_markings(list/passed_features) + var/name = pick("Synth Pecs Lights", "Synth Scutes", "Synth Pecs") + var/datum/body_marking_set/BMS = GLOB.body_marking_sets[name] + var/list/markings = list() + if(BMS) + markings = assemble_body_markings_from_set(BMS, passed_features, src) + return markings diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vox.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vox.dm new file mode 100644 index 00000000000..014a9e23af9 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/vox.dm @@ -0,0 +1,55 @@ +/datum/species/vox + // Bird-like humanoids + name = "Vox" + id = "vox" + eyes_icon = 'modular_skyrat/modules/customization/icons/mob/species/vox_eyes.dmi' + limbs_icon = 'modular_skyrat/modules/customization/icons/mob/species/vox_parts_greyscale.dmi' + say_mod = "shrieks" + default_color = "00FF00" + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE,HAIR,FACEHAIR) + inherent_traits = list(TRAIT_RESISTCOLD) + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID + mutantlungs = /obj/item/organ/lungs/vox + mutantbrain = /obj/item/organ/brain/vox + breathid = "n2" + mutant_bodyparts = list() + default_mutant_bodyparts = list("legs" = "Digitigrade Legs", "snout" = "Vox", "tail" = "Vox", "spines" = ACC_RANDOM) + attack_verb = "slash" + attack_sound = 'sound/weapons/slash.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + liked_food = MEAT | FRIED + outfit_important_for_life = /datum/outfit/vox + species_language_holder = /datum/language_holder/vox + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT + +/datum/species/vox/before_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE) + var/datum/outfit/vox/O = new /datum/outfit/vox + H.equipOutfit(O, visualsOnly) + H.internal = H.get_item_for_held_index(2) + H.update_internals_hud_icon(1) + +/datum/species/vox/random_name(gender,unique,lastname) + if(unique) + return random_unique_vox_name() + + var/randname = vox_name() + + if(lastname) + randname += " [lastname]" + + return randname + +/datum/species/vox/get_random_features() + var/list/returned = MANDATORY_FEATURE_LIST + returned["mcolor"] = pick("7D8", "7DA", "7CD", "7DC") + returned["mcolor2"] = pick("ED8", "EC8") + returned["mcolor3"] = pick("222", "4EF", "4FB", "84F", "323") + return returned + +/datum/species/vox/get_random_body_markings(list/passed_features) + var/name = pick("Vox", "Vox Hive", "Vox Nightling", "Vox Heart", "Vox Tiger") + var/datum/body_marking_set/BMS = GLOB.body_marking_sets[name] + var/list/markings = list() + if(BMS) + markings = assemble_body_markings_from_set(BMS, passed_features, src) + return markings diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/xeno.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/xeno.dm new file mode 100644 index 00000000000..ef2f34e38aa --- /dev/null +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/xeno.dm @@ -0,0 +1,19 @@ +/datum/species/xeno + // A cloning mistake, crossing human and xenomorph DNA + name = "Xenomorph Hybrid" + id = "xeno" + say_mod = "hisses" + default_color = "00FF00" + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE) + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID + default_features = null + mutant_bodyparts = list() + default_mutant_bodyparts = list("tail" = "Xenomorph Tail", "legs" = "Digitigrade Legs", "xenodorsal" = ACC_RANDOM, "xenohead" = ACC_RANDOM, "taur" = "None") + attack_verb = "slash" + attack_sound = 'sound/weapons/slash.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + liked_food = MEAT + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT + limbs_icon = 'modular_skyrat/modules/customization/icons/mob/species/xeno_parts_greyscale.dmi' + damage_overlay_type = "xeno" + diff --git a/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm b/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm new file mode 100644 index 00000000000..6a37be2bf39 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm @@ -0,0 +1,111 @@ +/obj/item/bodypart/proc/get_limb_icon(dropped) + icon_state = "" //to erase the default sprite, we're building the visual aspects of the bodypart through overlays alone. + + . = list() + + var/image_dir = 0 + if(dropped) + image_dir = SOUTH + if(dmg_overlay_type) + if(brutestate) + . += image('icons/mob/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0", -DAMAGE_LAYER, image_dir) + if(burnstate) + . += image('icons/mob/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_0[burnstate]", -DAMAGE_LAYER, image_dir) + + var/image/limb = image(layer = -BODYPARTS_LAYER, dir = image_dir) + var/image/aux + . += limb + + if(animal_origin) + if(is_organic_limb()) + limb.icon = 'icons/mob/animal_parts.dmi' + if(species_id == "husk") + limb.icon_state = "[animal_origin]_husk_[body_zone]" + else + limb.icon_state = "[animal_origin]_[body_zone]" + else + limb.icon = 'icons/mob/augmentation/augments.dmi' + limb.icon_state = "[animal_origin]_[body_zone]" + return + + var/icon_gender = (body_gender == FEMALE) ? "f" : "m" //gender of the icon, if applicable + + if((body_zone != BODY_ZONE_HEAD && body_zone != BODY_ZONE_CHEST)) + should_draw_gender = FALSE + + if(is_organic_limb()) + if(should_draw_greyscale) + limb.icon = rendered_bp_icon || 'icons/mob/human_parts_greyscale.dmi' //Skyrat change - customization + if(should_draw_gender) + limb.icon_state = "[species_id]_[body_zone]_[icon_gender]" + else if(use_digitigrade) + limb.icon_state = "digitigrade_[use_digitigrade]_[body_zone]" + else + limb.icon_state = "[species_id]_[body_zone]" + else + limb.icon = rendered_bp_icon || 'icons/mob/human_parts.dmi' //Skyrat change - customization + if(should_draw_gender) + limb.icon_state = "[species_id]_[body_zone]_[icon_gender]" + else + limb.icon_state = "[species_id]_[body_zone]" + if(aux_zone) + aux = image(limb.icon, "[species_id]_[aux_zone]", -aux_layer, image_dir) + . += aux + + else + limb.icon = icon + if(should_draw_gender) + limb.icon_state = "[body_zone]_[icon_gender]" + else + limb.icon_state = "[body_zone]" + if(aux_zone) + aux = image(limb.icon, "[aux_zone]", -aux_layer, image_dir) + . += aux + return + + + if(should_draw_greyscale) + var/draw_color = mutation_color || species_color || (skin_tone && skintone2hex(skin_tone)) + if(draw_color) + limb.color = "#[draw_color]" + if(aux_zone) + aux.color = "#[draw_color]" + + //Markings! + if(!is_pseudopart && owner) + var/mob/living/carbon/human/H = owner + var/override_color + if(HAS_TRAIT(H, TRAIT_HUSK)) + override_color = "888" + if(istype(H)) + for(var/key in H.dna.species.body_markings[body_zone]) + var/datum/body_marking/BM = GLOB.body_markings[key] + + var/render_limb_string = body_zone + switch(body_zone) + if(BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) + if(use_digitigrade) + render_limb_string = "digitigrade_[use_digitigrade]_[render_limb_string]" + if(BODY_ZONE_CHEST) + var/gendaar = (H.body_type == FEMALE) ? "f" : "m" + render_limb_string = "[render_limb_string]_[gendaar]" + + var/mutable_appearance/accessory_overlay = mutable_appearance(BM.icon, "[BM.icon_state]_[render_limb_string]", -BODYPARTS_LAYER) + if(override_color) + accessory_overlay.color = "#[override_color]" + else + accessory_overlay.color = "#[H.dna.species.body_markings[body_zone][key]]" + . += accessory_overlay + + if(aux_zone) + for(var/key in H.dna.species.body_markings[aux_zone]) + var/datum/body_marking/BM = GLOB.body_markings[key] + + var/render_limb_string = aux_zone + + var/mutable_appearance/accessory_overlay = mutable_appearance(BM.icon, "[BM.icon_state]_[render_limb_string]", -aux_layer) + if(override_color) + accessory_overlay.color = "#[override_color]" + else + accessory_overlay.color = "#[H.dna.species.body_markings[aux_zone][key]]" + . += accessory_overlay diff --git a/modular_skyrat/modules/customization/modules/surgery/organs/ears.dm b/modular_skyrat/modules/customization/modules/surgery/organs/ears.dm new file mode 100644 index 00000000000..f6ffa7b0287 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/surgery/organs/ears.dm @@ -0,0 +1,6 @@ +/obj/item/organ/ears/mutant + name = "fluffy ears" + icon = 'icons/obj/clothing/hats.dmi' + icon_state = "kitty" + mutantpart_key = "ears" + mutantpart_info = list(MUTANT_INDEX_NAME = "Cat", MUTANT_INDEX_COLOR_LIST = list("FA0")) diff --git a/modular_skyrat/modules/customization/modules/surgery/organs/genitals.dm b/modular_skyrat/modules/customization/modules/surgery/organs/genitals.dm new file mode 100644 index 00000000000..d786adeff1b --- /dev/null +++ b/modular_skyrat/modules/customization/modules/surgery/organs/genitals.dm @@ -0,0 +1,240 @@ +/obj/item/organ/genital + color = "#fcccb3" + organ_flags = ORGAN_EDIBLE | ORGAN_NO_DISMEMBERMENT + ///Size value of the genital, needs to be translated to proper lengths/diameters/cups + var/genital_size = 1 + ///Type of the genital. For penises tapered/horse/human etc. for breasts quadruple/sixtuple etc... + var/genital_type = "human" + ///Used for determining what sprite is being used, derrives from size and type + var/sprite_suffix + ///Used for input from the user whether to show a genital through clothing or not, always or never etc. + var/visibility_preference = GENITAL_HIDDEN_BY_CLOTHES + ///Whether the organ is aroused, matters for sprites, use a 0 or 1 for easy string append + var/aroused = 0 + +//This translates the float size into a sprite string +/obj/item/organ/genital/proc/get_sprite_size_string() + return 0 + +//This translates the float size into a sprite string +/obj/item/organ/genital/proc/update_sprite_suffix() + sprite_suffix = "[get_sprite_size_string()]" + +/obj/item/organ/genital/proc/get_description_string(datum/sprite_accessory/genital/gas) + return "You see genitals" + +/obj/item/organ/genital/proc/update_genital_icon_state() + return + +/obj/item/organ/genital/proc/set_type_and_size(type, size) + genital_type = type + genital_size = size + update_sprite_suffix() + +/obj/item/organ/genital/Initialize() + . = ..() + update_sprite_suffix() + +/obj/item/organ/genital/Remove(mob/living/carbon/M, special = FALSE) + . = ..() + update_genital_icon_state() + +/obj/item/organ/genital/penis + name = "penis" + desc = "A male reproductive organ." + icon_state = "penis" + icon = 'modular_skyrat/modules/customization/icons/obj/genitals/penis.dmi' + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_PENIS + mutantpart_key = "penis" + mutantpart_info = list(MUTANT_INDEX_NAME = "Human", MUTANT_INDEX_COLOR_LIST = list("FEB")) + var/girth = 9 + +/obj/item/organ/genital/penis/get_description_string(datum/sprite_accessory/genital/gas) + return "You see a [lowertext(gas.name)] penis. You estimate it's [genital_size] inches long, and [girth] inches in circumference." + +/obj/item/organ/genital/penis/update_genital_icon_state() + var/size_affix + var/measured_size = FLOOR(genital_size,1) + if(measured_size < 1) + measured_size = 1 + switch(measured_size) + if(1 to 8) + size_affix = "1" + if(9 to 15) + size_affix = "2" + if(16 to 25) + size_affix = "3" + else + size_affix = "4" + icon_state = "penis_[genital_type]_[size_affix]" + +/obj/item/organ/genital/penis/get_sprite_size_string() + var/size_affix + var/measured_size = FLOOR(genital_size,1) + if(measured_size < 1) + measured_size = 1 + switch(measured_size) + if(1 to 8) + size_affix = "1" + if(9 to 15) + size_affix = "2" + if(16 to 25) + size_affix = "3" + else + size_affix = "4" + return "[size_affix]_[aroused]" + +/obj/item/organ/genital/penis/build_from_dna(datum/dna/DNA, associated_key) + ..() + var/type = lowertext(DNA.mutant_bodyparts[associated_key][MUTANT_INDEX_NAME]) + girth = DNA.features["penis_girth"] + set_type_and_size(type, DNA.features["penis_size"]) + +/obj/item/organ/genital/testicles + name = "testicles" + desc = "A male reproductive organ." + icon_state = "testicles" + icon = 'modular_skyrat/modules/customization/icons/obj/genitals/testicles.dmi' + mutantpart_key = "testicles" + mutantpart_info = list(MUTANT_INDEX_NAME = "Pair", MUTANT_INDEX_COLOR_LIST = list("FEB")) + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_TESTICLES + +/obj/item/organ/genital/testicles/get_description_string(datum/sprite_accessory/genital/gas) + return "You see a pair of testicles, they look [lowertext(balls_size_to_description(genital_size))]." + +/obj/item/organ/genital/testicles/build_from_dna(datum/dna/DNA, associated_key) + ..() + var/type = lowertext(DNA.mutant_bodyparts[associated_key][MUTANT_INDEX_NAME]) + set_type_and_size(type, DNA.features["balls_size"]) + +/obj/item/organ/genital/testicles/get_sprite_size_string() + var/measured_size = FLOOR(genital_size,1) + if(measured_size < 0) + measured_size = 0 + else if (measured_size > 3) + measured_size = 3 + return "[measured_size]" + +/obj/item/organ/genital/vagina + name = "vagina" + icon = 'modular_skyrat/modules/customization/icons/obj/genitals/vagina.dmi' + icon_state = "vagina" + mutantpart_key = "vagina" + mutantpart_info = list(MUTANT_INDEX_NAME = "Human", MUTANT_INDEX_COLOR_LIST = list("FEB")) + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_VAGINA + +/obj/item/organ/genital/vagina/get_description_string(datum/sprite_accessory/genital/gas) + return "You see a [lowertext(gas.name)] vagina." + +/obj/item/organ/genital/womb + name = "womb" + desc = "A female reproductive organ." + icon = 'modular_skyrat/modules/customization/icons/obj/genitals/vagina.dmi' + icon_state = "womb" + mutantpart_key = "womb" + mutantpart_info = list(MUTANT_INDEX_NAME = "Normal", MUTANT_INDEX_COLOR_LIST = list("FEB")) + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_WOMB + visibility_preference = GENITAL_SKIP_VISIBILITY + +/obj/item/organ/genital/breasts + name = "breasts" + desc = "Female milk producing organs." + icon_state = "breasts" + icon = 'modular_skyrat/modules/customization/icons/obj/genitals/breasts.dmi' + genital_type = "pair" + mutantpart_key = "penis" + mutantpart_info = list(MUTANT_INDEX_NAME = "Pair", MUTANT_INDEX_COLOR_LIST = list("FEB")) + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_BREASTS + var/lactates = FALSE + +/obj/item/organ/genital/breasts/get_description_string(datum/sprite_accessory/genital/gas) + return "You see a [lowertext(gas.name)] of breasts. You estimate they are [breasts_size_to_cup(genital_size)]-cups." + +/obj/item/organ/genital/breasts/update_genital_icon_state() + var/max_size = 5 + var/current_size = FLOOR(genital_size, 1) + if(current_size < 0) + current_size = 0 + else if (current_size > max_size) + current_size = max_size + icon_state = "breasts_pair_[current_size]" + +/obj/item/organ/genital/breasts/get_sprite_size_string() + var/max_size = 5 + if(genital_type == "pair") + max_size = 16 + var/current_size = FLOOR(genital_size, 1) + if(current_size < 0) + current_size = 0 + else if (current_size > max_size) + current_size = max_size + return current_size + +/obj/item/organ/genital/breasts/build_from_dna(datum/dna/DNA, associated_key) + ..() + var/datum/sprite_accessory/SA = GLOB.sprite_accessories[associated_key][mutantpart_info[MUTANT_INDEX_NAME]] + var/type = SA.icon_state + lactates = DNA.features["breasts_lactation"] + set_type_and_size(type, DNA.features["breasts_size"]) + +/proc/breasts_size_to_cup(number) + if(number < 0) + number = 0 + var/returned = GLOB.breasts_size_translation["[number]"] + if(!returned) + returned = "beyond measurement" + return returned + +/proc/breasts_cup_to_size(cup) + for(var/key in GLOB.breasts_size_translation) + if(GLOB.breasts_size_translation[key] == cup) + return text2num(key) + return 0 + +/proc/balls_size_to_description(number) + if(number < 0) + number = 0 + var/returned = GLOB.balls_size_translation["[number]"] + if(!returned) + returned = "beyond measurement" + return returned + +/proc/balls_description_to_size(cup) + for(var/key in GLOB.balls_size_translation) + if(GLOB.balls_size_translation[key] == cup) + return text2num(key) + return 0 + +/mob/living/carbon/human/verb/toggle_genitals() + set category = "IC" + set name = "Expose/Hide genitals" + set desc = "Allows you to toggle which genitals should show through clothes or not." + + if(stat != CONSCIOUS) + to_chat(usr, "You can't toggle genitals visibility right now...") + return + + var/list/genital_list = list() + for(var/obj/item/organ/genital/G in internal_organs) + if(!G.visibility_preference == GENITAL_SKIP_VISIBILITY) + genital_list += G + if(!genital_list.len) //There is nothing to expose + return + //Full list of exposable genitals created + var/obj/item/organ/genital/picked_organ + picked_organ = input(src, "Choose which genitalia to expose/hide", "Expose/Hide genitals") as null|anything in genital_list + if(picked_organ && (picked_organ in internal_organs)) + var/list/gen_vis_trans = list("Never show" = GENITAL_NEVER_SHOW, + "Hidden by clothes" = GENITAL_HIDDEN_BY_CLOTHES, + "Always show" = GENITAL_ALWAYS_SHOW + ) + var/picked_visibility = input(src, "Choose visibility setting", "Expose/Hide genitals") as null|anything in gen_vis_trans + if(picked_visibility && picked_organ && (picked_organ in internal_organs)) + picked_organ.visibility_preference = gen_vis_trans[picked_visibility] + update_body() + return diff --git a/modular_skyrat/modules/customization/modules/surgery/organs/organ.dm b/modular_skyrat/modules/customization/modules/surgery/organs/organ.dm new file mode 100644 index 00000000000..99143a67204 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/surgery/organs/organ.dm @@ -0,0 +1,31 @@ +/obj/item/organ + ///This is for associating an organ with a mutant bodypart. Look at tails for examples + var/mutantpart_key + var/list/list/mutantpart_info + +/obj/item/organ/Initialize() + . = ..() + if(mutantpart_key) + color = mutantpart_info[MUTANT_INDEX_COLOR_LIST][1] + +/obj/item/organ/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) + var/mob/living/carbon/human/H = M + if(mutantpart_key && istype(H)) + H.dna.species.mutant_bodyparts[mutantpart_key] = mutantpart_info.Copy() + H.update_body() + . = ..() + +/obj/item/organ/Remove(mob/living/carbon/M, special = FALSE) + var/mob/living/carbon/human/H = M + if(mutantpart_key && istype(H)) + if(H.dna.species.mutant_bodyparts[mutantpart_key]) + mutantpart_info = H.dna.species.mutant_bodyparts[mutantpart_key].Copy() //Update the info in case it was changed on the person + color = "#[mutantpart_info[MUTANT_INDEX_COLOR_LIST][1]]" + H.dna.species.mutant_bodyparts -= mutantpart_key + H.update_body() + . = ..() + +/obj/item/organ/proc/build_from_dna(datum/dna/DNA, associated_key) + mutantpart_key = associated_key + mutantpart_info = DNA.mutant_bodyparts[associated_key].Copy() + color = "#[mutantpart_info[MUTANT_INDEX_COLOR_LIST][1]]" diff --git a/modular_skyrat/modules/customization/modules/surgery/organs/tails.dm b/modular_skyrat/modules/customization/modules/surgery/organs/tails.dm new file mode 100644 index 00000000000..292bcf472cd --- /dev/null +++ b/modular_skyrat/modules/customization/modules/surgery/organs/tails.dm @@ -0,0 +1,18 @@ +/obj/item/organ/tail + mutantpart_key = "tail" + mutantpart_info = list(MUTANT_INDEX_NAME = "Smooth", MUTANT_INDEX_COLOR_LIST = list("FFF")) + var/can_wag = TRUE + var/wagging = FALSE + +/obj/item/organ/tail/cat + mutantpart_info = list(MUTANT_INDEX_NAME = "Cat", MUTANT_INDEX_COLOR_LIST = list("FA0")) + +/obj/item/organ/tail/lizard + mutantpart_info = list(MUTANT_INDEX_NAME = "Smooth", MUTANT_INDEX_COLOR_LIST = list("DFD")) + +/obj/item/organ/tail/fluffy + name = "fluffy tail" + +/obj/item/organ/tail/fluffy/no_wag + name = "fluffy tail" + can_wag = FALSE diff --git a/modular_skyrat/modules/customization/modules/surgery/organs/vox.dm b/modular_skyrat/modules/customization/modules/surgery/organs/vox.dm new file mode 100644 index 00000000000..09a1fac00e3 --- /dev/null +++ b/modular_skyrat/modules/customization/modules/surgery/organs/vox.dm @@ -0,0 +1,41 @@ +/obj/item/organ/lungs/vox + name = "vox lungs" + desc = "They're filled with dust... wow." + icon_state = "lungs-c" + safe_oxygen_min = 0 //Dont need oxygen + safe_oxygen_max = 2 //But it is quite toxic to them + safe_nitro_min = 10 // Atleast 10 nitrogen + oxy_damage_type = TOX + oxy_breath_dam_min = 6 + oxy_breath_dam_max = 20 + + cold_level_1_threshold = 0 // Vox should be able to breathe in cold gas without issues? + cold_level_2_threshold = 0 + cold_level_3_threshold = 0 + status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/brain/vox + name = "vox brain" + status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/brain/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + if(owner.stat == DEAD) + return + switch(severity) + if(1) + to_chat(owner, "You feel [pick("like your brain is being fried", "a sharp pain in your head")]!") + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20, 150) + owner.jitteriness += 30 + owner.stuttering += 30 + owner.add_confusion(10) + if(2) + to_chat(owner, "You feel [pick("disoriented", "confused", "dizzy")].") + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 150) + owner.jitteriness += 10 + owner.stuttering += 10 + owner.add_confusion(3) diff --git a/modular_skyrat/modules/customization/modules/surgery/organs/wings.dm b/modular_skyrat/modules/customization/modules/surgery/organs/wings.dm new file mode 100644 index 00000000000..413dfe5887f --- /dev/null +++ b/modular_skyrat/modules/customization/modules/surgery/organs/wings.dm @@ -0,0 +1,43 @@ +/obj/item/organ/wings + name = "wings" + desc = "A pair of wings. Those may or may not allow you to fly... or at the very least flap." + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_WINGS + mutantpart_key = "wings" + mutantpart_info = list(MUTANT_INDEX_NAME = "Bat", MUTANT_INDEX_COLOR_LIST = list("353")) + ///Whether the wings should grant flight on insertion. + var/unconditional_flight + ///What species get flights thanks to those wings. Important for moth wings + var/list/flight_for_species + ///Whether a wing can be opened by the *wing emote. The sprite use a "_open" suffix, before their layer + var/can_open + ///Whether an openable wing is currently opened + var/is_open + ///Whether the owner of wings has flight thanks to the wings + var/granted_flight + +//TODO: Well you know what this flight stuff is a bit complicated and hardcoded, this is enough for now + +/obj/item/organ/wings/moth + name = "moth wings" + desc = "A pair of fuzzy moth wings." + flight_for_species = list("moth") + +/obj/item/organ/wings/flight + unconditional_flight = TRUE + can_open = TRUE + +/obj/item/organ/wings/flight/angel + name = "angel wings" + desc = "A pair of magnificent, feathery wings. They look strong enough to lift you up in the air." + mutantpart_info = list(MUTANT_INDEX_NAME = "Angel", MUTANT_INDEX_COLOR_LIST = list("FFF")) + +/obj/item/organ/wings/flight/dragon + name = "dragon wings" + desc = "A pair of intimidating, membranous wings. They look strong enough to lift you up in the air." + mutantpart_info = list(MUTANT_INDEX_NAME = "Dragon", MUTANT_INDEX_COLOR_LIST = list("800")) + +/obj/item/organ/wings/flight/megamoth + name = "megamoth wings" + desc = "A pair of horrifyingly large, fuzzy wings. They look strong enough to lift you up in the air." + mutantpart_info = list(MUTANT_INDEX_NAME = "Megamoth", MUTANT_INDEX_COLOR_LIST = list("FFF")) diff --git a/modular_skyrat/modules/customization/readme.md b/modular_skyrat/modules/customization/readme.md new file mode 100644 index 00000000000..2fd76fe4854 --- /dev/null +++ b/modular_skyrat/modules/customization/readme.md @@ -0,0 +1,67 @@ +## Title: Customization + +MODULE ID: CUSTOMIZATION + +### Description: + +Re-writes how mutant bodyparts exist and how they're handled. Adds in a per limb body marking system. Adds in loadout, with lots of clothing ported over. Adds in all the missing species. Adds in flavor text and OOC prefs. Adds in special rendering cases for digitigrades, taurs, snouts, voxes etc. + +### TG Proc Changes: + + ./code/__HELPERS/global_lists.dm > /proc/make_datum_references_lists() + ./code/__HELPERS/mobs.dm > /proc/random_features() + ./code/controllers/subsystem/job.dm > /datum/controller/subsystem/job/proc/EquipRank() + ./code/datums/dna.dm > /datum/dna/proc/initialize_dna() , /mob/living/carbon/set_species() + ./code/modules/admin/create_mob.dm > /proc/randomize_human() + ./code/modules/client/preferences.dm > ALMOST THE ENTIRETY OF THE FILE + ./code/modules/client/preferences_savefile.dm > ONCE AGAIN, THE ENTIRE FILE + ./code/modules/mob/dead/new_player/preferences_setup.dm > /datum/preferences/proc/random_character(), /datum/preferences/proc/random_species(), /datum/preferences/proc/update_preview_icon() + ./code/modules/mob/living/carbon/carbon_update_icons.dm > /mob/living/carbon/update_inv_wear_mask(), /mob/living/carbon/update_inv_head(), /mob/living/carbon/proc/update_body_parts(), /mob/living/carbon/proc/generate_icon_render_key() + ./code/modules/mob/living/carbon/human/emote.dm > /datum/emote/living/carbon/human/wag/run_emote(), /datum/emote/living/carbon/human/wag/can_run_emote() + ./code/modules/mob/living/carbon/human/examine.dm > /mob/living/carbon/human/examine() + ./code/modules/mob/living/carbon/human/human_update_icons.dm > /mob/living/carbon/human/update_inv_w_uniform(), /mob/living/carbon/human/update_inv_glasses(), /mob/living/carbon/human/update_inv_shoes(), /mob/living/carbon/human/update_inv_wear_suit(), /obj/item/proc/build_worn_icon(), /mob/living/carbon/human/generate_icon_render_key() + ./code/modules/mob/living/carbon/human/species.dm > /datum/species/proc/on_species_gain(), /datum/species/proc/handle_body(), /datum/species/proc/handle_mutant_bodyparts(), /datum/species/proc/can_equip(), /datum/species/proc/can_wag_tail(), /datum/species/proc/stop_wagging_tail(), /datum/species/proc/start_wagging_tail(), /datum/species/proc/is_wagging_tail() + ./code/modules/mob/living/carbon/human/species_types/felinid.dm > the 5 procs related to wagging tail + ./code/modules/mob/living/carbon/human/species_types/lizardpeople.dm the 5 procs related to wagging tail and - /datum/species/lizard/on_species_gain() + ./code/modules/surgery/bodyparts/_bodyparts.dm > /obj/item/bodypart/proc/get_limb_icon() + ./code/modules/surgery/organs/ears.dm > /obj/item/organ/ears/cat/Insert(), /obj/item/organ/ears/cat/Remove() + ./ code/modules/surgery/organs/tails.dm > /obj/item/organ/tail/cat/Insert(), /obj/item/organ/tail/cat/Remove(), /obj/item/organ/tail/lizard/Initialize(), /obj/item/organ/tail/lizard/Insert(), /obj/item/organ/tail/lizard/Remove() + +### Defines: + + ./code/modules/surgery/organs/tongue.dm > var/static/list/languages_possible_base - added 2 languages + ./code/modules/mob/living/carbon/human/species_types/lizardpeople.dm > commented out "mutant_organs = list(/obj/item/organ/tail/lizard)" + ./code/modules/mob/living/carbon/human/species_types/felinid.dm > commented out "mutantears = /obj/item/organ/ears/cat" and "mutant_organs = list(/obj/item/organ/tail/cat)" + ./code/modules/mob/living/carbon/human/species.dm > var/list/list/mutant_bodyparts (added typed list type) + ./code/_globalvars/lists/flavor_misc.dm > Removed accessory list defines + + ./code/modules/surgery/bodyparts/_bodyparts.dm > var/rendered_bp_icon + + ./code/__DEFINES/~skyrat_defines/DNA.dm > A TON of defines + ./code/__DEFINES/~skyrat_defines/obj_flags.dm > Organ flags + ./code/__DEFINES/~skyrat_defines/say.dm > MAX_FLAVOR_LEN + +### Master file additions + + .\modular_skyrat\master_files\icons\mob\clothing\eyes_vox.dmi + .\modular_skyrat\master_files\icons\mob\clothing\feet_digi.dmi + .\modular_skyrat\master_files\icons\mob\clothing\head_muzzled.dmi + .\modular_skyrat\master_files\icons\mob\clothing\head_vox.dmi + .\modular_skyrat\master_files\icons\mob\clothing\mask_muzzled.dmi + .\modular_skyrat\master_files\icons\mob\clothing\mask_vox.dmi + .\modular_skyrat\master_files\icons\mob\clothing\suit_digi.dmi + .\modular_skyrat\master_files\icons\mob\clothing\suit_taur_hoof.dmi + .\modular_skyrat\master_files\icons\mob\clothing\suit_taur_paw.dmi + .\modular_skyrat\master_files\icons\mob\clothing\suit_taur_snake.dmi + .\modular_skyrat\master_files\icons\mob\clothing\uniform_digi.dmi + .\modular_skyrat\master_files\icons\mob\clothing\under\uniform_digi.dmi + .\modular_skyrat\master_files\icons\mob\clothing\under\uniform_taur_hoof.dmi + .\modular_skyrat\master_files\icons\mob\clothing\under\uniform_taur_paw.dmi + .\modular_skyrat\master_files\icons\mob\clothing\under\uniform_taur_snake.dmi + +### Included files that are not contained in this module: + +- N/A + +### Credits: +Azarak diff --git a/tgstation.dme b/tgstation.dme index 22a53330088..3913f9f210a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -131,6 +131,9 @@ #include "code\__DEFINES\dcs\signals.dm" #include "code\__DEFINES\research\anomalies.dm" #include "code\__DEFINES\~skyrat_defines\blueshield.dm" +#include "code\__DEFINES\~skyrat_defines\DNA.dm" +#include "code\__DEFINES\~skyrat_defines\obj_flags.dm" +#include "code\__DEFINES\~skyrat_defines\say.dm" #include "code\__HELPERS\_lists.dm" #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" @@ -3269,6 +3272,88 @@ #include "modular_skyrat\modules\blueshield\code\modules\clothing\under\jobs\Plasmaman\security.dm" #include "modular_skyrat\modules\blueshield\code\modules\jobs\job_types\blueshield.dm" #include "modular_skyrat\modules\blueshield\code\modules\projectiles\guns\energy\special.dm" +#include "modular_skyrat\modules\customization\__DEFINES\inventory.dm" +#include "modular_skyrat\modules\customization\__DEFINES\lists.dm" +#include "modular_skyrat\modules\customization\__DEFINES\loadout.dm" +#include "modular_skyrat\modules\customization\__HELPERS\global_lists.dm" +#include "modular_skyrat\modules\customization\__HELPERS\is_helpers.dm" +#include "modular_skyrat\modules\customization\__HELPERS\mobs.dm" +#include "modular_skyrat\modules\customization\__HELPERS\names.dm" +#include "modular_skyrat\modules\customization\_globalvars\lists.dm" +#include "modular_skyrat\modules\customization\datums\dna.dm" +#include "modular_skyrat\modules\customization\game\objects\items\balls.dm" +#include "modular_skyrat\modules\customization\game\objects\items\storage\rings.dm" +#include "modular_skyrat\modules\customization\game\objects\items\tanks\n2_tanks.dm" +#include "modular_skyrat\modules\customization\modules\client\preferences.dm" +#include "modular_skyrat\modules\customization\modules\client\preferences_savefile.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\_loadout.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\backpack.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\glasses.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\gloves.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\hands.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\head.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\mask.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\neck.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\shoes.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\suit.dm" +#include "modular_skyrat\modules\customization\modules\client\loadout\uniform.dm" +#include "modular_skyrat\modules\customization\modules\clothing\clothing.dm" +#include "modular_skyrat\modules\customization\modules\clothing\ears\ears.dm" +#include "modular_skyrat\modules\customization\modules\clothing\hands\rings.dm" +#include "modular_skyrat\modules\customization\modules\clothing\head\head.dm" +#include "modular_skyrat\modules\customization\modules\clothing\masks\breath.dm" +#include "modular_skyrat\modules\customization\modules\clothing\neck\collars.dm" +#include "modular_skyrat\modules\customization\modules\clothing\outfits\vox.dm" +#include "modular_skyrat\modules\customization\modules\clothing\shoes\shoes.dm" +#include "modular_skyrat\modules\customization\modules\clothing\suits\armor.dm" +#include "modular_skyrat\modules\customization\modules\clothing\suits\coats.dm" +#include "modular_skyrat\modules\customization\modules\clothing\under\costumes.dm" +#include "modular_skyrat\modules\customization\modules\clothing\under\misc.dm" +#include "modular_skyrat\modules\customization\modules\clothing\under\pants.dm" +#include "modular_skyrat\modules\customization\modules\clothing\under\skirts_dresses.dm" +#include "modular_skyrat\modules\customization\modules\clothing\under\sweaters.dm" +#include "modular_skyrat\modules\customization\modules\jobs\_job.dm" +#include "modular_skyrat\modules\customization\modules\language\dwarf.dm" +#include "modular_skyrat\modules\customization\modules\language\language_holder.dm" +#include "modular_skyrat\modules\customization\modules\language\vox.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\preferences_setup.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\body_markings\body_marking_sets.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\body_markings\body_markings.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\body_markings\body_markings_synthliz.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\body_markings\body_markings_vox.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\ears.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\frills.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\genitals.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\ipc.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\snout.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\synthliz.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\tails.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\taur_types.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\vox.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\wings.dm" +#include "modular_skyrat\modules\customization\modules\mob\dead\new_player\sprite_accessories\xeno.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\carbon_update_icons.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\human.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\human_defines.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\human_update_icons.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\dwarf.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\ipc.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\lizard.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\mammal.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\podweak.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\roundstartslime.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\synthliz.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\vox.dm" +#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\xeno.dm" +#include "modular_skyrat\modules\customization\modules\surgery\bodyparts\_bodyparts.dm" +#include "modular_skyrat\modules\customization\modules\surgery\organs\ears.dm" +#include "modular_skyrat\modules\customization\modules\surgery\organs\genitals.dm" +#include "modular_skyrat\modules\customization\modules\surgery\organs\organ.dm" +#include "modular_skyrat\modules\customization\modules\surgery\organs\tails.dm" +#include "modular_skyrat\modules\customization\modules\surgery\organs\vox.dm" +#include "modular_skyrat\modules\customization\modules\surgery\organs\wings.dm" #include "modular_skyrat\modules\horrorform\code\modules\antagonists\changeling\powers\horror_form.dm" #include "modular_skyrat\modules\horrorform\code\modules\mob\hostile\true_changeling.dm" #include "modular_skyrat\modules\icspawning\code\_onclick\observer.dm"