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"