From 8ff09328893abf687f7500cb51e123224fb274cf Mon Sep 17 00:00:00 2001 From: "C.L" Date: Thu, 20 Jun 2024 16:04:43 -0400 Subject: [PATCH] Adds Toggleable Stomachs w/ toggleable visibility (#16052) * Adds Tummy * Toggleable stomachs! * Squash Squash * Update _planes+layers_vr.dm --- code/__defines/_planes+layers_vr.dm | 1 + code/__defines/mobs_vr.dm | 4 +- code/_helpers/unsorted.dm | 1 + .../client/preference_setup/vore/09_misc.dm | 15 ++ code/modules/client/preferences_vr.dm | 1 + code/modules/mob/living/carbon/human/human.dm | 27 +++ .../mob/living/carbon/human/human_helpers.dm | 9 + .../living/carbon/human/species/species.dm | 2 + .../mob/living/carbon/human/update_icons.dm | 75 ++++++- code/modules/mob/mob_defines_vr.dm | 1 + code/modules/mob/mob_helpers_vr.dm | 38 ++++ code/modules/mob/mob_planes_vr.dm | 1 + .../mob/new_player/sprite_accessories_taur.dm | 75 ++++++- .../new_player/sprite_accessories_taur_vr.dm | 59 +++++- code/modules/vore/eating/belly_obj_vr.dm | 91 +++++++++ .../vore/eating/bellymodes_datum_vr.dm | 9 + code/modules/vore/eating/living_vr.dm | 6 + code/modules/vore/eating/vore_vr.dm | 7 +- code/modules/vore/eating/vorepanel_vr.dm | 133 +++++++++++- icons/mob/vore/Bellies.dmi | Bin 0 -> 7013 bytes icons/mob/vore/Taur_Bellies.dmi | Bin 0 -> 33603 bytes tgui/packages/tgui/interfaces/VorePanel.jsx | 189 ++++++++++++++++++ 22 files changed, 732 insertions(+), 12 deletions(-) create mode 100644 icons/mob/vore/Bellies.dmi create mode 100644 icons/mob/vore/Taur_Bellies.dmi diff --git a/code/__defines/_planes+layers_vr.dm b/code/__defines/_planes+layers_vr.dm index 125f492cd7..a3cb889b46 100644 --- a/code/__defines/_planes+layers_vr.dm +++ b/code/__defines/_planes+layers_vr.dm @@ -3,5 +3,6 @@ #define PLANE_CH_STATUS_R 27 //Right-side status icon #define PLANE_CH_BACKUP 28 //Backup implant #define PLANE_CH_VANTAG 29 //Vore Antag hud +#define PLANE_CH_STOMACH 30 //Stomach Plane #define PLANE_AUGMENTED 40 //Augmented-reality plane diff --git a/code/__defines/mobs_vr.dm b/code/__defines/mobs_vr.dm index 61080f2fca..ae87b1c624 100644 --- a/code/__defines/mobs_vr.dm +++ b/code/__defines/mobs_vr.dm @@ -7,7 +7,9 @@ #define VIS_AUGMENTED 32 -#define VIS_COUNT 32 +#define VIS_CH_STOMACH 33 + +#define VIS_COUNT 33 //Protean organs #define O_ORCH "orchestrator" diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 20c38938a5..8a722ac767 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -1580,6 +1580,7 @@ GLOBAL_REAL_VAR(list/stack_trace_storage) . += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH_VR} //Health bar but transparent at 100 . += new /obj/screen/plane_master{plane = PLANE_CH_BACKUP} //Backup implant status . += new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags + . += new /obj/screen/plane_master{plane = PLANE_CH_STOMACH} //Stomachs . += new /obj/screen/plane_master{plane = PLANE_AUGMENTED} //Augmented reality //VOREStation Add End /proc/CallAsync(datum/source, proctype, list/arguments) diff --git a/code/modules/client/preference_setup/vore/09_misc.dm b/code/modules/client/preference_setup/vore/09_misc.dm index bde733d4c8..963354baea 100644 --- a/code/modules/client/preference_setup/vore/09_misc.dm +++ b/code/modules/client/preference_setup/vore/09_misc.dm @@ -11,6 +11,7 @@ S["capture_crystal"] >> pref.capture_crystal S["auto_backup_implant"] >> pref.auto_backup_implant S["borg_petting"] >> pref.borg_petting + S["stomach_vision"] >> pref.stomach_vision /datum/category_item/player_setup_item/vore/misc/save_character(var/savefile/S) S["show_in_directory"] << pref.show_in_directory @@ -21,12 +22,21 @@ S["capture_crystal"] << pref.capture_crystal S["auto_backup_implant"] << pref.auto_backup_implant S["borg_petting"] << pref.borg_petting + S["stomach_vision"] << pref.stomach_vision /datum/category_item/player_setup_item/vore/misc/copy_to_mob(var/mob/living/carbon/human/character) if(pref.sensorpref > 5 || pref.sensorpref < 1) pref.sensorpref = 5 character.sensorpref = pref.sensorpref character.capture_crystal = pref.capture_crystal + //Vore Stomach Sprite Preference + character.stomach_vision = pref.stomach_vision + if((character && !istype(character,/mob/living/carbon/human/dummy)) && character.stomach_vision && !(VIS_CH_STOMACH in character.vis_enabled)) + character.plane_holder.set_vis(VIS_CH_STOMACH,TRUE) + character.vis_enabled += VIS_CH_STOMACH + else if((character && !istype(character,/mob/living/carbon/human/dummy)) && !character.stomach_vision && (VIS_CH_STOMACH in character.vis_enabled)) + character.plane_holder.set_vis(VIS_CH_STOMACH,FALSE) + character.vis_enabled -= VIS_CH_STOMACH /datum/category_item/player_setup_item/vore/misc/sanitize_character() pref.show_in_directory = sanitize_integer(pref.show_in_directory, 0, 1, initial(pref.show_in_directory)) @@ -36,6 +46,7 @@ pref.capture_crystal = sanitize_integer(pref.capture_crystal, 0, 1, initial(pref.capture_crystal)) pref.auto_backup_implant = sanitize_integer(pref.auto_backup_implant, 0, 1, initial(pref.auto_backup_implant)) pref.borg_petting = sanitize_integer(pref.borg_petting, 0, 1, initial(pref.borg_petting)) + pref.stomach_vision = sanitize_integer(pref.stomach_vision, 0, 1, initial(pref.stomach_vision)) /datum/category_item/player_setup_item/vore/misc/content(var/mob/user) . += "
" @@ -47,6 +58,7 @@ . += "Capture Crystal Preference: [pref.capture_crystal ? "Yes" : "No"]
" . += "Spawn With Backup Implant: [pref.auto_backup_implant ? "Yes" : "No"]
" . += "Allow petting as robot: [pref.borg_petting ? "Yes" : "No"]
" + . += "Enable Stomach Sprites: [pref.stomach_vision ? "Yes" : "No"]
" /datum/category_item/player_setup_item/vore/misc/OnTopic(var/href, var/list/href_list, var/mob/user) if(href_list["toggle_show_in_directory"]) @@ -84,4 +96,7 @@ else if(href_list["toggle_borg_petting"]) pref.borg_petting = pref.borg_petting ? 0 : 1; return TOPIC_REFRESH + else if(href_list["toggle_stomach_vision"]) + pref.stomach_vision = pref.stomach_vision ? 0 : 1; + return TOPIC_REFRESH return ..(); diff --git a/code/modules/client/preferences_vr.dm b/code/modules/client/preferences_vr.dm index ee3363dff5..f1cfc4413a 100644 --- a/code/modules/client/preferences_vr.dm +++ b/code/modules/client/preferences_vr.dm @@ -7,6 +7,7 @@ var/capture_crystal = 1 //Whether or not someone is able to be caught with capture crystals var/auto_backup_implant = FALSE //Whether someone starts with a backup implant or not. var/borg_petting = TRUE //Whether someone can be petted as a borg or not. + var/stomach_vision = TRUE //Whether or not someone can view stomach sprites var/job_talon_high = 0 var/job_talon_med = 0 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f298a47fcb..712f549626 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -7,6 +7,17 @@ has_huds = TRUE //We do have HUDs (like health, wanted, status, not inventory slots) + + var/vore_capacity = 3 + var/vore_capacity_ex = list("stomach" = 3, "taur belly" = 3) + var/vore_fullness_ex = list("stomach" = 0, "taur belly" = 0) + var/vore_icon_bellies = list("stomach", "taur belly") + var/struggle_anim_stomach = FALSE + var/struggle_anim_taur = FALSE + var/vore_sprite_color = list("stomach" = "#FFFFFF", "taur belly" = "#FFFFFF") + var/vore_sprite_multiply = list("stomach" = TRUE, "taur belly" = TRUE) + var/vore_fullness = 0 + var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call. var/last_push_time //For human_attackhand.dm, keeps track of the last use of disarm @@ -1778,3 +1789,19 @@ /mob/living/carbon/human/get_mob_riding_slots() return list(back, head, wear_suit) + +/mob/living/carbon/human/proc/update_fullness() + var/list/new_fullness = list() + vore_fullness = 0 + for(var/belly_class in vore_icon_bellies) + new_fullness[belly_class] = 0 + for(var/obj/belly/B as anything in vore_organs) + new_fullness[B.belly_sprite_to_affect] += B.GetFullnessFromBelly() + for(var/belly_class in vore_icon_bellies) + new_fullness[belly_class] /= size_multiplier //Divided by pred's size so a macro mob won't get macro belly from a regular prey. + new_fullness[belly_class] = round(new_fullness[belly_class], 1) // Because intervals of 0.25 are going to make sprite artists cry. + vore_fullness_ex[belly_class] = min(vore_capacity_ex[belly_class], new_fullness[belly_class]) + vore_fullness += new_fullness[belly_class] + vore_fullness = min(vore_capacity, vore_fullness) + update_vore_belly_sprite() + update_vore_tail_sprite() diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 692f121ba8..c531ef5086 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -192,6 +192,15 @@ compiled_vis |= VIS_CH_VANTAG //VOREStation Add End + //Vore Stomach addition start. This goes here. + if(stomach_vision && !(VIS_CH_STOMACH in vis_enabled)) + plane_holder.set_vis(VIS_CH_STOMACH,TRUE) + compiled_vis += VIS_CH_STOMACH + else if(!stomach_vision && (VIS_CH_STOMACH in vis_enabled)) + plane_holder.set_vis(VIS_CH_STOMACH,FALSE) + compiled_vis -= VIS_CH_STOMACH + //Vore Stomach addition end + if(!compiled_vis.len && !vis_enabled.len) return //Nothin' doin'. diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index b83b36eeda..3b471a84a3 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -222,6 +222,8 @@ var/rarity_value = 1 // Relative rarity/collector value for this species. var/economic_modifier = 2 // How much money this species makes + var/vore_belly_default_variant = "H" + // Determines the organs that the species spawns with and var/list/has_organ = list( // which required-organ checks are conducted. O_HEART = /obj/item/organ/internal/heart, diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 9d82aaa30a..3a1441f334 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -97,7 +97,10 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() #define FIRE_LAYER 35 //'Mob on fire' overlay layer // # define MOB_WATER_LAYER 36 //'Mob submerged' overlay layer // Moved to global defines #define TARGETED_LAYER 37 //'Aimed at' overlay layer -#define TOTAL_LAYERS 37 //VOREStation edit. <---- KEEP THIS UPDATED, should always equal the highest number here, used to initialize a list. +#define VORE_BELLY_LAYER 38 +#define VORE_TAIL_LAYER 39 + +#define TOTAL_LAYERS 39 //VOREStation edit. <---- KEEP THIS UPDATED, should always equal the highest number here, used to initialize a list. ////////////////////////////////// /mob/living/carbon/human @@ -421,6 +424,8 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() //tail update_tail_showing() update_wing_showing() + update_vore_belly_sprite() + update_vore_tail_sprite() /mob/living/carbon/human/proc/update_skin() if(QDESTROYING(src)) @@ -1393,6 +1398,74 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if((. = ..())) update_wing_showing() +/mob/living/carbon/human/proc/update_vore_belly_sprite() + if(QDESTROYING(src)) + return + + remove_layer(VORE_BELLY_LAYER) + + var/image/vore_belly_image = get_vore_belly_image() + if(vore_belly_image) + vore_belly_image.layer = BODY_LAYER+VORE_BELLY_LAYER + overlays_standing[VORE_BELLY_LAYER] = vore_belly_image + vore_belly_image.plane = PLANE_CH_STOMACH //This one line of code. This ONE LINE OF CODE TOOK 6 HOURS TO FIGURE OUT. THANK YOU REDCAT. + + apply_layer(VORE_BELLY_LAYER) + +/mob/living/carbon/human/proc/get_vore_belly_image() + if(!(wear_suit && wear_suit.flags_inv & HIDETAIL)) + var/vs_fullness = vore_fullness_ex["stomach"] + var/icon/vorebelly_s = new/icon(icon = 'icons/mob/vore/Bellies.dmi', icon_state = "[species.vore_belly_default_variant]Belly[vs_fullness][struggle_anim_stomach ? "" : " idle"]") + vorebelly_s.Blend(vore_sprite_color["stomach"], vore_sprite_multiply["stomach"] ? ICON_MULTIPLY : ICON_ADD) + var/image/working = image(vorebelly_s) + working.overlays += em_block_image_generic(working) + return working + return null + +/mob/living/carbon/human/proc/vore_belly_animation() + if(!struggle_anim_stomach) + struggle_anim_stomach = TRUE + update_vore_belly_sprite() + spawn(12) + struggle_anim_stomach = FALSE + update_vore_belly_sprite() + +/mob/living/carbon/human/proc/update_vore_tail_sprite() + if(QDESTROYING(src)) + return + + remove_layer(VORE_TAIL_LAYER) + + var/image/vore_tail_image = get_vore_tail_image() + if(vore_tail_image) + vore_tail_image.layer = BODY_LAYER+VORE_TAIL_LAYER + overlays_standing[VORE_TAIL_LAYER] = vore_tail_image + vore_tail_image.plane = PLANE_CH_STOMACH //This one line of code. This ONE LINE OF CODE TOOK 6 HOURS TO FIGURE OUT. THANK YOU REDCAT. + + apply_layer(VORE_TAIL_LAYER) + +/mob/living/carbon/human/proc/get_vore_tail_image() + if(tail_style && istaurtail(tail_style) && tail_style:vore_tail_sprite_variant) + var/vs_fullness = vore_fullness_ex["taur belly"] + var/loaf_alt = lying && tail_style:belly_variant_when_loaf + var/fullness_icons = min(tail_style.fullness_icons, vs_fullness) + var/icon/vorebelly_s = new/icon(icon = tail_style.bellies_icon_path, icon_state = "Taur[tail_style:vore_tail_sprite_variant]-Belly-[fullness_icons][loaf_alt ? " loaf" : (struggle_anim_taur ? "" : " idle")]") + vorebelly_s.Blend(vore_sprite_color["taur belly"], vore_sprite_multiply["taur belly"] ? ICON_MULTIPLY : ICON_ADD) + var/image/working = image(vorebelly_s) + working.pixel_x = -16 + if(tail_style.em_block) + working.overlays += em_block_image_generic(working) + return working + return null + +/mob/living/carbon/human/proc/vore_tail_animation() + if(tail_style.struggle_anim && !struggle_anim_taur) + struggle_anim_taur = TRUE + update_vore_tail_sprite() + spawn(12) + struggle_anim_taur = FALSE + update_vore_tail_sprite() + //Human Overlays Indexes///////// #undef MUTATIONS_LAYER #undef SKIN_LAYER diff --git a/code/modules/mob/mob_defines_vr.dm b/code/modules/mob/mob_defines_vr.dm index 619cfe5940..0eaed29131 100644 --- a/code/modules/mob/mob_defines_vr.dm +++ b/code/modules/mob/mob_defines_vr.dm @@ -1,5 +1,6 @@ /mob var/vantag_hud = 0 // Do I have the HUD enabled? + var/stomach_vision = 1 // By default, you will see stomachs. var/mob/temporary_form // For holding onto a temporary form var/disconnect_time = null //Time of client loss, set by Logout(), for timekeeping diff --git a/code/modules/mob/mob_helpers_vr.dm b/code/modules/mob/mob_helpers_vr.dm index 663cfc7f4a..81ae7da305 100644 --- a/code/modules/mob/mob_helpers_vr.dm +++ b/code/modules/mob/mob_helpers_vr.dm @@ -1,5 +1,13 @@ /mob/recalculate_vis() . = ..() + + if(stomach_vision && !(VIS_CH_STOMACH in vis_enabled)) + plane_holder.set_vis(VIS_CH_STOMACH,TRUE) + vis_enabled += VIS_CH_STOMACH + else if(!stomach_vision && (VIS_CH_STOMACH in vis_enabled)) + plane_holder.set_vis(VIS_CH_STOMACH,FALSE) + vis_enabled -= VIS_CH_STOMACH + if(!plane_holder || !vis_enabled) return @@ -12,3 +20,33 @@ plane_holder.set_vis(VIS_CH_VANTAG,FALSE) vis_enabled -= VIS_CH_VANTAG return + + +/mob/verb/toggle_stomach_vision() + set name = "Toggle Stomach Sprites" + set category = "Preferences" + set desc = "Toggle the ability to see stomachs or not" + + var/toggle + toggle = tgui_alert(src, "Would you like to see visible stomachs?", "Visible Tummy?", list("Yes", "No")) + if(toggle =="Yes") + stomach_vision = 1 //Simple! Easy! + if(!(VIS_CH_STOMACH in vis_enabled)) + plane_holder.set_vis(VIS_CH_STOMACH,TRUE) + vis_enabled += VIS_CH_STOMACH + to_chat("You can now see stomachs!") + else + stomach_vision = 0 + if(VIS_CH_STOMACH in vis_enabled) + plane_holder.set_vis(VIS_CH_STOMACH,FALSE) + vis_enabled -= VIS_CH_STOMACH + to_chat("You will no longer see stomachs!") + +/* //Leaving this in as an example of 'how to properly enable a plane to hide/show itself' for future PRs. +if(stomach_vision && !(VIS_CH_STOMACH in vis_enabled)) + plane_holder.set_vis(VIS_CH_STOMACH,TRUE) + vis_enabled += VIS_CH_STOMACH +else if(!stomach_vision && (VIS_CH_STOMACH in vis_enabled)) + plane_holder.set_vis(VIS_CH_STOMACH,FALSE) + vis_enabled -= VIS_CH_STOMACH +*/ diff --git a/code/modules/mob/mob_planes_vr.dm b/code/modules/mob/mob_planes_vr.dm index b23067733f..9f5b30f579 100644 --- a/code/modules/mob/mob_planes_vr.dm +++ b/code/modules/mob/mob_planes_vr.dm @@ -4,6 +4,7 @@ plane_masters[VIS_CH_HEALTH_VR] = new /obj/screen/plane_master{plane = PLANE_CH_HEALTH_VR} //Health bar but transparent at 100 plane_masters[VIS_CH_BACKUP] = new /obj/screen/plane_master{plane = PLANE_CH_BACKUP} //Backup implant status plane_masters[VIS_CH_VANTAG] = new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags + plane_masters[VIS_CH_STOMACH] = new /obj/screen/plane_master{plane = PLANE_CH_STOMACH} //Stomach plane_masters[VIS_AUGMENTED] = new /obj/screen/plane_master/augmented(M = my_mob) //Augmented reality ..() diff --git a/code/modules/mob/new_player/sprite_accessories_taur.dm b/code/modules/mob/new_player/sprite_accessories_taur.dm index 0e052d9c50..89a264c82e 100644 --- a/code/modules/mob/new_player/sprite_accessories_taur.dm +++ b/code/modules/mob/new_player/sprite_accessories_taur.dm @@ -1,3 +1,10 @@ +/datum/sprite_accessory/tail + var/vore_tail_sprite_variant = "" + var/belly_variant_when_loaf = FALSE + var/fullness_icons = 0 + var/struggle_anim = FALSE + var/bellies_icon_path = 'icons/mob/vore/Taur_Bellies.dmi' + /datum/riding/taur keytype = /obj/item/weapon/material/twohanded/riding_crop // Crack! nonhuman_key_exemption = FALSE // If true, nonhumans who can't hold keys don't need them, like borgs and simplemobs. @@ -355,4 +362,70 @@ /datum/sprite_accessory/tail/taur/zorgoia/fat name = "Zorgoia (Fat Taur)" - extra_overlay = "zorgoia_fat" \ No newline at end of file + extra_overlay = "zorgoia_fat" + + +/datum/sprite_accessory/tail/taur/wolf + vore_tail_sprite_variant = "N" + fullness_icons = 3 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/naga/naga_2c + vore_tail_sprite_variant = "Naga" + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/horse + vore_tail_sprite_variant = "Horse" + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/cow + vore_tail_sprite_variant = "Cow" + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/lizard + vore_tail_sprite_variant = "Lizard" + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/lizard/synthlizard + vore_tail_sprite_variant = "SynthLiz" + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/feline + vore_tail_sprite_variant = "Feline" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/slug + vore_tail_sprite_variant = "Slug" + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/drake + vore_tail_sprite_variant = "Drake" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/otie + vore_tail_sprite_variant = "Otie" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/deer + vore_tail_sprite_variant = "Deer" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/skunk + vore_tail_sprite_variant = "Skunk" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE diff --git a/code/modules/mob/new_player/sprite_accessories_taur_vr.dm b/code/modules/mob/new_player/sprite_accessories_taur_vr.dm index 17e716fd4e..2a85dda15f 100644 --- a/code/modules/mob/new_player/sprite_accessories_taur_vr.dm +++ b/code/modules/mob/new_player/sprite_accessories_taur_vr.dm @@ -60,6 +60,9 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 4 + vore_tail_sprite_variant = "N" + fullness_icons = 3 + struggle_anim = TRUE /datum/sprite_accessory/tail/taur/wolf/fatwolf name = "Fat Wolf (Taur)" @@ -131,6 +134,10 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 3 + vore_tail_sprite_variant = "Skunk" //Sadly there appears to be no sprites... For now! + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE /datum/sprite_accessory/tail/taur/naga name = "Naga (Taur)" @@ -165,34 +172,43 @@ msg_prey_stepunder = "You jump over %prey's thick tail." msg_owner_stepunder = "%owner bounds over your tail." -/datum/sprite_accessory/tail/taur/naga/naga_2c +/datum/sprite_accessory/tail/taur/naga/vore_compatable + name = "Naga (Taur) (Vore Compatable)" + vore_tail_sprite_variant = "Naga" + fullness_icons = 1 + struggle_anim = TRUE + +/datum/sprite_accessory/tail/taur/naga/vore_compatable/naga_2c name = "Naga dual-color (Taur)" icon_state = "naga_s" extra_overlay = "naga_markings" //icon_sprite_tag = "naga2c" + vore_tail_sprite_variant = "Naga" + fullness_icons = 1 + struggle_anim = TRUE -/datum/sprite_accessory/tail/taur/naga/alt_2c +/datum/sprite_accessory/tail/taur/naga/vore_compatable/alt_2c name = "Naga alt style dual-color (Taur)" suit_sprites = 'icons/mob/taursuits_naga_alt_vr.dmi' icon_state = "altnaga_s" extra_overlay = "altnaga_markings" //icon_sprite_tag = "altnaga2c" -/datum/sprite_accessory/tail/taur/naga/alt_3c +/datum/sprite_accessory/tail/taur/naga/vore_compatable/alt_3c name = "Naga alt style tri-color (Taur)" suit_sprites = 'icons/mob/taursuits_naga_alt_vr.dmi' icon_state = "altnaga_s" extra_overlay = "altnaga_markings" extra_overlay2 = "altnaga_stripes" -/datum/sprite_accessory/tail/taur/naga/alt_3c_rattler +/datum/sprite_accessory/tail/taur/naga/vore_compatable/alt_3c_rattler name = "Naga alt style tri-color, rattler (Taur)" suit_sprites = 'icons/mob/taursuits_naga_alt_vr.dmi' icon_state = "altnaga_s" extra_overlay = "altnaga_markings" extra_overlay2 = "altnaga_rattler" -/datum/sprite_accessory/tail/taur/naga/alt_3c_tailmaw +/datum/sprite_accessory/tail/taur/naga/vore_compatable/alt_3c_tailmaw name = "Naga alt style tri-color, tailmaw (Taur)" suit_sprites = 'icons/mob/taursuits_naga_alt_vr.dmi' icon_state = "altnagatailmaw_s" @@ -208,6 +224,9 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 4 + vore_tail_sprite_variant = "Horse" + fullness_icons = 1 + struggle_anim = TRUE msg_owner_disarm_run = "You quickly push %prey to the ground with your hoof!" msg_prey_disarm_run = "%owner pushes you down to the ground with their hoof!" @@ -242,6 +261,9 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 3 + vore_tail_sprite_variant = "Cow" + fullness_icons = 1 + struggle_anim = TRUE msg_owner_disarm_run = "You quickly push %prey to the ground with your hoof!" msg_prey_disarm_run = "%owner pushes you down to the ground with their hoof!" @@ -267,6 +289,10 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 7 + vore_tail_sprite_variant = "Deer" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE msg_owner_disarm_run = "You quickly push %prey to the ground with your hoof!" msg_prey_disarm_run = "%owner pushes you down to the ground with their hoof!" @@ -303,6 +329,9 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 5 + vore_tail_sprite_variant = "Lizard" + fullness_icons = 1 + struggle_anim = TRUE /datum/sprite_accessory/tail/taur/lizard/fatlizard name = "Fat Lizard (Taur)" @@ -349,6 +378,9 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 3 + vore_tail_sprite_variant = "SynthLiz" + fullness_icons = 1 + struggle_anim = TRUE /datum/sprite_accessory/tail/taur/lizard/fatsynthlizard name = "Fat SynthLizard dual-color (Taur)" @@ -424,6 +456,10 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 5 + vore_tail_sprite_variant = "Feline" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE /datum/sprite_accessory/tail/taur/fatfeline name = "Fat Feline (Taur)" @@ -529,6 +565,9 @@ icon_state = "slug_s" suit_sprites = 'icons/mob/taursuits_slug_vr.dmi' icon_sprite_tag = "slug" + vore_tail_sprite_variant = "Slug" + fullness_icons = 1 + struggle_anim = TRUE msg_owner_help_walk = "You carefully slither around %prey." msg_prey_help_walk = "%owner's huge tail slithers past beside you!" @@ -599,6 +638,10 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 6 + vore_tail_sprite_variant = "Drake" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE /datum/sprite_accessory/tail/taur/drake/fat name = "Fat Drake (Taur)" @@ -626,6 +669,10 @@ can_loaf = TRUE icon_loaf = 'icons/mob/vore/taurs_vr_loaf.dmi' loaf_offset = 5 + vore_tail_sprite_variant = "Otie" + belly_variant_when_loaf = TRUE + fullness_icons = 1 + struggle_anim = TRUE /datum/sprite_accessory/tail/taur/alraune/alraune_2c name = "Alraune (dual color)" @@ -1071,4 +1118,4 @@ offset_x = -32 offset_y = -11 mob_offset_y = 11 -*/ \ No newline at end of file +*/ diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index 21602a1c27..23b0796789 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -8,6 +8,12 @@ // // Parent type of all the various "belly" varieties. // + +#define DM_FLAG_VORESPRITE_TAIL 0x2 +#define DM_FLAG_VORESPRITE_MARKING 0x4 +#define DM_FLAG_VORESPRITE_ARTICLE 0x8 + + /obj/belly name = "belly" // Name of this location desc = "It's a belly! You're in it!" // Flavor text description of inside sight/sound/smells/feels. @@ -60,6 +66,30 @@ var/belly_item_mult = 1 //Multiplier for how filling items are in borg borg bellies. Items are also weighted on item size var/belly_overall_mult = 1 //Multiplier applied ontop of any other specific multipliers + + var/vore_sprite_flags = DM_FLAG_VORESPRITE_ARTICLE + var/tmp/static/list/vore_sprite_flag_list= list( + "Normal Belly Sprite" = DM_FLAG_VORESPRITE_ARTICLE, + //"Tail adjustment" = DM_FLAG_VORESPRITE_TAIL, + //"Marking addition" = DM_FLAG_VORESPRITE_MARKING + ) + var/affects_vore_sprites = FALSE + var/count_absorbed_prey_for_sprite = TRUE + var/absorbed_multiplier = 1 + var/count_liquid_for_sprite = FALSE + var/liquid_multiplier = 1 + var/count_items_for_sprite = FALSE + var/item_multiplier = 1 + var/health_impacts_size = TRUE + var/resist_triggers_animation = TRUE + var/size_factor_for_sprite = 1 + var/belly_sprite_to_affect = "stomach" + var/datum/sprite_accessory/tail/tail_to_change_to = FALSE + var/tail_colouration = FALSE + var/tail_extra_overlay = FALSE + var/tail_extra_overlay2 = FALSE + var/undergarment_chosen = "Underwear, bottom" + // Generally just used by AI var/autotransferchance = 0 // % Chance of prey being autotransferred to transfer location var/autotransferwait = 10 // Time between trying to transfer. @@ -345,6 +375,15 @@ "belly_item_mult", "belly_overall_mult", "drainmode", + "vore_sprite_flags", + "affects_vore_sprites", + "count_absorbed_prey_for_sprite", + "resist_triggers_animation", + "size_factor_for_sprite", + "belly_sprite_to_affect", + "health_impacts_size", + "count_items_for_sprite", + "item_multiplier" ) if (save_digest_mode == 1) @@ -426,6 +465,10 @@ if(M.ai_holder) M.ai_holder.handle_eaten() + if (istype(owner, /mob/living/carbon/human)) + var/mob/living/carbon/human/hum = owner + hum.update_fullness() + // Intended for simple mobs if(!owner.client && autotransferlocation && autotransferchance > 0) addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/belly, check_autotransfer), thing, autotransferlocation), autotransferwait) @@ -444,6 +487,10 @@ L.toggle_hud_vis() if((L.stat != DEAD) && L.ai_holder) L.ai_holder.go_wake() + if (istype(owner, /mob/living/carbon/human)) + var/mob/living/carbon/human/hum = owner + hum.update_fullness() + /obj/belly/proc/vore_fx(mob/living/L) if(!istype(L)) @@ -1757,6 +1804,15 @@ dupe.belly_mob_mult = belly_mob_mult dupe.belly_item_mult = belly_item_mult dupe.belly_overall_mult = belly_overall_mult + dupe.vore_sprite_flags = vore_sprite_flags + dupe.affects_vore_sprites = affects_vore_sprites + dupe.count_absorbed_prey_for_sprite = count_absorbed_prey_for_sprite + dupe.resist_triggers_animation = resist_triggers_animation + dupe.size_factor_for_sprite = size_factor_for_sprite + dupe.belly_sprite_to_affect = belly_sprite_to_affect + dupe.health_impacts_size = health_impacts_size + dupe.count_items_for_sprite = count_items_for_sprite + dupe.item_multiplier = item_multiplier //// Object-holding variables //struggle_messages_outside - strings @@ -1955,3 +2011,38 @@ /obj/belly/container_resist(mob/M) return relay_resist(M) + +/obj/belly/proc/GetFullnessFromBelly() + if(!affects_vore_sprites) + return 0 + var/belly_fullness = 0 + for(var/mob/living/M in src) + if(count_absorbed_prey_for_sprite || !M.absorbed) + var/fullness_to_add = M.size_multiplier + fullness_to_add *= M.mob_size / 20 + if(M.absorbed) + fullness_to_add *= absorbed_multiplier + if(health_impacts_size) + fullness_to_add *= M.health / M.getMaxHealth() + belly_fullness += fullness_to_add + if(count_liquid_for_sprite) + belly_fullness += (reagents.total_volume / 100) * liquid_multiplier + if(count_items_for_sprite) + for(var/obj/item/I in src) + var/fullness_to_add = 0 + if(I.w_class == ITEMSIZE_TINY) + fullness_to_add = ITEMSIZE_COST_TINY + else if(I.w_class == ITEMSIZE_SMALL) + fullness_to_add = ITEMSIZE_COST_SMALL + else if(I.w_class == ITEMSIZE_NORMAL) + fullness_to_add = ITEMSIZE_COST_NORMAL + else if(I.w_class == ITEMSIZE_LARGE) + fullness_to_add = ITEMSIZE_COST_LARGE + else if(I.w_class == ITEMSIZE_HUGE) + fullness_to_add = ITEMSIZE_COST_HUGE + else + fullness_to_add = ITEMSIZE_COST_NO_CONTAINER + fullness_to_add /= 32 + belly_fullness += fullness_to_add * item_multiplier + belly_fullness *= size_factor_for_sprite + return belly_fullness diff --git a/code/modules/vore/eating/bellymodes_datum_vr.dm b/code/modules/vore/eating/bellymodes_datum_vr.dm index b372dc2ce9..9c49d8f93f 100644 --- a/code/modules/vore/eating/bellymodes_datum_vr.dm +++ b/code/modules/vore/eating/bellymodes_datum_vr.dm @@ -35,6 +35,10 @@ GLOBAL_LIST_INIT(digest_modes, list()) else SEND_SOUND(L, sound(get_sfx("fancy_death_prey"))) B.handle_digestion_death(L) + if(!L) + if (istype(B.owner, /mob/living/carbon/human)) + var/mob/living/carbon/human/howner = B.owner + howner.update_fullness() if(!B.fancy_vore) return list("to_update" = TRUE, "soundToPlay" = sound(get_sfx("classic_death_sounds"))) return list("to_update" = TRUE, "soundToPlay" = sound(get_sfx("fancy_death_pred"))) @@ -61,6 +65,11 @@ GLOBAL_LIST_INIT(digest_modes, list()) var/offset = (1 + ((L.weight - 137) / 137)) // 130 pounds = .95 140 pounds = 1.02 var/difference = B.owner.size_multiplier / L.size_multiplier + if(B.health_impacts_size) + if (istype(B.owner, /mob/living/carbon/human)) + var/mob/living/carbon/human/howner = B.owner + howner.update_fullness() + consider_healthbar(L, old_health, B.owner) if(isrobot(B.owner)) diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index f4bf873316..91f528c8ba 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -256,6 +256,8 @@ P.weight_message_visible = src.weight_message_visible P.weight_messages = src.weight_messages + P.vore_sprite_color = istype(src, /mob/living/carbon/human) ? src:vore_sprite_color : null + var/list/serialized = list() for(var/obj/belly/B as anything in src.vore_organs) serialized += list(B.serialize()) //Can't add a list as an object to another list in Byond. Thanks. @@ -306,6 +308,10 @@ weight_message_visible = P.weight_message_visible weight_messages = P.weight_messages + + if (istype(src, /mob/living/carbon/human)) + src:vore_sprite_color = P.vore_sprite_color + if(bellies) if(isliving(src)) var/mob/living/L = src diff --git a/code/modules/vore/eating/vore_vr.dm b/code/modules/vore/eating/vore_vr.dm index 7888cdb010..d7fe76ed5a 100644 --- a/code/modules/vore/eating/vore_vr.dm +++ b/code/modules/vore/eating/vore_vr.dm @@ -69,6 +69,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE var/step_mechanics_pref = FALSE var/pickup_pref = TRUE + var/vore_sprite_color = list("stomach" = "#000", "taur belly" = "#000") + var/list/belly_prefs = list() var/vore_taste = "nothing in particular" var/vore_smell = "nothing in particular" @@ -193,6 +195,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE weight_message_visible = json_from_file["weight_message_visible"] weight_messages = json_from_file["weight_messages"] eating_privacy_global = json_from_file["eating_privacy_global"] + vore_sprite_color = json_from_file["vore_sprite_color"] //Quick sanitize if(isnull(digestable)) @@ -279,7 +282,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE else if(weight_messages.len < 10) while(weight_messages.len < 10) weight_messages.Add("") - + if(isnull(vore_sprite_color)) + vore_sprite_color = list("stomach" = "#000", "taur belly" = "#000") return TRUE /datum/vore_preferences/proc/save_vore() @@ -320,6 +324,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE "weight_message_visible" = weight_message_visible, "weight_messages" = weight_messages, "eating_privacy_global" = eating_privacy_global, + "vore_sprite_color" = vore_sprite_color, ) //List to JSON diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index bb59b7c7ad..d2286f78b5 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -227,7 +227,23 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", "belly_item_mult" = selected.belly_item_mult, "belly_overall_mult" = selected.belly_overall_mult, "drainmode" = selected.drainmode, - + "affects_voresprite" = selected.affects_vore_sprites, + "absorbed_voresprite" = selected.count_absorbed_prey_for_sprite, + "absorbed_multiplier" = selected.absorbed_multiplier, + "liquid_voresprite" = selected.count_liquid_for_sprite, + "liquid_multiplier" = selected.liquid_multiplier, + "item_voresprite" = selected.count_items_for_sprite, + "item_multiplier" = selected.item_multiplier, + "health_voresprite" = selected.health_impacts_size, + "resist_animation" = selected.resist_triggers_animation, + "voresprite_size_factor" = selected.size_factor_for_sprite, + "belly_sprite_to_affect" = selected.belly_sprite_to_affect, + "belly_sprite_option_shown" = istype(host, /mob/living/carbon/human) ? (LAZYLEN(host:vore_icon_bellies) >= 1 ? TRUE : FALSE) : FALSE, // TODO: FIX THIS (It won't be fixed) + "tail_option_shown" = istype(host, /mob/living/carbon/human), + "tail_to_change_to" = selected.tail_to_change_to, + "tail_colouration" = selected.tail_colouration, + "tail_extra_overlay" = selected.tail_extra_overlay, + "tail_extra_overlay2" = selected.tail_extra_overlay2 ) var/list/addons = list() @@ -236,6 +252,13 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", addons.Add(flag_name) selected_list["addons"] = addons + var/list/vs_flags = list() + for(var/flag_name in selected.vore_sprite_flag_list) + if(selected.vore_sprite_flags & selected.vore_sprite_flag_list[flag_name]) + vs_flags.Add(flag_name) + selected_list["vore_sprite_flags"] = vs_flags + + selected_list["egg_type"] = selected.egg_type selected_list["contaminates"] = selected.contaminates selected_list["contaminate_flavor"] = null @@ -609,6 +632,20 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", host.weight_message_visible = !host.weight_message_visible unsaved_changes = TRUE return TRUE + if("set_vs_color") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/belly_choice = tgui_input_list(usr, "Which vore sprite are you going to edit the color of?", "Vore Sprite Color", hhost.vore_icon_bellies) + var/newcolor = input(usr, "Choose a color.", "", hhost.vore_sprite_color[belly_choice]) as color|null + if(newcolor) + hhost.vore_sprite_color[belly_choice] = newcolor + var/multiply = tgui_input_list(usr, "Set the color to be applied multiplicatively or additively? Currently in [hhost.vore_sprite_multiply[belly_choice] ? "Multiply" : "Add"]", "Vore Sprite Color", list("Multiply", "Add")) + if(multiply == "Multiply") + hhost.vore_sprite_multiply[belly_choice] = TRUE + else if(multiply == "Add") + hhost.vore_sprite_multiply[belly_choice] = FALSE + hhost.update_icons_body() + return TRUE /datum/vore_look/proc/pick_from_inside(mob/user, params) var/atom/movable/target = locate(params["pick"]) @@ -1680,6 +1717,98 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", qdel(host.vore_selected) host.vore_selected = host.vore_organs[1] . = TRUE - + if("b_belly_sprite_to_affect") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/belly_choice = tgui_input_list(usr, "Which belly sprite do you want your [lowertext(hhost.vore_selected.name)] to affect?","Select Region", hhost.vore_icon_bellies) + if(!belly_choice) //They cancelled, no changes + return FALSE + else + hhost.vore_selected.belly_sprite_to_affect = belly_choice + hhost.update_fullness() + . = TRUE + if("b_affects_vore_sprites") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + hhost.vore_selected.affects_vore_sprites = !hhost.vore_selected.affects_vore_sprites + hhost.update_fullness() + . = TRUE + if("b_count_absorbed_prey_for_sprites") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + hhost.vore_selected.count_absorbed_prey_for_sprite = !hhost.vore_selected.count_absorbed_prey_for_sprite + hhost.update_fullness() + . = TRUE + if("b_absorbed_multiplier") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/absorbed_multiplier_input = input(user, "Set the impact absorbed prey's size have on your vore sprite. 1 means no scaling, 0.5 means absorbed prey count half as much, 2 means absorbed prey count double. (Range from 0.1 - 3)", "Absorbed Multiplier") as num|null + if(!isnull(absorbed_multiplier_input)) + hhost.vore_selected.absorbed_multiplier = CLAMP(absorbed_multiplier_input, 0.1, 3) + hhost.update_fullness() + . = TRUE + if("b_count_items_for_sprites") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + hhost.vore_selected.count_items_for_sprite = !hhost.vore_selected.count_items_for_sprite + hhost.update_fullness() + . = TRUE + if("b_item_multiplier") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/item_multiplier_input = input(user, "Set the impact items will have on your vore sprite. 1 means a belly with 8 normal-sized items will count as 1 normal sized prey-thing's worth, 0.5 means items count half as much, 2 means items count double. (Range from 0.1 - 10)", "Item Multiplier") as num|null + if(!isnull(item_multiplier_input)) + hhost.vore_selected.item_multiplier = CLAMP(item_multiplier_input, 0.1, 10) + hhost.update_fullness() + . = TRUE + if("b_health_impacts_size") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + hhost.vore_selected.health_impacts_size = !hhost.vore_selected.health_impacts_size + hhost.update_fullness() + . = TRUE + if("b_resist_animation") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + hhost.vore_selected.resist_triggers_animation = !hhost.vore_selected.resist_triggers_animation + . = TRUE + if("b_size_factor_sprites") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/size_factor_input = input(user, "Set the impact all belly content's collective size has on your vore sprite. 1 means no scaling, 0.5 means content counts half as much, 2 means contents count double. (Range from 0.1 - 3)", "Size Factor") as num|null + if(!isnull(size_factor_input)) + hhost.vore_selected.size_factor_for_sprite = CLAMP(size_factor_input, 0.1, 3) + hhost.update_fullness() + . = TRUE + if("b_tail_to_change_to") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/tail_choice = tgui_input_list(usr, "Which tail sprite do you want to use when your [lowertext(host.vore_selected.name)] is filled?","Select Sprite", global.tail_styles_list) + if(!tail_choice) //They cancelled, no changes + return FALSE + else + hhost.vore_selected.tail_to_change_to = tail_choice + . = TRUE + if("b_tail_color") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/newcolor = input(usr, "Choose tail color.", "", hhost.vore_selected.tail_colouration) as color|null + if(newcolor) + hhost.vore_selected.tail_colouration = newcolor + . = TRUE + if("b_tail_color2") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/newcolor = input(usr, "Choose tail secondary color.", "", hhost.vore_selected.tail_extra_overlay) as color|null + if(newcolor) + hhost.vore_selected.tail_extra_overlay = newcolor + . = TRUE + if("b_tail_color3") + if (istype(host, /mob/living/carbon/human)) + var/mob/living/carbon/human/hhost = host + var/newcolor = input(usr, "Choose tail tertiary color.", "", hhost.vore_selected.tail_extra_overlay2) as color|null + if(newcolor) + hhost.vore_selected.tail_extra_overlay2 = newcolor + . = TRUE if(.) unsaved_changes = TRUE diff --git a/icons/mob/vore/Bellies.dmi b/icons/mob/vore/Bellies.dmi new file mode 100644 index 0000000000000000000000000000000000000000..4f0d94f00836ba86149aaba1916281704e96b8e3 GIT binary patch literal 7013 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 L;ZLHK*X{oSaG$ZM literal 0 HcmV?d00001 diff --git a/icons/mob/vore/Taur_Bellies.dmi b/icons/mob/vore/Taur_Bellies.dmi new file mode 100644 index 0000000000000000000000000000000000000000..e606c64d183eea8952e2612736cbe3562823ea69 GIT binary patch literal 33603 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 literal 0 HcmV?d00001 diff --git a/tgui/packages/tgui/interfaces/VorePanel.jsx b/tgui/packages/tgui/interfaces/VorePanel.jsx index 5a5236545c..0de645c5f7 100644 --- a/tgui/packages/tgui/interfaces/VorePanel.jsx +++ b/tgui/packages/tgui/interfaces/VorePanel.jsx @@ -1369,10 +1369,192 @@ const VoreSelectedBellyVisuals = (props) => { belly_fullscreen_color_trinary, mapRef, colorization_enabled, + vore_sprite_flags, + affects_voresprite, + absorbed_voresprite, + absorbed_multiplier, + item_voresprite, + item_multiplier, + health_voresprite, + resist_animation, + voresprite_size_factor, + belly_sprite_option_shown, + belly_sprite_to_affect, + undergarment_chosen, + undergarment_if_none, + undergarment_color, + tail_option_shown, + tail_to_change_to, + tail_colouration, + tail_extra_overlay, + tail_extra_overlay2, } = belly; return ( <> +
+ + + +
{ + +