diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm index 9e0a66fb6f2..1fb1cbf02cb 100644 --- a/code/__defines/belly_modes_vr.dm +++ b/code/__defines/belly_modes_vr.dm @@ -1,6 +1,7 @@ // Belly Mode Constants #define DM_HOLD "Hold" #define DM_DIGEST "Digest" +#define DM_DIGEST_NUMB "Digest (Numbing)" #define DM_HEAL "Heal" #define DM_ABSORB "Absorb" #define DM_TRANSFORM_HAIR_AND_EYES "Transform (Hair and eyes)" @@ -18,7 +19,6 @@ #define DM_DRAIN "Drain" #define DM_UNABSORB "Unabsorb" - // Stance for hostile mobs to be in while devouring someone. #define HOSTILE_STANCE_EATING 99 diff --git a/code/__defines/misc_vr.dm b/code/__defines/misc_vr.dm index 7f25f414758..b3c87fcec3b 100644 --- a/code/__defines/misc_vr.dm +++ b/code/__defines/misc_vr.dm @@ -15,3 +15,7 @@ #define VANTAG_KILL "vantag_kill" #define ANNOUNCER_NAME "Facility PA" + +//For custom species +#define STARTING_SPECIES_POINTS 1 +#define MAX_SPECIES_TRAITS 4 diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index 72937092c4f..73d41048ed2 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -32,7 +32,7 @@ var/global/list/all_species[0] var/global/list/all_languages[0] var/global/list/language_keys[0] // Table of say codes for all languages var/global/list/whitelisted_species = list("Human") // Species that require a whitelist check. -var/global/list/playable_species = list("Human") // A list of ALL playable species, whitelisted, latejoin or otherwise. +var/global/list/playable_species = list("Custom Species","Human") // A list of ALL playable species, whitelisted, latejoin or otherwise. //VOREStation Edit - Making sure custom species is obvious. var/list/mannequins_ diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm index fe953e1f1ba..3e83ce7fbf6 100644 --- a/code/_helpers/global_lists_vr.dm +++ b/code/_helpers/global_lists_vr.dm @@ -4,6 +4,11 @@ var/global/list/ear_styles_list = list() // Stores /datum/sprite_accessory/ears indexed by type var/global/list/tail_styles_list = list() // Stores /datum/sprite_accessory/tail indexed by type +var/global/list/negative_traits = list() // Negative custom species traits, indexed by path +var/global/list/neutral_traits = list() // Neutral custom species traits, indexed by path +var/global/list/positive_traits = list() // Positive custom species traits, indexed by path +var/global/list/traits_costs = list() // Just path = cost list, saves time in char setup +var/global/list/all_traits = list() // All of 'em at once (same instances) //stores numeric player size options indexed by name var/global/list/player_sizes_list = list( @@ -120,4 +125,20 @@ var/global/list/tf_egg_types = list( for(var/path in paths) var/datum/sprite_accessory/tail/instance = new path() tail_styles_list[path] = instance - return 1 // Hooks must return 1 + + // Custom species traits + paths = typesof(/datum/trait) - /datum/trait + for(var/path in paths) + var/datum/trait/instance = new path() + var/cost = instance.cost + traits_costs[path] = cost + all_traits[path] = instance + switch(cost) + if(-INFINITY to -0.1) + negative_traits[path] = instance + if(0) + neutral_traits[path] = instance + if(0.1 to INFINITY) + positive_traits[path] = instance + + return 1 // Hooks must return 1 \ No newline at end of file diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 6866f8fcb46..4e5af5e504e 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -90,6 +90,8 @@ var/global/list/datum/dna/gene/dna_genes[0] // VOREStation var/custom_species + var/base_species = "Human" + var/list/species_traits = list() // VOREStation // New stuff @@ -105,6 +107,8 @@ var/global/list/datum/dna/gene/dna_genes[0] new_dna.real_name=real_name new_dna.species=species new_dna.body_markings=body_markings.Copy() + new_dna.base_species=base_species //VOREStation Edit + new_dna.species_traits=species_traits.Copy() //VOREStation Edit for(var/b=1;b<=DNA_SE_LENGTH;b++) new_dna.SE[b]=SE[b] if(b<=DNA_UI_LENGTH) @@ -163,6 +167,10 @@ var/global/list/datum/dna/gene/dna_genes[0] // Technically custom_species is not part of the UI, but this place avoids merge problems. src.custom_species = character.custom_species + if(istype(character.species,/datum/species/custom)) + var/datum/species/custom/CS = character.species + src.species_traits = CS.traits.Copy() + src.base_species = CS.base_species // +1 to account for the none-of-the-above possibility SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 4482967cf93..784898cd824 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -201,11 +201,15 @@ // Technically custom_species is not part of the UI, but this place avoids merge problems. H.custom_species = dna.custom_species + if(istype(H.species,/datum/species/custom)) + var/datum/species/custom/CS = H.species + CS.produceCopy(dna.base_species,dna.species_traits,src) // VOREStation Edit End + H.force_update_organs() //VOREStation Add - Gotta do this too H.force_update_limbs() - H.update_body(0) + //H.update_body(0) //VOREStation Edit - Done in force_update_limbs already H.update_eyes() H.update_hair() @@ -213,6 +217,13 @@ else return 0 +//VOREStation Add +/mob/living/carbon/human/proc/force_update_organs() + for(var/organ in organs + internal_organs) + var/obj/item/organ/O = organ + O.species = species +//VOREStation Add End + // Used below, simple injection modifier. /proc/probinj(var/pr, var/inj) return prob(pr+inj*pr) diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 81bbf075dee..72df34b08cf 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -384,7 +384,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O var/list/valid_hairstyles = list() for(var/hairstyle in hair_styles_list) var/datum/sprite_accessory/S = hair_styles_list[hairstyle] - if(!(pref.species in S.species_allowed)) + if(!(pref.species in S.species_allowed) && (!pref.custom_base || !(pref.custom_base in S.species_allowed))) //VOREStation Edit - Custom species base species allowance continue valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] @@ -440,7 +440,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O continue if(pref.biological_gender == FEMALE && S.gender == MALE) continue - if(!(pref.species in S.species_allowed)) + if(!(pref.species in S.species_allowed) && (!pref.custom_base || !(pref.custom_base in S.species_allowed))) //VOREStation Edit - Custom species base species allowance continue valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle] diff --git a/code/modules/client/preference_setup/vore/01_ears.dm b/code/modules/client/preference_setup/vore/01_ears.dm index 9757e288462..04bec4c2eed 100644 --- a/code/modules/client/preference_setup/vore/01_ears.dm +++ b/code/modules/client/preference_setup/vore/01_ears.dm @@ -6,7 +6,6 @@ // Define a place to save appearance in character setup /datum/preferences - var/custom_species // Custom species name var/ear_style // Type of selected ear style var/tail_style // Type of selected tail style var/r_tail = 30 // Tail/Taur color @@ -20,7 +19,6 @@ sort_order = 1 /datum/category_item/player_setup_item/vore/ears/load_character(var/savefile/S) - S["custom_species"] >> pref.custom_species S["ear_style"] >> pref.ear_style S["tail_style"] >> pref.tail_style S["r_tail"] >> pref.r_tail @@ -28,7 +26,6 @@ S["b_tail"] >> pref.b_tail /datum/category_item/player_setup_item/vore/ears/save_character(var/savefile/S) - S["custom_species"] << pref.custom_species S["ear_style"] << pref.ear_style S["tail_style"] << pref.tail_style S["r_tail"] << pref.r_tail @@ -45,7 +42,6 @@ pref.tail_style = sanitize_inlist(pref.tail_style, tail_styles_list, initial(pref.tail_style)) /datum/category_item/player_setup_item/vore/ears/copy_to_mob(var/mob/living/carbon/human/character) - character.custom_species = pref.custom_species character.ear_style = ear_styles_list[pref.ear_style] character.tail_style = tail_styles_list[pref.tail_style] character.r_tail = pref.r_tail @@ -86,20 +82,10 @@ if (T.do_colouration) . += "Change Color
__

" - . += "Custom Species " - . += "[pref.custom_species ? pref.custom_species : "None"]
" - /datum/category_item/player_setup_item/vore/ears/OnTopic(var/href,var/list/href_list, var/mob/user) if(!CanUseTopic(user)) return TOPIC_NOACTION - else if(href_list["custom_species"]) - var/raw_choice = sanitize(input(user, "Input your character's species:", - "Character Preference", pref.custom_species) as null|text, MAX_NAME_LEN) - if (CanUseTopic(user)) - pref.custom_species = raw_choice - return TOPIC_REFRESH - else if(href_list["ear_style"]) // Construct the list of names allowed for this user. var/list/pretty_ear_styles = list("Normal" = null) diff --git a/code/modules/client/preference_setup/vore/07_traits.dm b/code/modules/client/preference_setup/vore/07_traits.dm new file mode 100644 index 00000000000..602751c63f0 --- /dev/null +++ b/code/modules/client/preference_setup/vore/07_traits.dm @@ -0,0 +1,245 @@ +#define POSITIVE_MODE 1 +#define NEUTRAL_MODE 2 +#define NEGATIVE_MODE 3 + +/datum/preferences + var/custom_species // Custom species name, can't be changed due to it having been used in savefiles already. + var/custom_base // What to base the custom species on + + var/list/pos_traits = list() // What traits they've selected for their custom species + var/list/neu_traits = list() + var/list/neg_traits = list() + + var/traits_cheating = 0 //Varedit by admins allows saving new maximums on people who apply/etc + var/starting_trait_points = STARTING_SPECIES_POINTS + var/max_traits = MAX_SPECIES_TRAITS + +// Definition of the stuff for Ears +/datum/category_item/player_setup_item/vore/traits + name = "Traits" + sort_order = 7 + +/datum/category_item/player_setup_item/vore/traits/load_character(var/savefile/S) + S["custom_species"] >> pref.custom_species + S["custom_base"] >> pref.custom_base + S["pos_traits"] >> pref.pos_traits + S["neu_traits"] >> pref.neu_traits + S["neg_traits"] >> pref.neg_traits + + S["traits_cheating"]>> pref.traits_cheating + S["max_traits"] >> pref.max_traits + S["trait_points"] >> pref.starting_trait_points + +/datum/category_item/player_setup_item/vore/traits/save_character(var/savefile/S) + S["custom_species"] << pref.custom_species + S["custom_base"] << pref.custom_base + S["pos_traits"] << pref.pos_traits + S["neu_traits"] << pref.neu_traits + S["neg_traits"] << pref.neg_traits + + S["traits_cheating"]<< pref.traits_cheating + S["max_traits"] << pref.max_traits + S["trait_points"] << pref.starting_trait_points + +/datum/category_item/player_setup_item/vore/traits/sanitize_character() + if(!pref.pos_traits) pref.pos_traits = list() + if(!pref.neu_traits) pref.neu_traits = list() + if(!pref.neg_traits) pref.neg_traits = list() + + if(!pref.traits_cheating) + pref.starting_trait_points = STARTING_SPECIES_POINTS + pref.max_traits = MAX_SPECIES_TRAITS + + if(pref.species != "Custom Species") + pref.custom_species = null + pref.pos_traits.Cut() + pref.neu_traits.Cut() + pref.neg_traits.Cut() + else + // Clean up positive traits + for(var/path in pref.pos_traits) + if(!(path in positive_traits)) + pref.pos_traits -= path + //Neutral traits + for(var/path in pref.neu_traits) + if(!(path in neutral_traits)) + pref.neu_traits -= path + //Negative traits + for(var/path in pref.neg_traits) + if(!(path in negative_traits)) + pref.neg_traits -= path + + if(!pref.custom_base || !(pref.custom_base in playable_species - whitelisted_species)) + pref.custom_base = "Human" + +/datum/category_item/player_setup_item/vore/traits/copy_to_mob(var/mob/living/carbon/human/character) + character.custom_species = pref.custom_species + if(pref.species == "Custom Species") + var/datum/species/custom/CS = character.species + var/S = pref.custom_base ? pref.custom_base : "Human" + CS.produceCopy(S, pref.pos_traits + pref.neu_traits + pref.neg_traits, character) + +/datum/category_item/player_setup_item/vore/traits/content(var/mob/user) + if(pref.species == "Custom Species" || pref.custom_species) + . += "Custom Species " + . += "[pref.custom_species ? pref.custom_species : "-Input Name-"]
" + + if(pref.species == "Custom Species") + . += "Icon Base: " + . += "[pref.custom_base ? pref.custom_base : "Human"]
" + + var/points_left = pref.starting_trait_points + var/traits_left = pref.max_traits + for(var/T in pref.pos_traits + pref.neu_traits + pref.neg_traits) + points_left -= traits_costs[T] + traits_left-- + + . += "Points Left: [points_left]
" + . += "Traits Left: [traits_left]
" + if(points_left < 0 || traits_left < 0 || !pref.custom_species) + . += "^ Fix things! ^
" + + . += "Positive Trait +
" + . += "" + + . += "Neutral Trait +
" + . += "" + + . += "Negative Trait +
" + . += "" + +/datum/category_item/player_setup_item/vore/traits/OnTopic(var/href,var/list/href_list, var/mob/user) + if(!CanUseTopic(user)) + return TOPIC_NOACTION + + else if(href_list["custom_species"]) + if(pref.species != "Custom Species") + alert("You cannot set a custom species name unless you set your character to use the 'Custom Species' \ + species on the 'General' tab. If you have this set to something, it's because you had it set before the \ + Trait system was implemented. If you wish to change it, set your species to 'Custom Species' and configure \ + the species completely.") + return TOPIC_REFRESH + var/raw_choice = sanitize(input(user, "Input your custom species name:", + "Character Preference", pref.custom_species) as null|text, MAX_NAME_LEN) + if (CanUseTopic(user)) + pref.custom_species = raw_choice + return TOPIC_REFRESH + + else if(href_list["custom_base"]) + var/text_choice = input("Pick an icon set for your species:","Icon Base") in playable_species - whitelisted_species - "Custom Species" + if(text_choice in playable_species) + pref.custom_base = text_choice + return TOPIC_REFRESH_UPDATE_PREVIEW + + else if(href_list["clicked_pos_trait"]) + var/datum/trait/trait = text2path(href_list["clicked_pos_trait"]) + var/choice = alert("Remove [initial(trait.name)] and regain [initial(trait.cost)] points?","Remove Trait","Remove","Cancel") + if(choice == "Remove") + pref.pos_traits -= trait + return TOPIC_REFRESH + + else if(href_list["clicked_neu_trait"]) + var/datum/trait/trait = text2path(href_list["clicked_neu_trait"]) + var/choice = alert("Remove [initial(trait.name)]?","Remove Trait","Remove","Cancel") + if(choice == "Remove") + pref.neu_traits -= trait + return TOPIC_REFRESH + + else if(href_list["clicked_neg_trait"]) + var/datum/trait/trait = text2path(href_list["clicked_neg_trait"]) + var/choice = alert("Remove [initial(trait.name)] and lose [initial(trait.cost)] points?","Remove Trait","Remove","Cancel") + if(choice == "Remove") + pref.neg_traits -= trait + return TOPIC_REFRESH + + else if(href_list["add_trait"]) + var/mode = text2num(href_list["add_trait"]) + var/list/picklist + var/list/mylist + switch(mode) + if(POSITIVE_MODE) + picklist = positive_traits.Copy() - pref.pos_traits + mylist = pref.pos_traits + if(NEUTRAL_MODE) + picklist = neutral_traits.Copy() - pref.pos_traits + mylist = pref.neu_traits + if(NEGATIVE_MODE) + picklist = negative_traits.Copy() - pref.pos_traits + mylist = pref.neg_traits + else + + if(isnull(picklist)) + return TOPIC_REFRESH + + if(isnull(mylist)) + return TOPIC_REFRESH + + var/list/nicelist = list() + for(var/P in picklist) + var/datum/trait/T = picklist[P] + nicelist[T.name] = P + + var/points_left = pref.starting_trait_points + for(var/T in pref.pos_traits + pref.neu_traits + pref.neg_traits) + points_left -= traits_costs[T] + + var/traits_left = pref.max_traits - (pref.pos_traits.len + pref.neg_traits.len + pref.neu_traits.len) + + var/trait_choice + var/done = FALSE + while(!done) + var/message = "\[Remaining: [points_left] points, [traits_left] traits\] Select a trait to read the description and see the cost." + trait_choice = input(message,"Positive Traits") in nicelist + if(trait_choice in nicelist) + var/datum/trait/path = nicelist[trait_choice] + var/choice = alert("\[Cost:[initial(path.cost)]\] [initial(path.desc)]",initial(path.name),"Take Trait","Cancel","Go Back") + if(choice == "Cancel") + trait_choice = null + if(choice != "Go Back") + done = TRUE + + if(!trait_choice) + return TOPIC_REFRESH + else if(trait_choice in nicelist) + var/datum/trait/path = nicelist[trait_choice] + var/datum/trait/instance = all_traits[path] + + var/conflict = FALSE + + varconflict: + for(var/P in pref.pos_traits + pref.neu_traits + pref.neg_traits) + var/datum/trait/instance_test = all_traits[P] + if(path in instance_test.excludes) + conflict = instance_test.name + break varconflict + + for(var/V in instance.var_changes) + if(V in instance_test.var_changes) + conflict = instance_test.name + break varconflict + + if(conflict) + alert("You cannot take this trait and [conflict] at the same time. \ + Please remove that trait, or pick another trait to add.","Error") + return TOPIC_REFRESH + + mylist += path + return TOPIC_REFRESH + + return ..() + +#undef POSITIVE_MODE +#undef NEUTRAL_MODE +#undef NEGATIVE_MODE diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 2c35c44fffc..3489b25d8c4 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -274,7 +274,10 @@ datum/preferences // Ask the preferences datums to apply their own settings to the new mob player_setup.copy_to_mob(character) - + + // VOREStation Edit - Sync up all their organs and species one final time + character.force_update_organs() + if(icon_updates) character.force_update_limbs() character.update_mutations(0) diff --git a/code/modules/mob/living/carbon/human/species/station/blank_vr.dm b/code/modules/mob/living/carbon/human/species/station/blank_vr.dm new file mode 100644 index 00000000000..1906bd37228 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/station/blank_vr.dm @@ -0,0 +1,108 @@ +/datum/species + var/vore_numbing = 0 + +/datum/species/custom + name = "Custom Species" + name_plural = "Custom" + var/base_species = "Human" + + unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) + + blurb = "This is a custom species where you can assign various species traits to them as you wish, to \ + create a (hopefully) balanced species. You will see the options to customize them on the VORE tab once \ + you select and set this species as your species. Please look at the VORE tab if you select this species." + + name_language = null // Use the first-name last-name generator rather than a language scrambler + min_age = 18 + max_age = 200 + health_hud_intensity = 2 + num_alternate_languages = 3 + + spawn_flags = SPECIES_CAN_JOIN + appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR + + var/list/traits = list() + +/datum/species/custom/get_bodytype() + return base_species + +/datum/species/custom/get_race_key() + var/datum/species/real = all_species[base_species] + return real.race_key + +/datum/species/custom/proc/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H) + ASSERT(to_copy) + ASSERT(istype(H)) + + if(ispath(to_copy)) + to_copy = "[initial(to_copy.name)]" + if(istext(to_copy)) + to_copy = all_species[to_copy] + + var/datum/species/custom/new_copy = new() + + //Initials so it works with a simple path passed, or an instance + new_copy.base_species = to_copy.name + new_copy.icobase = to_copy.icobase + new_copy.deform = to_copy.deform + new_copy.tail = to_copy.tail + new_copy.tail_animation = to_copy.tail_animation + new_copy.icobase_tail = to_copy.icobase_tail + new_copy.color_mult = to_copy.color_mult + new_copy.primitive_form = to_copy.primitive_form + new_copy.appearance_flags = to_copy.appearance_flags + new_copy.flesh_color = to_copy.flesh_color + new_copy.base_color = to_copy.base_color + new_copy.blood_mask = to_copy.blood_mask + new_copy.damage_mask = to_copy.damage_mask + new_copy.damage_overlays = to_copy.damage_overlays + + new_copy.traits = traits + + //If you had traits, apply them + if(new_copy.traits) + for(var/trait in new_copy.traits) + var/datum/trait/T = all_traits[trait] + T.apply(new_copy,H) + + //Set up a mob + H.species = new_copy + H.icon_state = lowertext(new_copy.get_bodytype()) + + if(new_copy.holder_type) + H.holder_type = new_copy.holder_type + + if(H.dna) + H.dna.ready_dna(H) + + return new_copy + +// Stub species overrides for shoving trait abilities into + +//Called when face-down in the water or otherwise over their head. +// Return: TRUE for able to breathe fine in water. +/datum/species/custom/can_breathe_water() + return ..() + +//Called during handle_environment in Life() ticks. +// Return: Not used. +/datum/species/custom/handle_environment_special(var/mob/living/carbon/human/H) + return ..() + +//Called when spawning to equip them with special things. +/datum/species/custom/equip_survival_gear(var/mob/living/carbon/human/H) + /* Example, from Vox: + H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(H), slot_wear_mask) + if(H.backbag == 1) + H.equip_to_slot_or_del(new /obj/item/weapon/tank/vox(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/vox(H), slot_r_hand) + H.internal = H.back + else + H.equip_to_slot_or_del(new /obj/item/weapon/tank/vox(H), slot_r_hand) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/vox(H.back), slot_in_backpack) + H.internal = H.r_hand + H.internal = locate(/obj/item/weapon/tank) in H.contents + if(istype(H.internal,/obj/item/weapon/tank) && H.internals) + H.internals.icon_state = "internal1" + */ + return ..() diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm new file mode 100644 index 00000000000..0a854e34567 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm @@ -0,0 +1,63 @@ +/datum/trait/speed_slow + name = "Slowdown" + desc = "Allows you to move slower on average than baseline." + cost = -1 + var_changes = list("slowdown" = 0.3) + +/datum/trait/speed_slow_plus + name = "Slowdown (Plus)" + desc = "Allows you to move MUCH slower on average than baseline." + cost = -2 + var_changes = list("slowdown" = 0.5) + +/datum/trait/weakling + name = "Weakling" + desc = "Causes heavy equipment to slow you down more when carried." + cost = -1 + var_changes = list("item_slowdown_mod" = 1.5) + +/datum/trait/weakling_plus + name = "Weakling (Plus)" + desc = "Allows you to carry heavy equipment with much more slowdown." + cost = -2 + var_changes = list("item_slowdown_mod" = 2.0) + +/datum/trait/endurance_low + name = "Low Endurance" + desc = "Reduces your maximum total hitpoints." + cost = -2 + var_changes = list("total_health" = 75) + + apply(var/datum/species/S,var/mob/living/carbon/human/H) + ..(S,H) + H.setMaxHealth(S.total_health) + +/datum/trait/brute_weak + name = "Brute Weakness" + desc = "Increases damage from brute damage sources." + cost = -1 + var_changes = list("brute_mod" = 1.15) + +/datum/trait/brute_weak_plus + name = "Brute Weakness (Plus)" + desc = "Increases damage significantly from brute damage sources." + cost = -2 + var_changes = list("brute_mod" = 1.30) + +/datum/trait/burn_weak + name = "Burn Weakness" + desc = "Increases damage from burn damage sources." + cost = -1 + var_changes = list("burn_mod" = 1.15) + +/datum/trait/burn_weak_plus + name = "Burn Weakness (Plus)" + desc = "Increases damage significantly from burn damage sources." + cost = -2 + var_changes = list("burn_mod" = 1.30) + +/datum/trait/photosensitive + name = "Photosensitive" + desc = "Increases stun duration from flashes and other light-based stuns." + cost = -1 + var_changes = list("flash_mod" = 2.0) diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm new file mode 100644 index 00000000000..b27dbf9cbc9 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm @@ -0,0 +1,31 @@ +/datum/trait/metabolism_up + name = "Fast Metabolism" + desc = "You process ingested and injected reagents faster, but get hungry faster." + cost = 0 + var_changes = list("metabolic_rate" = 1.2) + +/datum/trait/metabolism_down + name = "Slow Metabolism" + desc = "You process ingested and injected reagents slower, but get hungry slower." + cost = 0 + var_changes = list("metabolic_rate" = 0.8) + +/datum/trait/vore_numbing + name = "Prey Numbing" + desc = "Adds a 'Digest (Numbing)' belly mode, to douse prey in numbing enzymes during digestion." + cost = 0 + var_changes = list("vore_numbing" = TRUE) + +/datum/trait/cold_discomfort + name = "Hot-Blooded" + desc = "You are too hot at the standard 20C. 18C is more suitable. Rolling down your jumpsuit or being unclothed helps." + cost = 0 + var_changes = list("heat_discomfort_level" = T0C+19) + excludes = list(/datum/trait/hot_discomfort) + +/datum/trait/hot_discomfort + name = "Cold-Blooded" + desc = "You are too cold at the standard 20C. 22C is more suitable. Wearing clothing that covers your legs and torso helps." + cost = 0 + var_changes = list("cold_discomfort_level" = T0C+21) + excludes = list(/datum/trait/cold_discomfort) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm new file mode 100644 index 00000000000..9c1c1519c82 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm @@ -0,0 +1,75 @@ +/datum/trait/speed_fast + name = "Haste" + desc = "Allows you to move faster on average than baseline." + cost = 2 + var_changes = list("slowdown" = -0.3) + +/datum/trait/speed_fast_plus + name = "Haste (Plus)" + desc = "Allows you to move MUCH faster on average than baseline." + cost = 3 + var_changes = list("slowdown" = -0.5) + +/datum/trait/hardy + name = "Hardy" + desc = "Allows you to carry heavy equipment with less slowdown." + cost = 1 + var_changes = list("item_slowdown_mod" = 0.5) + +/datum/trait/hardy_plus + name = "Hardy (Plus)" + desc = "Allows you to carry heavy equipment with almost no slowdown." + cost = 2 + var_changes = list("item_slowdown_mod" = 0.1) + +/datum/trait/endurance_high + name = "High Endurance" + desc = "Increases your maximum total hitpoints." + cost = 2 + var_changes = list("total_health" = 125) + + apply(var/datum/species/S,var/mob/living/carbon/human/H) + ..(S,H) + H.setMaxHealth(S.total_health) + +/datum/trait/darksight + name = "Darksight" + desc = "Allows you to see a short distance in the dark." + cost = 1 + var_changes = list("darksight" = 3) + +/datum/trait/darksight_plus + name = "Darksight (Plus)" + desc = "Allows you to see in the dark for the whole screen." + cost = 2 + var_changes = list("darksight" = 7) + +/datum/trait/melee_attack + name = "Sharp Melee" + desc = "Provides sharp melee attacks that do slightly more damage." + cost = 1 + var_changes = list("unarmed_types" = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp)) + +/datum/trait/brute_resist + name = "Brute Resist" + desc = "Adds some resistance to brute damage sources." + cost = 1 + var_changes = list("brute_mod" = 0.85) + +/datum/trait/brute_resist_plus + name = "Brute Resist (Plus)" + desc = "Adds some resistance to brute damage sources." + cost = 2 + var_changes = list("brute_mod" = 0.70) + +/datum/trait/burn_resist + name = "Burn Resist" + desc = "Adds some resistance to burn damage sources." + cost = 1 + var_changes = list("burn_mod" = 0.85) + +/datum/trait/burn_resist_plus + name = "Burn Resist (Plus)" + desc = "Adds some resistance to burn damage sources." + cost = 2 + var_changes = list("burn_mod" = 0.70) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm new file mode 100644 index 00000000000..b225cc6e896 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm @@ -0,0 +1,20 @@ +/datum/trait + var/name = "Prototype Trait" + var/desc = "Contact a developer if you see this trait." + + var/cost = 0 // 0 is neutral, negative cost means negative, positive cost means positive. + var/list/var_changes // A list to apply to the custom species vars. + var/list/excludes // Store a list of paths of traits to exclude, but done automatically if they change the same vars. + +//Proc can be overridden lower to include special changes, make sure to call up though for the vars changes +/datum/trait/proc/apply(var/datum/species/S,var/mob/living/carbon/human/H) + ASSERT(S) + if(var_changes) + for(var/V in var_changes) + S.vars[V] = var_changes[V] + return + +//Similar to the above, but for removing. Probably won't be called often/ever. +/datum/trait/proc/remove(var/datum/species/S) + ASSERT(S) + return diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 459195f092f..554de787d79 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -387,6 +387,7 @@ default behaviour is: return result /mob/living/proc/setMaxHealth(var/newMaxHealth) + health = (health/maxHealth) * (newMaxHealth) //VOREStation Add - Adjust existing health maxHealth = newMaxHealth /mob/living/Stun(amount) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 782e03a06af..c4ad0699ef9 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -488,7 +488,7 @@ //new_character.dna.UpdateSE() // Do the initial caching of the player's body icons. - new_character.force_update_limbs() + //new_character.force_update_limbs() //VOREStation Removal - This is done in copy_to, don't waste time. new_character.update_eyes() new_character.regenerate_icons() diff --git a/code/modules/mob/new_player/new_player_vr.dm b/code/modules/mob/new_player/new_player_vr.dm index d2dbfadf523..199563de4a7 100644 --- a/code/modules/mob/new_player/new_player_vr.dm +++ b/code/modules/mob/new_player/new_player_vr.dm @@ -1,8 +1,41 @@ /mob/new_player/proc/spawn_checks_vr() - var/pass = 1 - if (config.allow_Metadata && client && client.prefs && (isnull(client.prefs.metadata) || length(client.prefs.metadata) < 5)) - src << "You must first set your OOC notes before spawning in!" - pass = 0 + var/pass = TRUE + + //No OOC notes + if (config.allow_Metadata && client && client.prefs && (isnull(client.prefs.metadata) || length(client.prefs.metadata) < 15)) + src << "Please set informative OOC notes related to ERP preferences. Set them using the 'OOC Notes' button on the 'General' tab in character setup." + pass = FALSE + + //Custom species checks + if (client && client.prefs && client.prefs.species == "Custom Species") + + //Didn't name it + if(!client.prefs.custom_species) + pass = FALSE + src << "You have to name your custom species. Do this on the VORE tab in character setup." + + //Check traits/costs + var/list/megalist = client.prefs.pos_traits + client.prefs.neu_traits + client.prefs.neg_traits + var/points_left = client.prefs.starting_trait_points + var/traits_left = client.prefs.max_traits + for(var/T in megalist) + traits_left-- + var/cost = traits_costs[T] + + //A trait was removed from the game + if(isnull(cost)) + pass = FALSE + src << "Your custom species is not playable. One or more traits appear to have been removed from the game or renamed. Enter character setup to correct this." + break + else + points_left -= traits_costs[T] + + //Went into negatives + if(points_left < 0 || traits_left < 0) + pass = FALSE + src << "Your custom species is not playable. Reconfigure your traits on the VORE tab." + + //Final popup notice if (!pass) alert(src,"There were problems with spawning your character. Check your message log for details.","Error","OK") return pass diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 02450c2c5cc..1899b8a3c76 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -55,7 +55,7 @@ var/list/organ_cache = list() species = all_species["Human"] if(holder.dna) dna = holder.dna.Clone() - species = all_species[dna.species] + species = holder.species //VOREStation Edit - For custom species else log_debug("[src] at [loc] spawned without a proper DNA.") var/mob/living/carbon/human/H = holder diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index c64fb36cc4c..fc734e0e813 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -102,7 +102,7 @@ var/global/list/limb_icon_cache = list() if(owner && owner.gender == MALE) gender = "m" - icon_cache_key = "[icon_name]_[species ? species.name : "Human"]" + icon_cache_key = "[icon_name]_[species ? species.get_bodytype() : "Human"]" //VOREStation Edit if(force_icon) mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_[gender]" : ""]") diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine_vr.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine_vr.dm index ddc0a5a4117..bebbb913250 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine_vr.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine_vr.dm @@ -15,4 +15,17 @@ if(M.eye_blurry) M.eye_blurry = max(M.eye_blurry - 8*removed, 0) if(M.jitteriness) - M.make_jittery(max(M.jitteriness - 8*removed,0)) \ No newline at end of file + M.make_jittery(max(M.jitteriness - 8*removed,0)) + +/datum/reagent/numbing_enzyme + name = "Numbing Enzyme" + id = "numbenzyme" + description = "Some sort of organic painkiller." + taste_description = "sourness" + reagent_state = LIQUID + color = "#800080" + metabolism = 0.02 + mrate_static = TRUE + +/datum/reagent/numbing_enzyme/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + M.add_chemical_effect(CE_PAINKILLER, 200) diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm index 0836ef18918..2a14eb0a895 100644 --- a/code/modules/vore/eating/bellymodes_vr.dm +++ b/code/modules/vore/eating/bellymodes_vr.dm @@ -22,7 +22,7 @@ return //Pretty boring, huh //////////////////////////// DM_DIGEST //////////////////////////// - if(digest_mode == DM_DIGEST) + if(digest_mode == DM_DIGEST || digest_mode == DM_DIGEST_NUMB) if(prob(50)) //Was SO OFTEN. AAAA. var/churnsound = pick(digestion_sounds) @@ -60,6 +60,11 @@ owner.update_icons() continue + if(digest_mode == DM_DIGEST_NUMB && ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.bloodstr.get_reagent_amount("numbenzyme") < 5) + H.bloodstr.add_reagent("numbenzyme",10) + // Deal digestion damage (and feed the pred) if(!(M.status_flags & GODMODE)) M.adjustBruteLoss(digest_brute) diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index e186b8ec841..9e882c5ab8f 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -451,6 +451,9 @@ if(href_list["b_mode"]) var/list/menu_list = selected.digest_modes if(istype(usr,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = usr + if(H.species.vore_numbing) + menu_list += DM_DIGEST_NUMB menu_list += selected.transform_modes if(selected.digest_modes.len == 1) // Don't do anything diff --git a/vorestation.dme b/vorestation.dme index 3b28ef75d1e..0c298486a4f 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1298,6 +1298,7 @@ #include "code\modules\client\preference_setup\vore\04_resleeving.dm" #include "code\modules\client\preference_setup\vore\05_persistence.dm" #include "code\modules\client\preference_setup\vore\06_vantag.dm" +#include "code\modules\client\preference_setup\vore\07_traits.dm" #include "code\modules\clothing\chameleon.dm" #include "code\modules\clothing\clothing.dm" #include "code\modules\clothing\clothing_accessories.dm" @@ -1764,6 +1765,7 @@ #include "code\modules\mob\living\carbon\human\species\species_vr.dm" #include "code\modules\mob\living\carbon\human\species\outsider\shadow.dm" #include "code\modules\mob\living\carbon\human\species\outsider\vox.dm" +#include "code\modules\mob\living\carbon\human\species\station\blank_vr.dm" #include "code\modules\mob\living\carbon\human\species\station\golem.dm" #include "code\modules\mob\living\carbon\human\species\station\monkey.dm" #include "code\modules\mob\living\carbon\human\species\station\monkey_vr.dm" @@ -1774,6 +1776,10 @@ #include "code\modules\mob\living\carbon\human\species\station\station_special_abilities_vr.dm" #include "code\modules\mob\living\carbon\human\species\station\station_special_vr.dm" #include "code\modules\mob\living\carbon\human\species\station\station_vr.dm" +#include "code\modules\mob\living\carbon\human\species\station\traits_vr\negative.dm" +#include "code\modules\mob\living\carbon\human\species\station\traits_vr\neutral.dm" +#include "code\modules\mob\living\carbon\human\species\station\traits_vr\positive.dm" +#include "code\modules\mob\living\carbon\human\species\station\traits_vr\trait.dm" #include "code\modules\mob\living\carbon\metroid\death.dm" #include "code\modules\mob\living\carbon\metroid\emote.dm" #include "code\modules\mob\living\carbon\metroid\examine.dm"