diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index cac02b26ca..1771b1b146 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -164,9 +164,9 @@ //Determines if there's directionals. if(render_icon && curdir != SOUTH) if ( - !length(icon_states(icon(curicon, curstate, NORTH))) \ - && !length(icon_states(icon(curicon, curstate, EAST))) \ - && !length(icon_states(icon(curicon, curstate, WEST))) \ + !length(icon_states_fast(icon(curicon, curstate, NORTH))) \ + && !length(icon_states_fast(icon(curicon, curstate, EAST))) \ + && !length(icon_states_fast(icon(curicon, curstate, WEST))) \ ) base_icon_dir = SOUTH diff --git a/code/_helpers/icons/flatten.dm b/code/_helpers/icons/flatten.dm index 36bd29d628..b70e0f2cc9 100644 --- a/code/_helpers/icons/flatten.dm +++ b/code/_helpers/icons/flatten.dm @@ -72,7 +72,7 @@ var/state = A.icon_state var/none = !icon if(!none) - var/list/states = cached_icon_states(icon) + var/list/states = icon_states_fast(icon) if(!(state in states)) if(!("" in states)) none = TRUE @@ -89,11 +89,11 @@ dir = A.dir var/ourdir = dir if(!none && ourdir != SOUTH) - if(length(icon_states(icon(icon, state, NORTH)))) + if(length(icon_states_fast(icon(icon, state, NORTH)))) pass() - else if(length(icon_states(icon(icon, state, EAST)))) + else if(length(icon_states_fast(icon(icon, state, EAST)))) pass() - else if(length(icon_states(icon(icon, state, WEST)))) + else if(length(icon_states_fast(icon(icon, state, WEST)))) pass() else ourdir = SOUTH diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 8bb66f8bd4..8f32c413f1 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -139,7 +139,7 @@ else return "unknown" /proc/RoundHealth(health) - var/list/icon_states = cached_icon_states(GLOB.ingame_hud_med) + var/list/icon_states = icon_states_fast(GLOB.ingame_hud_med) for(var/icon_state in icon_states) if(health >= text2num(icon_state)) return icon_state diff --git a/code/controllers/subsystems/plants.dm b/code/controllers/subsystems/plants.dm index 01bb6505cd..653991e48c 100644 --- a/code/controllers/subsystems/plants.dm +++ b/code/controllers/subsystems/plants.dm @@ -38,7 +38,7 @@ SUBSYSTEM_DEF(plants) // Looks like shit but it's sort of necessary. /datum/controller/subsystem/plants/proc/setup() // Build the icon lists. - for(var/icostate in cached_icon_states('icons/obj/hydroponics_growing.dmi')) + for(var/icostate in icon_states_fast('icons/obj/hydroponics_growing.dmi')) var/split = findtext(icostate,"-") if(!split) // invalid icon_state @@ -56,7 +56,7 @@ SUBSYSTEM_DEF(plants) if(!(base in GLOB.forbidden_plant_growth_sprites)) accessible_plant_sprites[base] = ikey - for(var/icostate in cached_icon_states('icons/obj/hydroponics_products.dmi')) + for(var/icostate in icon_states_fast('icons/obj/hydroponics_products.dmi')) var/split = findtext(icostate,"-") var/base = copytext(icostate,1,split) if(split) diff --git a/code/controllers/subsystems/robot_sprites.dm b/code/controllers/subsystems/robot_sprites.dm index 4477d86170..d2c12dd015 100644 --- a/code/controllers/subsystems/robot_sprites.dm +++ b/code/controllers/subsystems/robot_sprites.dm @@ -139,7 +139,7 @@ SUBSYSTEM_DEF(robot_sprites) RS.icon_x = text2num(splitted[1]) RS.icon_y = text2num(splitted[2]) RS.vis_height = text2num(splitted[2]) - var/list/icon_states = cached_icon_states(RS.sprite_icon) + var/list/icon_states = icon_states_fast(RS.sprite_icon) for(var/icon in icon_states) // testing whitelist functionality ckey-... if(findtext(icon, regex("ckey-"))) diff --git a/code/game/objects/items/magazine.dm b/code/game/objects/items/magazine.dm index 6da89532e5..bf8ba8264f 100644 --- a/code/game/objects/items/magazine.dm +++ b/code/game/objects/items/magazine.dm @@ -75,7 +75,7 @@ pixel_x = 5-rand(10) pixel_x = 5-rand(10) - icon_state = pick(cached_icon_states('icons/obj/magazine.dmi')) + icon_state = pick(icon_states_fast('icons/obj/magazine.dmi')) headline = pick(tabloid_headlines) name = pick(tabloid_publishers) diff --git a/code/game/objects/structures/barsign.dm b/code/game/objects/structures/barsign.dm index 85d49c59ca..619ee10d3c 100644 --- a/code/game/objects/structures/barsign.dm +++ b/code/game/objects/structures/barsign.dm @@ -8,7 +8,7 @@ var/cult = 0 /obj/structure/sign/double/barsign/proc/get_valid_states(initial=1) - . = cached_icon_states(icon) + . = icon_states_fast(icon) . -= "On" . -= "Nar-sie Bistro" . -= "Empty" diff --git a/code/modules/asset_cache/asset_list.dm b/code/modules/asset_cache/asset_list.dm index 9059a57cdb..c06123c664 100644 --- a/code/modules/asset_cache/asset_list.dm +++ b/code/modules/asset_cache/asset_list.dm @@ -440,7 +440,7 @@ GLOBAL_LIST_EMPTY(asset_datums) /datum/asset/spritesheet/proc/queuedInsert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE) I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving) - if(!I || !length(cached_icon_states(I))) // that direction or state doesn't exist + if(!I || !length(icon_states_fast(I))) // that direction or state doesn't exist return var/size_id = "[I.Width()]x[I.Height()]" var/size = sizes[size_id] @@ -476,7 +476,7 @@ GLOBAL_LIST_EMPTY(asset_datums) if(!directions) directions = list(SOUTH) - for(var/icon_state_name in cached_icon_states(I)) + for(var/icon_state_name in icon_states_fast(I)) for(var/direction in directions) var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]-" : "" Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction) @@ -558,7 +558,7 @@ GLOBAL_LIST_EMPTY(asset_datums) var/generic_icon_names = FALSE //generate icon filenames using generate_asset_name() instead the above format /datum/asset/simple/icon_states/register(_icon = icon) - for(var/icon_state_name in icon_states(_icon)) + for(var/icon_state_name in icon_states_fast(_icon)) for(var/direction in directions) var/asset = icon(_icon, icon_state_name, direction, frame, movement_states) if(!asset) diff --git a/code/modules/asset_cache/assets/belly_assets.dm b/code/modules/asset_cache/assets/belly_assets.dm index 98caf9da06..3dde341158 100644 --- a/code/modules/asset_cache/assets/belly_assets.dm +++ b/code/modules/asset_cache/assets/belly_assets.dm @@ -1,3 +1,10 @@ +/datum/overlay_previews + var/old_precolored = 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi' + var/base = 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_base.dmi' + var/layer1 = 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer1.dmi' + var/layer2 = 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer2.dmi' + var/layer3 = 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer3.dmi' + /datum/belly_overlays var/belly_icon /* @@ -273,13 +280,3 @@ /datum/belly_overlays/synth_flesh_mono_hole belly_icon = 'icons/mob/vore_fullscreens/synth_flesh_mono_hole.dmi' - -/datum/belly_overlays/yet_another_tumby - belly_icon = 'icons/mob/vore_fullscreens/yet_another_tumby.dmi' - -//Compatibility assets due to renames... -/datum/belly_overlays/anim_belly - belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly1.dmi' - -/datum/belly_overlays/a_anim_belly - belly_icon = 'icons/mob/vore_fullscreens/VBOanim_belly1.dmi' diff --git a/code/modules/asset_cache/assets/research_designs.dm b/code/modules/asset_cache/assets/research_designs.dm index fd1bf1db9f..dcb8d7d0df 100644 --- a/code/modules/asset_cache/assets/research_designs.dm +++ b/code/modules/asset_cache/assets/research_designs.dm @@ -58,7 +58,7 @@ var/obj/machinery/computer/C = item var/screen = initial(C.icon_screen) var/keyboard = initial(C.icon_keyboard) - var/all_states = cached_icon_states(icon_file) + var/all_states = icon_states_fast(icon_file) if (screen && (screen in all_states)) transform.blend_icon(uni_icon(icon_file, screen), ICON_OVERLAY) if (keyboard && (keyboard in all_states)) diff --git a/code/modules/asset_cache/assets/spritesheets/vending.dm b/code/modules/asset_cache/assets/spritesheets/vending.dm index b8ad946d82..833acac7b3 100644 --- a/code/modules/asset_cache/assets/spritesheets/vending.dm +++ b/code/modules/asset_cache/assets/spritesheets/vending.dm @@ -22,7 +22,7 @@ var/datum/universal_icon/I - var/icon_states_list = cached_icon_states(icon_file) + var/icon_states_list = icon_states_fast(icon_file) if(icon_state in icon_states_list) I = uni_icon(icon_file, icon_state, SOUTH) var/c = initial(item.color) diff --git a/code/modules/asset_cache/assets/spritesheets/vore.dm b/code/modules/asset_cache/assets/spritesheets/vore.dm deleted file mode 100644 index 4881e0ede6..0000000000 --- a/code/modules/asset_cache/assets/spritesheets/vore.dm +++ /dev/null @@ -1,15 +0,0 @@ -/datum/asset/spritesheet/vore - name = "vore" - -/datum/asset/spritesheet/vore/create_spritesheets() - var/icon/downscaled = icon('icons/mob/screen_full_vore_list.dmi') // preserving save data - downscaled.Scale(240, 240) - InsertAll("", downscaled) - -/datum/asset/spritesheet/vore_fixed //This should be getting loaded in the TGUI vore panel but the game refuses to do so, for some reason. It only loads the vore spritesheet. - name = "fixedvore" - -/datum/asset/spritesheet/vore_fixed/create_spritesheets() // preserving save data - var/icon/downscaledVF = icon('icons/mob/screen_full_vore.dmi') - downscaledVF.Scale(240, 240) - InsertAll("", downscaledVF) diff --git a/code/modules/asset_cache/iconforge/batched_spritesheet.dm b/code/modules/asset_cache/iconforge/batched_spritesheet.dm index 58d815b782..0c3ca784be 100644 --- a/code/modules/asset_cache/iconforge/batched_spritesheet.dm +++ b/code/modules/asset_cache/iconforge/batched_spritesheet.dm @@ -158,7 +158,7 @@ if (!directions) directions = list(SOUTH) - for (var/icon_state_name in icon_states(I)) + for (var/icon_state_name in icon_states_fast(I)) for (var/direction in directions) var/prefix2 = (directions.len > 1 && prefix_with_dirs) ? "[dir2text(direction)]-" : "" insert_icon("[prefix][prefix2][icon_state_name]", uni_icon(I, icon_state_name, direction)) diff --git a/code/modules/asset_cache/iconforge/universal_icon.dm b/code/modules/asset_cache/iconforge/universal_icon.dm index 344e92b6f4..7eb73f0ad9 100644 --- a/code/modules/asset_cache/iconforge/universal_icon.dm +++ b/code/modules/asset_cache/iconforge/universal_icon.dm @@ -487,7 +487,7 @@ var/dir_count = state_data["dirs"] if(dir_count == 1) base_icon_dir = SOUTH - else if(!length(icon_states(icon(curicon, curstate, NORTH)))) + else if(!length(icon_states_fast(icon(curicon, curstate, NORTH)))) base_icon_dir = SOUTH var/list/icon_dimensions = get_icon_dimensions(curicon) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 2b6d28d2d7..23f74aabf4 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -1395,7 +1395,7 @@ // only override icon if a corresponding digitigrade replacement icon_state exists // otherwise, keep the old non-digi icon_define (or nothing) - if(icon_state && cached_icon_states(update_icon_define_digi):Find(icon_state)) //Unsure what to do to this seeing as it does :Find() + if(icon_state && icon_states_fast(update_icon_define_digi):Find(icon_state)) //Unsure what to do to this seeing as it does :Find() update_icon_define = update_icon_define_digi diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index b18a661ceb..b613eca4b2 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -78,7 +78,7 @@ var/list/new_item_icons = list() var/list/new_item_state_slots = list() - var/list/available_states = cached_icon_states(CUSTOM_ITEM_MOB) + var/list/available_states = icon_states_fast(CUSTOM_ITEM_MOB) //If l_hand or r_hand are not present, preserve them using item_icons/item_state_slots //Then use icon_override to make every other slot use the custom sprites by default. diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/carp.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/carp.dm index 1fae3c1e99..f21bd88114 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/space/carp.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/carp.dm @@ -160,7 +160,7 @@ B.digest_brute = 0.5 B.digest_burn = 0.5 B.escapechance = 20 - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" B.belly_fullscreen_color = "#660021" B.belly_fullscreen_color2 = "#660021" B.fancy_vore = 1 diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/turkeygirl.dm b/code/modules/mob/living/simple_mob/subtypes/animal/turkeygirl.dm index 1951876b2c..2f8c56893e 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/turkeygirl.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/turkeygirl.dm @@ -49,7 +49,7 @@ B.name = "stomach" B.desc = "The hot churning stomach of a turkey girl! The doughy flesh presses inward to form to your figure, thick slime coating everything, and very shortly that includes you as well! There isn't any escaping that constant full body motion, as her body works to ball yours up into a tight little package. Gurgling and glubbing with every shifting movement, while her pulse throbs through the flesh all around you with every beat of her heart. All in all, one thing is for certain! You've become turkey stuffing! Oh no..." B.mode_flags = DM_FLAG_THICKBELLY | DM_FLAG_NUMBING - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" B.digest_brute = 1 B.digest_burn = 6 B.digestchance = 0 diff --git a/code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm b/code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm index a069896ca4..b44276c985 100644 --- a/code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm +++ b/code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm @@ -47,7 +47,7 @@ B.name = "tail" B.desc = "The small critter seems to suddenly panic, lunging at you with its massive fluffy tail, using it like a weapon. Despite the appearance of the tail, it seems to be much larger on the inside, suddenly engulfing you completely in a world of endless softness. Inside, you are bound up nice and tight in an oddly comfortable prison of hair, it ripples over your body tickling every bit of exposed body on offer." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 1 B.digest_burn = 1 B.digest_oxy = 0 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/bat.dm b/code/modules/mob/living/simple_mob/subtypes/vore/bat.dm index 7066944a30..6bc7b94543 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/bat.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/bat.dm @@ -48,7 +48,7 @@ B.name = "stomach" B.desc = "The giant bat has managed to swallow you alive, which is particularly impressive given that it's still a rather small creature. It's belly bulges out as you're squeezed into the oppressively tight stomach, and it lands to manage the weight, wings curling over your form beneath. The body groans under your strain, burbling and growling as it gets to work on it's feed. However, at least for now, it seems to do you no physical harm. Instead, the damp walls that squelch across your body try to leech out your energy through some less direct means." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 2 B.digest_burn = 2 B.digest_oxy = 1 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm b/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm index a1f343133f..700bb2596f 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm @@ -660,7 +660,7 @@ I think I covered everything. mode_flags = DM_FLAG_NUMBING struggle_messages_inside = list( "Deciding that you've stayed long enough, you wriggle and writhe, stretching yourself out in the chamber, trying to thrust your hands and face up the way you entered. The beast stirs, and this churny pocket of flesh providing you safety clenches hard, aiding your entry back up into the lowermost depths of it's gullet. rhythmic clenches continue to invite you back down, however, should you reconsider.") - belly_fullscreen = "anim_belly" + belly_fullscreen = "VBOanim_belly1" /// /// AI handling stuff diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm index a3cc2e06b6..90003acea1 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm @@ -380,7 +380,7 @@ B.release_sound = "Pred Escape" B.fancy_vore = 1 B.belly_fullscreen_color = "#380000" - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" B.name = "fuel processor" B.desc = "Uttering distorted growls and fragmented voice clips all the while, the corrupted hound gulps the rest of your squirming figure past its jaws... which snap shut with an audible click of metal on metal. Your trip down its slickly lubricated, rubbery gullet is a tight and efficient one... and once you spill out into the machine's fuel processor, your weight making it sag slightly, hot-and-thick slime begins oozing all over your form. Only time will tell if you're destined to become fuel for its next bout of rampaging... be it days, hours, or just mere minutes..." diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm b/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm index a6a5f7b02b..c3008785e5 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm @@ -76,7 +76,7 @@ B.release_sound = "Pred Escape" B.fancy_vore = TRUE B.belly_fullscreen_color = "#c47cb4" - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" /datum/say_list/fennec speak = list("SKREEEE!","Chrp?","Ararrrararr.") diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm b/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm index 2f15a13fb2..f246ff93f0 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm @@ -131,7 +131,7 @@ B.contamination_color = "grey" B.contamination_flavor = "Wet" B.belly_fullscreen_color = "#c47cb4" - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" B.emote_lists[DM_HOLD] = list( "The wolf's idle wandering helps its stomach gently churn around you, slimily squelching against your figure.", diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm b/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm index 2a8dce738d..f0231ad6f9 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm @@ -95,7 +95,7 @@ B.contamination_color = "grey" B.contamination_flavor = "Wet" B.belly_fullscreen_color = "#c47cb4" - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" B.emote_lists[DM_HEAL] = list( "The drake's idle movement helps its stomach gently churn around you, slimily squelching against your figure.", "The draconic predator takes a moment to intentionally clench its gut around you, encapsulating you in a strange, fleshy hug.", @@ -192,7 +192,7 @@ B.contamination_flavor = "Wet" B.belly_fullscreen_color = "#df3dbc" B.belly_fullscreen_alpha = 240 - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" B.emote_lists[DM_HEAL] = list( "The drake's idle movement helps its stomach gently churn around you, slimily squelching against your figure.", "The draconic predator takes a moment to intentionally clench its gut around you, encapsulating you in a strange, fleshy hug.", diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/meowl.dm b/code/modules/mob/living/simple_mob/subtypes/vore/meowl.dm index bc261b2e54..dc01cc3c1e 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/meowl.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/meowl.dm @@ -44,7 +44,7 @@ B.name = "stomach" B.desc = "The strange critter suddenly takes advantage of you being alone to pounce atop you and quickly engulf your head within its maw! Before you even have a chance to react, the world goes dark with the inside of the meowls mouth covering your face, a rough tounge lapping smearing wet hot slobber over you. The rest of the process is pretty quick as the cat-owl begins to gulp your head down through a surprisingly stretchy throat and along the tight, flexing tunnel of its gullet. Before long you are pushing face first into the creature's stomach, the wrinkled walls quickly beginning grind slick flesh across it like any other piece of food. The rest of your body soon follows into the increasingly tight space, forced to curl up over yourself as the stomach lining bears down on you from every angle. At first, the stomach itself seems rather inactive, happily just squeezing and massaging you as the meowl settles down to slowly enjoy their snack. Though, struggling might risk setting off the gut one way or another..." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 1 B.digest_burn = 1 B.digest_oxy = 1 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/peasant.dm b/code/modules/mob/living/simple_mob/subtypes/vore/peasant.dm index 12b3a4f910..7a1366528b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/peasant.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/peasant.dm @@ -60,7 +60,7 @@ B.name = "stomach" B.desc = "You've somehow managed to get yourself eaten by one of the local peasants. After jamming you down into their stomach, you find yourself cramped up tight in a space that clearly shouldn't be able to accept you. They let out a relieved sigh as they heft around their new found weight, giving it a hearty pat, clearly content to get a good meal for once. The world around you groans and grumbles, but the gut is far from harmful to you right now, even as the walls clench down on your body." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 1 B.digest_burn = 1 B.digest_oxy = 0 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/rabbit.dm b/code/modules/mob/living/simple_mob/subtypes/vore/rabbit.dm index 3e56ed14b8..1f0f21381b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/rabbit.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/rabbit.dm @@ -103,7 +103,7 @@ B.release_sound = "Pred Escape" B.fancy_vore = TRUE B.belly_fullscreen_color = "#b15aac" - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" /datum/say_list/rabbit speak = list("chrrrs.") diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm index 022e81c8f9..8caf0a08b7 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm @@ -82,7 +82,7 @@ B.release_sound = "Pred Escape" B.fancy_vore = TRUE B.belly_fullscreen_color = "#c47cb4" - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" B.emote_lists[DM_HOLD] = list( "As time passes, the massive rat's stomach slowly churns and squeezes down around you, packing you into an easier to carry bundle amidst that oddly soothing massage.", diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm b/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm index 624cf2a554..52fb4ae649 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm @@ -102,7 +102,7 @@ B.vore_sound = "Tauric Swallow" B.release_sound = "Pred Escape" B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "a_anim_belly" + B.belly_fullscreen = "VBOanim_belly1" B.fancy_vore = 1 B.selective_preference = DM_SELECT B.vore_verb = "devour" diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/scrubble.dm b/code/modules/mob/living/simple_mob/subtypes/vore/scrubble.dm index 4781af84f2..8c5cb5015f 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/scrubble.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/scrubble.dm @@ -46,7 +46,7 @@ B.name = "stomach" B.desc = "Despite the small size of the scrubble, it seems to have a lot of energy behind it. The critter dives atop you in a panic, its maw quickly engulfing your head as its paws flail scrabble against you, hot slobber slathering across your tightly trapped face. It takes a little repositioning to get itself in the right position, but soon the creature is gulping its way down your entire body. Somehow it manages to squeeze you completely into a gut that should rightly be far too small for anything but a mouse, bundling up your body into a tight ball as the walls around you clench in tightly to keep you nice and compact. The sounds of burbling and glorping echo through the intensely tight space as the stomach lining grinds in thick oozes against your skin, pressure so high that you can barely move a muscle." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 1 B.digest_burn = 1 B.digest_oxy = 0 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/sonadile.dm b/code/modules/mob/living/simple_mob/subtypes/vore/sonadile.dm index db2a7dfb78..34a8fd4ff1 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/sonadile.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/sonadile.dm @@ -49,7 +49,7 @@ B.name = "stomach" B.desc = "The creature's huge maw drops down over your body, the long neck preventing it from barely having to shift its torso at all. The jaws quickly travel down you, slathering you in a drool as you're quickly stuffed through the flexible muscle of the throat. In a matter of seconds you are effortlessly lifted from the ground, your entire figure now reduced to a bulge within the neck of the beast, your feet soon vanishing into its mouth with a visceral gulp. The journey down is a long and slow one, the gullet squeezing you steadily along with heavy rippling contractions, the sonadile is quite content that you're heading in the right direction. With every inch, the world around you grows louder with the sound of a heartbeat and the gutteral grumbles of your upcoming destination. Before long you are squeezed down through a tight fleshy valve and deposited in the stomach of the reptile, walls immediately bearing down on you from every direction to ensure that you're tightly confined with little room to move. Hot, humid and slick with all manner of thick and thin liquids, this place isn't treating you any different from whatever else this animal likes to eat." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 2 B.digest_burn = 2 B.digest_oxy = 1 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/stalker.dm b/code/modules/mob/living/simple_mob/subtypes/vore/stalker.dm index 7c135298b0..f82c216391 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/stalker.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/stalker.dm @@ -49,7 +49,7 @@ B.name = "stomach" B.desc = "The lithe creature spends only minimal time with you pinned beneath it, before it's jaws stretch wide ahead of your face. The slightly blue hued interior squelches tightly over your head as the stalker's teeth prod against you, threatening to become much more of a danger if you put up too much of a fight. However, the process is quick, your body is efficiently squeezed through that tight gullet, contractions dragging you effortlessly towards the creature's gut. The stomach swells and hangs beneath the animal, swaying like a hammock under the newfound weight. The walls wrap incredibly tightly around you, compressing you tightly into a small ball as it grinds caustic juices over you." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 2 B.digest_burn = 2 B.digest_oxy = 1 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/succubi.dm b/code/modules/mob/living/simple_mob/subtypes/vore/succubi.dm index ea377c560a..bbf3119566 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/succubi.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/succubi.dm @@ -78,7 +78,7 @@ GLOBAL_LIST_INIT(succubus_safewords, list( B.name = "stomach" B.desc = "You find yourself tightly compressed into the stomach of the succubus, with immense pressure squeezing down on you from every direction. The wrinkled walls of the gut knead over you, like a swelteringly hot, wet massage. You can feel movement from the outside, as though the demoness is running her hands over your form with delight. The world around you groans and gurgles, but the fluids that ooze into this place don't seem harmful, yet. Instead, you feel your very energy being steadily depleted, much to the joy of the woman who's claiming it all for herself." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 2 B.digest_burn = 2 B.digest_oxy = 1 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vampire.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vampire.dm index 301f7c653c..e6b846ab19 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/vampire.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/vampire.dm @@ -60,7 +60,7 @@ B.name = "stomach" B.desc = "Having been rapidly gulped up by the vampire, you find yourself tightly contained with a set of groaning, wrinkled walls. It seems that the beast has decided against draining your lifeforce through you blood, and instead taking a more direct approach as it saps your strength from all around you. Your attacker seems content to just take that essence for now, but it is a gut afterall and struggling may set it off." B.mode_flags = DM_FLAG_THICKBELLY - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.digest_brute = 3 B.digest_burn = 0 B.digest_oxy = 1 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vore_hostile.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vore_hostile.dm index 091e59cad8..6075b9cee5 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/vore_hostile.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/vore_hostile.dm @@ -308,7 +308,7 @@ B.name = "interior" B.desc = "An incredibly thick oozing slime surrounds you, filling in all the space around your form! It's hard to catch a breath here as the jiggling gel that makes up the body of the creature swiftly fills in the hole you made in its surface by entering. The gel is semi-transparent, and you can see your surroundings though its surface, and similarly you can be seen floating in the gel from the outside. When the cube moves, your whole body is wobbled along with it. There are clouds of still processing material floating all around you as the corrosive substance works on breaking everything down." B.mode_flags = DM_FLAG_NUMBING - B.belly_fullscreen = "yet_another_tumby" + B.belly_fullscreen = "VBO_fleshs" B.colorization_enabled = TRUE B.belly_fullscreen_color = color B.digest_brute = 2 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm b/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm index 6d4982a8e9..237142e2aa 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm @@ -51,7 +51,7 @@ B.release_sound = "Pred Escape" B.fancy_vore = 1 B.belly_fullscreen_color = "#c47cb4" - B.belly_fullscreen = "anim_belly" + B.belly_fullscreen = "VBOanim_belly1" // Space edition, stronger and bitier /mob/living/simple_mob/vore/wolf/space diff --git a/code/modules/persistence/graffiti.dm b/code/modules/persistence/graffiti.dm index 83c611feaf..9e869b908b 100644 --- a/code/modules/persistence/graffiti.dm +++ b/code/modules/persistence/graffiti.dm @@ -25,7 +25,7 @@ author = _author /obj/effect/decal/writing/Initialize(mapload) - var/list/random_icon_states = cached_icon_states(icon) + var/list/random_icon_states = icon_states_fast(icon) for(var/obj/effect/decal/writing/writing in loc) random_icon_states.Remove(writing.icon_state) if(length(random_icon_states)) diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index 6f53cd3269..3439342c74 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -235,7 +235,7 @@ GLOBAL_LIST_EMPTY(magazine_icondata_states) /proc/magazine_icondata_cache_add(var/obj/item/ammo_magazine/M) var/list/icon_keys = list() var/list/ammo_states = list() - var/list/states = cached_icon_states(M.icon) + var/list/states = icon_states_fast(M.icon) for(var/i = 0, i <= M.max_ammo, i++) var/ammo_state = "[M.icon_state]-[i]" if(ammo_state in states) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index e59dc27021..0fb8f6fb54 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -105,7 +105,6 @@ #include "map_tests.dm" #include "mapping.dm" #include "material_tests.dm" -#include "mob_vbo_test.dm" // #include "nuke_cinematic.dm" // TODO: This is probably fixed later on #include "poster_tests.dm" // #include "preferences.dm" // This unit test is missing some other stuff @@ -121,7 +120,8 @@ #include "timer_sanity.dm" #include "trait_tests.dm" #include "unit_test.dm" -// #include "vore_tests.dm" // FIXME: REWRITE OR FIX THIS +#include "vbo_tests.dm" +#include "vore_tests.dm" // END_INCLUDE #ifdef REFERENCE_TRACKING_DEBUG //Don't try and parse this file if ref tracking isn't turned on. IE: don't parse ref tracking please mr linter #include "find_reference_sanity.dm" diff --git a/code/modules/unit_tests/mob_vbo_test.dm b/code/modules/unit_tests/vbo_tests.dm similarity index 61% rename from code/modules/unit_tests/mob_vbo_test.dm rename to code/modules/unit_tests/vbo_tests.dm index 7c1908c66c..c767b5b7c7 100644 --- a/code/modules/unit_tests/mob_vbo_test.dm +++ b/code/modules/unit_tests/vbo_tests.dm @@ -1,3 +1,12 @@ +/// Tests that all mobs with assigned bellies use valid datums +/datum/unit_test/vbo_has_state + +/datum/unit_test/vbo_has_state/Run() + for(var/datum/belly_overlays/test_path as anything in subtypesof(/datum/belly_overlays)) + var/icon_name = icon_states_fast(initial(test_path.belly_icon))[1] + if(!(icon_exists('icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_base.dmi', icon_name))) + TEST_FAIL("[test_path] is missing inside the screen_full_vore_list_base list dmi file.") + /// Tests that all mobs with assigned bellies use valid datums /datum/unit_test/mobs_use_valid_belly_overlays diff --git a/code/modules/unit_tests/vore_tests.dm b/code/modules/unit_tests/vore_tests.dm index ba1fde8f56..32fa9a9996 100644 --- a/code/modules/unit_tests/vore_tests.dm +++ b/code/modules/unit_tests/vore_tests.dm @@ -1,214 +1,103 @@ -/// converted unit test, maybe should be fully refactored +/datum/unit_test/proc/create_test_human(turf/loc = null) + if(!loc) + for(var/turf/simulated/floor/tiled/T in world) + var/pressure = T.zone.air.return_pressure() + if(90 < pressure && pressure < 120) // Find a turf between 90 and 120 + loc = T + break -// FIXME: THIS SHOULD BE REPLACED WITH ALLOCATE IN THE END -// SEE unit_test.dm NEW() WHY THIS ISNT IMPLEMENTED YET -/datum/unit_test - var/static/default_mobloc = null + TEST_ASSERT(loc, "No valid turf available for test mob") -// FIXME: THIS SHOULD BE REPLACED WITH ALLOCATE IN THE END -// SEE unit_test.dm NEW() WHY THIS ISNT IMPLEMENTED YET -/datum/unit_test/proc/create_test_mob(var/turf/mobloc = null, var/mobtype = /mob/living/carbon/human, var/with_mind = FALSE) - if(isnull(mobloc)) - if(!default_mobloc) - for(var/turf/simulated/floor/tiled/T in world) - var/pressure = T.zone.air.return_pressure() - if(90 < pressure && pressure < 120) // Find a turf between 90 and 120 - default_mobloc = T - break - mobloc = default_mobloc - if(!mobloc) - fail("Unable to find a location to create test mob") - return 0 + var/mob/living/carbon/human/test_human = allocate(/mob/living/carbon/human, loc) - var/mob/living/carbon/human/H = new mobtype(mobloc) + return test_human - if(with_mind) - H.mind_initialize("TestKey[rand(0,10000)]") - - return H - -/// Test that a human mob does not suffocate in a belly /datum/unit_test/belly_nonsuffocation - var/startLifeTick - var/startOxyloss - var/endOxyloss - var/mob/living/carbon/human/pred - var/mob/living/carbon/human/prey /datum/unit_test/belly_nonsuffocation/Run() - pred = create_test_mob() - if(!istype(pred)) - return 0 - prey = create_test_mob(pred.loc) - if(!istype(prey)) - return 0 + var/mob/living/carbon/human/pred = create_test_human() + var/mob/living/carbon/human/prey = create_test_human() - return 1 + TEST_ASSERT(pred && prey, "Failed to create test mobs") -/datum/unit_test/belly_nonsuffocation/check_result() - // Unfortuantely we need to wait for the pred's belly to initialize. (Currently after a spawn()) - if(!pred.vore_organs || !pred.vore_organs.len) - return 0 + pred.init_vore(TRUE) + TEST_ASSERT(pred.vore_selected, "[pred] has no vore_selected") - // Now that pred belly exists, we can eat the prey. - if(!pred.vore_selected) - fail("[pred] has no vore_selected.") - return 1 + pred.vore_selected.nom_mob(prey) - // Attempt to eat the prey - if(prey.loc != pred.vore_selected) - pred.vore_selected.nom_mob(prey) + TEST_ASSERT(prey.loc == pred.vore_selected, "Prey not inside predator belly") - if(prey.loc != pred.vore_selected) - fail("[pred.vore_selected].nom_mob([prey]) did not put prey inside [pred]") - return 1 + var/start_oxy = prey.getOxyLoss() + var/end_tick = pred.life_tick + 10 - // Okay, we succeeded in eating them, now lets wait a bit - startLifeTick = pred.life_tick - startOxyloss = prey.getOxyLoss() - return 0 + while(pred.life_tick < end_tick) + sleep(1) - if(pred.life_tick < (startLifeTick + 10)) - return 0 // Wait for them to breathe a few times + var/end_oxy = prey.getOxyLoss() + if(end_oxy > start_oxy) + TEST_FAIL("Prey took oxygen damage in belly (before: [start_oxy], after: [end_oxy])") - // Alright lets check it! - endOxyloss = prey.getOxyLoss() - if(startOxyloss < endOxyloss) - fail("Prey takes oxygen damage in a pred's belly! (Before: [startOxyloss]; after: [endOxyloss])") - else - pass("Prey is not taking oxygen damage in pred's belly. (Before: [startOxyloss]; after: [endOxyloss])") - - qdel(prey) - qdel(pred) - return 1 -//////////////////////////////////////////////////////////////// /datum/unit_test/belly_spacesafe - name = "MOB: human mob protected from space in a belly" - var/startLifeTick - var/startOxyloss - var/endOxyloss - var/mob/living/carbon/human/pred - var/mob/living/carbon/human/prey - async = 1 -/datum/unit_test/belly_spacesafe/start_test() - pred = create_test_mob() - if(!istype(pred)) - return 0 - prey = create_test_mob(pred.loc) - if(!istype(prey)) - return 0 +/datum/unit_test/belly_spacesafe/Run() + var/mob/living/carbon/human/pred = create_test_human() + var/mob/living/carbon/human/prey = create_test_human() - return 1 + TEST_ASSERT(pred && prey, "Failed to create test mobs") -/datum/unit_test/belly_spacesafe/check_result() - // Unfortuantely we need to wait for the pred's belly to initialize. (Currently after a spawn()) - if(!pred.vore_organs || !pred.vore_organs.len) - return 0 + pred.init_vore(TRUE) + TEST_ASSERT(pred.vore_selected, "[pred] has no vore_selected") - // Now that pred belly exists, we can eat the prey. - if(!pred.vore_selected) - fail("[pred] has no vore_selected.") - return 1 + pred.vore_selected.nom_mob(prey) - // Attempt to eat the prey - if(prey.loc != pred.vore_selected) - pred.vore_selected.nom_mob(prey) + TEST_ASSERT(prey.loc == pred.vore_selected, "Prey not inside predator belly") - if(prey.loc != pred.vore_selected) - fail("[pred.vore_selected].nom_mob([prey]) did not put prey inside [pred]") - return 1 - else - // Get an empty space level instead of just picking a random space turf - var/empty_z = using_map.get_empty_zlevel() - if(!empty_z) - fail("Unable to get empty z-level for vore space protection test!") - return 1 + var/empty_z = using_map.get_empty_zlevel() + TEST_ASSERT(empty_z, "Failed to get empty z-level") - // Away from map edges so they don't transit while we're testing - var/mid_w = round(world.maxx*0.5) - var/mid_h = round(world.maxy*0.5) + var/turf/space_turf = locate( + round(world.maxx * 0.5), + round(world.maxy * 0.5), + empty_z + ) - var/turf/T = locate(mid_w, mid_h, empty_z) + TEST_ASSERT(space_turf, "Failed to locate space turf") - if(!T) - fail("Unable to get turf for vore space protection test!") - return 1 - else - pred.forceMove(T) + pred.forceMove(space_turf) - // Okay, we succeeded in eating them, now lets wait a bit - startLifeTick = pred.life_tick - startOxyloss = prey.getOxyLoss() - return 0 + var/start_oxy = prey.getOxyLoss() + var/end_tick = pred.life_tick + 10 - if(pred.life_tick < (startLifeTick + 10)) - return 0 // Wait for them to breathe a few times + while(pred.life_tick < end_tick) + sleep(1) - // Alright lets check it! - endOxyloss = prey.getOxyLoss() - if(startOxyloss < endOxyloss) - fail("Prey takes oxygen damage in space! (Before: [startOxyloss]; after: [endOxyloss])") - else - pass("Prey is not taking oxygen damage in space. (Before: [startOxyloss]; after: [endOxyloss])") + var/end_oxy = prey.getOxyLoss() + if(end_oxy > start_oxy) + TEST_FAIL("Prey took oxygen damage in space belly (before: [start_oxy], after: [end_oxy])") - qdel(prey) - qdel(pred) - return 1 -//////////////////////////////////////////////////////////////// /datum/unit_test/belly_damage - name = "MOB: human mob takes damage from digestion" - var/startLifeTick - var/startBruteBurn - var/endBruteBurn - var/mob/living/carbon/human/pred - var/mob/living/carbon/human/prey - async = 1 -/datum/unit_test/belly_damage/start_test() - pred = create_test_mob() - if(!istype(pred)) - return 0 - prey = create_test_mob(pred.loc) - if(!istype(prey)) - return 0 +/datum/unit_test/belly_damage/Run() + var/mob/living/carbon/human/pred = create_test_human() + var/mob/living/carbon/human/prey = create_test_human() - return 1 + TEST_ASSERT(pred && prey, "Failed to create test mobs") -/datum/unit_test/belly_damage/check_result() - // Unfortuantely we need to wait for the pred's belly to initialize. (Currently after a spawn()) - if(!pred.vore_organs || !pred.vore_organs.len) - return 0 + pred.init_vore(TRUE) + TEST_ASSERT(pred.vore_selected, "[pred] has no vore_selected") - // Now that pred belly exists, we can eat the prey. - if(!pred.vore_selected) - fail("[pred] has no vore_selected.") - return 1 + pred.vore_selected.nom_mob(prey) - // Attempt to eat the prey - if(prey.loc != pred.vore_selected) - pred.vore_selected.nom_mob(prey) + TEST_ASSERT(prey.loc == pred.vore_selected, "Prey not inside predator belly") - if(prey.loc != pred.vore_selected) - fail("[pred.vore_selected].nom_mob([prey]) did not put prey inside [pred]") - return 1 + pred.vore_selected.digest_mode = DM_DIGEST - // Okay, we succeeded in eating them, now lets wait a bit - pred.vore_selected.digest_mode = DM_DIGEST - startLifeTick = pred.life_tick - startBruteBurn = prey.getBruteLoss() + prey.getFireLoss() - return 0 + var/start_damage = prey.getBruteLoss() + prey.getFireLoss() + var/end_tick = pred.life_tick + 10 - if(pred.life_tick < (startLifeTick + 10)) - return 0 // Wait a few ticks for damage to happen + while(pred.life_tick < end_tick) + sleep(1) - // Alright lets check it! - endBruteBurn = prey.getBruteLoss() + prey.getFireLoss() - if(startBruteBurn >= endBruteBurn) - fail("Prey doesn't take damage in digesting belly! (Before: [startBruteBurn]; after: [endBruteBurn])") - else - pass("Prey is taking damage in pred's belly. (Before: [startBruteBurn]; after: [endBruteBurn])") - - qdel(prey) - qdel(pred) - return 1 + var/end_damage = prey.getBruteLoss() + prey.getFireLoss() + if(end_damage <= start_damage) + TEST_FAIL("Prey took no digestion damage (before: [start_damage], after: [end_damage])") diff --git a/code/modules/vore/eating/belly_import.dm b/code/modules/vore/eating/belly_import.dm index 604609ea6f..82dc7dbd9a 100644 --- a/code/modules/vore/eating/belly_import.dm +++ b/code/modules/vore/eating/belly_import.dm @@ -828,9 +828,9 @@ if(new_disable_hud == 1) new_belly.disable_hud = TRUE - var/possible_fullscreens = cached_icon_states('icons/mob/screen_full_vore_list.dmi') + var/possible_fullscreens = icon_states_fast('icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_base.dmi') if(!new_belly.colorization_enabled) - possible_fullscreens = cached_icon_states('icons/mob/screen_full_vore.dmi') + possible_fullscreens = icon_states_fast('icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi') if(!(new_belly.belly_fullscreen in possible_fullscreens)) new_belly.belly_fullscreen = "" diff --git a/code/modules/vore/eating/belly_obj_liquids.dm b/code/modules/vore/eating/belly_obj_liquids.dm index c15f4d0121..cb0117a038 100644 --- a/code/modules/vore/eating/belly_obj_liquids.dm +++ b/code/modules/vore/eating/belly_obj_liquids.dm @@ -39,11 +39,11 @@ continue if(reagents.total_volume) reagents.trans_to(I, affecting_amt, 1, FALSE) - SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, FALSE, reagents.total_volume) // Signals vore_fx() reagents updates. + SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, reagents.total_volume) // Signals vore_fx() reagents updates. for(var/mob/living/L in contents) - vore_fx(L, FALSE, reagents.total_volume) + vore_fx(L, reagents.total_volume) if(owner.previewing_belly == src) - vore_fx(owner, FALSE, reagents.total_volume) + vore_fx(owner, reagents.total_volume) /obj/belly/proc/GenerateBellyReagents() if(isrobot(owner)) @@ -57,7 +57,7 @@ if(count_liquid_for_sprite) owner.handle_belly_update() //This is run whenever a belly's contents are changed. if(LAZYLEN(belly_surrounding)) - SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, FALSE, reagents.total_volume) // Signals vore_fx() reagents updates. + SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, reagents.total_volume) // Signals vore_fx() reagents updates. //////////////////////////// REAGENT_DIGEST //////////////////////// @@ -325,15 +325,15 @@ /obj/belly/proc/update_internal_overlay() if(LAZYLEN(belly_surrounding)) - SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX, TRUE) // Signals vore_fx() to listening atoms. Atoms must handle appropriate isliving() checks. + SEND_SIGNAL(src, COMSIG_BELLY_UPDATE_VORE_FX) // Signals vore_fx() to listening atoms. Atoms must handle appropriate isliving() checks. for(var/A in belly_surrounding) if(isliving(A)) - vore_fx(A,1) + vore_fx(A) if(owner.previewing_belly == src) if(isbelly(owner.loc)) owner.previewing_belly = null return - vore_fx(owner,1) + vore_fx(owner) /obj/belly/deserialize(var/list/data) ..() diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index dd6340e164..642d5acb5f 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -588,9 +588,9 @@ var/taste if(can_taste && living_mob.loc == src && (taste = living_mob.get_taste_message(FALSE))) // Prevent indirect tasting to_chat(owner, span_vnotice("[living_mob] tastes of [taste].")) - vore_fx(living_mob, TRUE) + vore_fx(living_mob) if(owner.previewing_belly == src) - vore_fx(owner, TRUE) + vore_fx(owner) //Stop AI processing in bellies if(living_mob.ai_holder) living_mob.ai_holder.go_sleep() @@ -653,7 +653,7 @@ // SEND_SIGNAL(COMSIG_BELLY_UPDATE_VORE_FX) is sometimes used when calling vore_fx() to send belly visuals // to certain non-belly atoms. Not called here as vore_fx() is usually only called if a mob is in the belly. // Don't forget it if you need to rework vore_fx(). -/obj/belly/proc/vore_fx(mob/living/L, var/update, var/severity = 0) +/obj/belly/proc/vore_fx(mob/living/L, var/severity = 0) if(!istype(L)) return if(!L.client) @@ -667,8 +667,6 @@ L.clear_fullscreen("belly") L.previewing_belly = null return - if(update) - L.clear_fullscreen("belly") if(belly_fullscreen) if(colorization_enabled) var/atom/movable/screen/fullscreen/F = L.overlay_fullscreen("belly", /atom/movable/screen/fullscreen/belly, severity) // preserving save data @@ -677,7 +675,7 @@ var/used_fullscreen = belly_fullscreen to_chat(owner, span_warning("The belly overlay ([used_fullscreen]) you've selected for [src] no longer exists. Please reselect your overlay.")) belly_fullscreen = null - CRASH("Icon datum was not defined for [used_fullscreen]") + log_runtime("Icon datum was not defined for [used_fullscreen]") var/alpha = min(belly_fullscreen_alpha, L.max_voreoverlay_alpha) F.icon = initial(lookup_belly_path.belly_icon) @@ -750,7 +748,7 @@ F.update_for_view(L.client.view) else var/atom/movable/screen/fullscreen/F = L.overlay_fullscreen("belly", /atom/movable/screen/fullscreen/belly/fixed, severity) //preserving save data - F.icon = 'icons/mob/screen_full_vore.dmi' + F.icon = 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi' F.cut_overlays() F.add_overlay(image(F.icon, belly_fullscreen)) F.add_overlay(image(F.icon, belly_fullscreen+"-2")) diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 9a69191d15..9101c10518 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -1098,11 +1098,8 @@ // Full screen belly overlays! /atom/movable/screen/fullscreen/belly - icon = 'icons/mob/vore_fullscreens/screen_full_vore_list.dmi' /atom/movable/screen/fullscreen/belly/fixed - icon = 'icons/mob/screen_full_vore.dmi' - icon_state = "" /mob/living/proc/vorebelly_printout() //Spew the vorepanel belly messages into chat window for copypasting. set name = "X-Print Vorebelly Settings" diff --git a/code/modules/vore/eating/panel_databackend/vorepanel_vore_data.dm b/code/modules/vore/eating/panel_databackend/vorepanel_vore_data.dm index bcd4a076e0..5071ea702f 100644 --- a/code/modules/vore/eating/panel_databackend/vorepanel_vore_data.dm +++ b/code/modules/vore/eating/panel_databackend/vorepanel_vore_data.dm @@ -238,9 +238,9 @@ ) var/list/belly_fullscreens if(selected.colorization_enabled) - belly_fullscreens = cached_icon_states('icons/mob/screen_full_vore_list.dmi') //Makes any icons inside of here selectable. + belly_fullscreens = icon_states_fast('icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_base.dmi') //Makes any icons inside of here selectable. else - belly_fullscreens = cached_icon_states('icons/mob/screen_full_vore.dmi') //Non colorable + belly_fullscreens = icon_states_fast('icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi') //Non colorable var/list/vs_flags = list() for(var/flag_name in selected.vore_sprite_flag_list) diff --git a/code/modules/vore/eating/soulcatcher.dm b/code/modules/vore/eating/soulcatcher.dm index f5c0d8cfb4..6104e8304e 100644 --- a/code/modules/vore/eating/soulcatcher.dm +++ b/code/modules/vore/eating/soulcatcher.dm @@ -192,7 +192,7 @@ //Announce to host and other minds notify_holder("New mind loaded: [brainmob.name]") - show_vore_fx(brainmob, TRUE) + show_vore_fx(brainmob) brainmob.copy_from_prefs_vr(bellies = FALSE) return TRUE @@ -251,7 +251,7 @@ /obj/soulgem/proc/toggle_setting(var/flag) setting_flags ^= flag if(flag & SOULGEM_SHOW_VORE_SFX) - soulgem_show_vfx(TRUE) + soulgem_show_vfx() soulgem_vfx() if(flag & NIF_SC_BACKUPS) soulgem_backup() @@ -330,22 +330,22 @@ RegisterSignal(linked_belly, COMSIG_BELLY_UPDATE_VORE_FX, PROC_REF(soulgem_show_vfx)) // Handles the vore fx updates for the captured souls -/obj/soulgem/proc/soulgem_show_vfx(var/update, var/severity = 0) +/obj/soulgem/proc/soulgem_show_vfx(var/severity = 0) SIGNAL_HANDLER if(linked_belly) for(var/mob/living/L in brainmobs) if(flag_check(SOULGEM_SHOW_VORE_SFX)) - show_vore_fx(L, update, severity) + show_vore_fx(L, severity) else clear_vore_fx(L) // Function to show the vore fx overlay -/obj/soulgem/proc/show_vore_fx(var/mob/living/L, var/update, var/severity = 0) +/obj/soulgem/proc/show_vore_fx(var/mob/living/L, var/severity = 0) if(!linked_belly || !flag_check(SOULGEM_SHOW_VORE_SFX)) return if(!istype(L) || L.eyeobj) return - linked_belly.vore_fx(L, update, severity) + linked_belly.vore_fx(L, severity) // Function to clear the vore fx overlay /obj/soulgem/proc/clear_vore_fx(var/mob/M) diff --git a/code/modules/vore/eating/soulcatcher_mob.dm b/code/modules/vore/eating/soulcatcher_mob.dm index 18da5a82e7..17c9f5d8fd 100644 --- a/code/modules/vore/eating/soulcatcher_mob.dm +++ b/code/modules/vore/eating/soulcatcher_mob.dm @@ -190,7 +190,7 @@ QDEL_NULL(eyeobj) gem.notify_holder("[src] ended SR projection.") - gem.show_vore_fx(src, TRUE) + gem.show_vore_fx(src) /mob/living/carbon/brain/caught_soul/vore/nsay_brain() set name = "NSay" diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index e1cac4c600..fae69b4bc0 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -59,11 +59,6 @@ host = null . = ..() -/datum/vore_look/ui_assets(mob/user) - . = ..() - . += get_asset_datum(/datum/asset/spritesheet/vore) - . += get_asset_datum(/datum/asset/spritesheet/vore_fixed) //Either this isn't working or my cache is corrupted and won't show them. - /datum/vore_look/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -530,7 +525,7 @@ host.client.prefs_vr.show_vore_fx = host.show_vore_fx if (isbelly(host.loc)) var/obj/belly/B = host.loc - B.vore_fx(host, TRUE) + B.vore_fx(host) else host.clear_fullscreen("belly") if(!host.hud_used.hud_shown) @@ -548,7 +543,7 @@ host.client.prefs_vr.max_voreoverlay_alpha = host.max_voreoverlay_alpha if (isbelly(host.loc)) var/obj/belly/B = host.loc - B.vore_fx(host, TRUE) + B.vore_fx(host) unsaved_changes = TRUE return TRUE // liquid belly code diff --git a/icons/mob/screen_full_colorized_vore.dmi b/icons/mob/screen_full_colorized_vore.dmi deleted file mode 100644 index d4bf393e17..0000000000 Binary files a/icons/mob/screen_full_colorized_vore.dmi and /dev/null differ diff --git a/icons/mob/screen_full_colorized_vore_overlays.dmi b/icons/mob/screen_full_colorized_vore_overlays.dmi deleted file mode 100644 index 77c45a57ec..0000000000 Binary files a/icons/mob/screen_full_colorized_vore_overlays.dmi and /dev/null differ diff --git a/icons/mob/screen_full_vore_list.dmi b/icons/mob/screen_full_vore_list.dmi deleted file mode 100644 index 7e7ae708d2..0000000000 Binary files a/icons/mob/screen_full_vore_list.dmi and /dev/null differ diff --git a/icons/mob/vore_fullscreens/VBO_belly9.dmi b/icons/mob/vore_fullscreens/VBO_belly9.dmi index 905e578282..83f6eb2a33 100644 Binary files a/icons/mob/vore_fullscreens/VBO_belly9.dmi and b/icons/mob/vore_fullscreens/VBO_belly9.dmi differ diff --git a/icons/mob/vore_fullscreens/VBO_fleshs.dmi b/icons/mob/vore_fullscreens/VBO_fleshs.dmi index 4971c00c27..71a6e0adac 100644 Binary files a/icons/mob/vore_fullscreens/VBO_fleshs.dmi and b/icons/mob/vore_fullscreens/VBO_fleshs.dmi differ diff --git a/icons/mob/vore_fullscreens/VBO_intestines9.dmi b/icons/mob/vore_fullscreens/VBO_intestines9.dmi index 5b6232c9eb..b07e1f38e5 100644 Binary files a/icons/mob/vore_fullscreens/VBO_intestines9.dmi and b/icons/mob/vore_fullscreens/VBO_intestines9.dmi differ diff --git a/icons/mob/vore_fullscreens/VBO_maw13.dmi b/icons/mob/vore_fullscreens/VBO_maw13.dmi index 0683c05bbb..994d642eb2 100644 Binary files a/icons/mob/vore_fullscreens/VBO_maw13.dmi and b/icons/mob/vore_fullscreens/VBO_maw13.dmi differ diff --git a/icons/mob/vore_fullscreens/VBO_maw14.dmi b/icons/mob/vore_fullscreens/VBO_maw14.dmi index a49bbf74dc..573d39ae3b 100644 Binary files a/icons/mob/vore_fullscreens/VBO_maw14.dmi and b/icons/mob/vore_fullscreens/VBO_maw14.dmi differ diff --git a/icons/mob/vore_fullscreens/VBO_maw15.dmi b/icons/mob/vore_fullscreens/VBO_maw15.dmi index ef73a2bba8..fec9dc9470 100644 Binary files a/icons/mob/vore_fullscreens/VBO_maw15.dmi and b/icons/mob/vore_fullscreens/VBO_maw15.dmi differ diff --git a/icons/mob/vore_fullscreens/VBO_maw18.dmi b/icons/mob/vore_fullscreens/VBO_maw18.dmi index 3dca1e7d68..37335b74c3 100644 Binary files a/icons/mob/vore_fullscreens/VBO_maw18.dmi and b/icons/mob/vore_fullscreens/VBO_maw18.dmi differ diff --git a/icons/mob/vore_fullscreens/VBO_maw27.dmi b/icons/mob/vore_fullscreens/VBO_maw27.dmi index 2e4736020d..a0493c5a0c 100644 Binary files a/icons/mob/vore_fullscreens/VBO_maw27.dmi and b/icons/mob/vore_fullscreens/VBO_maw27.dmi differ diff --git a/icons/mob/vore_fullscreens/VBO_notbelly.dmi b/icons/mob/vore_fullscreens/VBO_notbelly.dmi index e34abf974b..13c72ba4ec 100644 Binary files a/icons/mob/vore_fullscreens/VBO_notbelly.dmi and b/icons/mob/vore_fullscreens/VBO_notbelly.dmi differ diff --git a/icons/mob/vore_fullscreens/__readme.md b/icons/mob/vore_fullscreens/__readme.md new file mode 100644 index 0000000000..c611807de0 --- /dev/null +++ b/icons/mob/vore_fullscreens/__readme.md @@ -0,0 +1,73 @@ +# Overlay contribution + +This is a short guide and ruleset for contributing new overlays. + +## Table of contents + +- [Rules](#rules) +- [Assets](#assets) +- [Code](#code) +- [Example](#example) +- [Notes](#notes) + +## Rules + +To contribute new overlays, you need to be either the artist or the owner of the images, with written permission from the artist in the latter case. +The artist needs to clearly state that they allow the usage of those assets under a CC license. + +This policy applies to all assets added from December 2025 onward. + +## Assets + +For assets to be included, the following will be required: + +| Requirement | Notes | +| ---------------- | -------------------------------------------------------------------------------- | +| Overlay images | PNG format | +| Resolution | 480x480 and 120x120 | +| Layers | The image can consist of up to 4 layers; each layer needs to be its own PNG file | +| License | Must be CC-compatible | +| Artist credit | Required | +| Permission proof | Required if not the artist | + +## Code + +For assets to be loaded into the game, the following steps need to be followed: + +- The 480x480 resolution PNG files need to be moved into their own DMI file, with a file name `VBO_xxxxxxx.dmi`. + Each layer needs to be named the same as the file; for layers 2–4, the layer number is added after a dash (`-n`). + +- The 120x120 resolution PNG files need to be moved into the corresponding lists: + `screen_full_vore_list_base.dmi`, + `screen_full_vore_list_layer1.dmi`, + `screen_full_vore_list_layer2.dmi`, + `screen_full_vore_list_layer3.dmi`. + Across all files, the name needs to match the `VBO_xxxxxxx` name exactly. + +- Inside the `code/modules/asset_cache/assets/belly_assets.dm` file, a new asset datum needs to be created. + The name must match the `vbo_xxxxxxx` name exactly, but entirely lowercase. + +## Example + +The following is a quick example demonstration for `VBO_maw13`: + +- The asset itself consists of four layers, all contained within the main 480x480 asset file: + `icons/mob/vore_fullscreens/VBO_maw13.dmi` + +- Inside the four lists, each layer from the 120x120 file is stored under the `VBO_maw13` name: + `screen_full_vore_list_base.dmi`, + `screen_full_vore_list_layer1.dmi`, + `screen_full_vore_list_layer2.dmi`, + `screen_full_vore_list_layer3.dmi`. + +- The asset datum used to load the file into the game, located in + `code/modules/asset_cache/assets/belly_assets.dm`, looks like this: + +```text +/datum/belly_overlays/vbo_maw13 + belly_icon = 'icons/mob/vore_fullscreens/VBO_maw13.dmi' +``` + +## Notes + +Violations of licensing will result in a repo ban. diff --git a/icons/mob/vore_fullscreens/screen_full_vore_list.dmi b/icons/mob/vore_fullscreens/screen_full_vore_list.dmi deleted file mode 100644 index bed6c63bc7..0000000000 Binary files a/icons/mob/vore_fullscreens/screen_full_vore_list.dmi and /dev/null differ diff --git a/icons/mob/screen_full_vore_list_credits.txt b/icons/mob/vore_fullscreens/screen_full_vore_list_credits.txt similarity index 100% rename from icons/mob/screen_full_vore_list_credits.txt rename to icons/mob/vore_fullscreens/screen_full_vore_list_credits.txt diff --git a/icons/mob/screen_full_vore.dmi b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi similarity index 100% rename from icons/mob/screen_full_vore.dmi rename to icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi diff --git a/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_base.dmi b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_base.dmi new file mode 100644 index 0000000000..eb636d08cf Binary files /dev/null and b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_base.dmi differ diff --git a/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer1.dmi b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer1.dmi new file mode 100644 index 0000000000..fb2ab5cfc4 Binary files /dev/null and b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer1.dmi differ diff --git a/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer2.dmi b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer2.dmi new file mode 100644 index 0000000000..b8bbe4c849 Binary files /dev/null and b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer2.dmi differ diff --git a/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer3.dmi b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer3.dmi new file mode 100644 index 0000000000..2e6408f35b Binary files /dev/null and b/icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer3.dmi differ diff --git a/icons/mob/vore_fullscreens/yet_another_tumby.dmi b/icons/mob/vore_fullscreens/yet_another_tumby.dmi deleted file mode 100644 index f0a99f0a62..0000000000 Binary files a/icons/mob/vore_fullscreens/yet_another_tumby.dmi and /dev/null differ diff --git a/tgui/packages/tgui/interfaces/PublicLibraryWiki/WikiCommon/WikiColorIcon.tsx b/tgui/packages/tgui/interfaces/PublicLibraryWiki/WikiCommon/WikiColorIcon.tsx index 1f8eb42c7f..63435b4a35 100644 --- a/tgui/packages/tgui/interfaces/PublicLibraryWiki/WikiCommon/WikiColorIcon.tsx +++ b/tgui/packages/tgui/interfaces/PublicLibraryWiki/WikiCommon/WikiColorIcon.tsx @@ -63,7 +63,10 @@ export const CanvasBackedImage = (props: { width={dimension} height={dimension} onError={() => setLoadFailed(true)} - style={{ visibility: bitmap && !loadFailed ? 'visible' : 'hidden' }} + style={{ + visibility: bitmap && !loadFailed ? 'visible' : 'hidden', + imageRendering: 'pixelated', + }} /> ); }; diff --git a/tgui/packages/tgui/interfaces/VorePanel/VorePanelElements/MultiOverlayImage.tsx b/tgui/packages/tgui/interfaces/VorePanel/VorePanelElements/MultiOverlayImage.tsx new file mode 100644 index 0000000000..edf3771c30 --- /dev/null +++ b/tgui/packages/tgui/interfaces/VorePanel/VorePanelElements/MultiOverlayImage.tsx @@ -0,0 +1,130 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; +import { getImage } from '../../PublicLibraryWiki/WikiCommon/WikiColorIcon'; +import type { Overlay } from '../types'; + +const imageCache = new Map>(); + +function cachedGetImage(url: string) { + if (!imageCache.has(url)) { + imageCache.set( + url, + getImage(url).catch(() => null), + ); + } + return imageCache.get(url)!; +} + +export const MultiOverlayImage = (props: { + overlays: Overlay[]; + size: number; + targetSize: number; +}) => { + const { overlays, size, targetSize } = props; + const [src, setSrc] = useState(''); + const blobRef = useRef(''); + + const render = useCallback( + async (canvas: OffscreenCanvas, ctx: OffscreenCanvasRenderingContext2D) => { + ctx.clearRect(0, 0, targetSize, targetSize); + ctx.imageSmoothingEnabled = false; + + const images = await Promise.all( + overlays.map(async (o, i) => { + const iconRef = o.icon ? Byond.iconRefMap?.[o.icon] : null; + if (!iconRef) return null; + const url = `${iconRef}?state=${o.iconState}`; + const img = await cachedGetImage(url); + return img; + }), + ); + + for (let i = 0; i < overlays.length; i++) { + const overlay = overlays[i]; + const image = images[i]; + if (!image) continue; + + ctx.globalCompositeOperation = 'source-over'; + ctx.drawImage(image, 0, 0, size, size, 0, 0, targetSize, targetSize); + + if (overlay.color) { + const tempCanvas = new OffscreenCanvas(targetSize, targetSize); + const tempCtx = tempCanvas.getContext('2d'); + if (!tempCtx) continue; + + tempCtx.imageSmoothingEnabled = false; + tempCtx.drawImage( + image, + 0, + 0, + size, + size, + 0, + 0, + targetSize, + targetSize, + ); + + tempCtx.globalCompositeOperation = 'multiply'; + tempCtx.fillStyle = overlay.color; + tempCtx.fillRect(0, 0, targetSize, targetSize); + + tempCtx.globalCompositeOperation = 'destination-in'; + tempCtx.drawImage( + image, + 0, + 0, + size, + size, + 0, + 0, + targetSize, + targetSize, + ); + + ctx.drawImage(tempCanvas, 0, 0); + } + } + + ctx.globalCompositeOperation = 'source-over'; + }, + [overlays], + ); + + const drawToBlob = useCallback(async () => { + const offscreen = new OffscreenCanvas(targetSize, targetSize); + const ctx = offscreen.getContext('2d'); + if (!ctx) return; + + try { + await render(offscreen, ctx); + const blob = await offscreen.convertToBlob(); + if (!blob) return; + + const url = URL.createObjectURL(blob); + if (blobRef.current) URL.revokeObjectURL(blobRef.current); + blobRef.current = url; + setSrc(url); + } catch (e) { + console.error('Failed to render image', e); + } + }, [render]); + + useEffect(() => { + drawToBlob(); + return () => { + if (blobRef.current) { + URL.revokeObjectURL(blobRef.current); + blobRef.current = ''; + } + }; + }, [drawToBlob]); + + return src ? ( + + ) : null; +}; diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VisualTab/BellyFullscreenPreview.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VisualTab/BellyFullscreenPreview.tsx new file mode 100644 index 0000000000..9b54d69e7b --- /dev/null +++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VisualTab/BellyFullscreenPreview.tsx @@ -0,0 +1,48 @@ +import { Blink, Box, Icon, Stack } from 'tgui-core/components'; +import type { BooleanLike } from 'tgui-core/react'; +import { getOverlays } from '../../functions'; +import { MultiOverlayImage } from '../../VorePanelElements/MultiOverlayImage'; + +export function BellyFullscreenPreview(props: { + colors: string[]; + belly_fullscreen: string; + colorization_enabled: BooleanLike; + possible_fullscreens: string[]; +}) { + const { + colors, + belly_fullscreen, + colorization_enabled, + possible_fullscreens, + } = props; + + if (!belly_fullscreen) { + return No overlay selected.; + } + + if (!possible_fullscreens.includes(belly_fullscreen)) { + return ( + + + + + + + + + Selected overly "{belly_fullscreen}" no longer exists! + + Please select a new one. + + + ); + } + + return ( + + ); +} diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VisualTab/BellyFullscreenSelection.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VisualTab/BellyFullscreenSelection.tsx index 65f36ab5cc..bbb3b6ebbe 100644 --- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VisualTab/BellyFullscreenSelection.tsx +++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VisualTab/BellyFullscreenSelection.tsx @@ -1,8 +1,12 @@ import { useBackend } from 'tgui/backend'; -import { Box, Button, Section, Stack } from 'tgui-core/components'; -import { type BooleanLike, classes } from 'tgui-core/react'; +import { Button, Section, Stack } from 'tgui-core/components'; +import type { BooleanLike } from 'tgui-core/react'; +import { getOverlays } from '../../functions'; +import { MultiOverlayImage } from '../../VorePanelElements/MultiOverlayImage'; +import { BellyFullscreenPreview } from './BellyFullscreenPreview'; export const BellyFullscreenSelection = (props: { + colors: string[]; editMode: boolean; belly_fullscreen: string; colorization_enabled: BooleanLike; @@ -11,6 +15,7 @@ export const BellyFullscreenSelection = (props: { const { act } = useBackend(); const { + colors, editMode, belly_fullscreen, colorization_enabled, @@ -31,24 +36,27 @@ export const BellyFullscreenSelection = (props: { Disabled - {Object.keys(possible_fullscreens).map((key, index) => ( - + {possible_fullscreens.map((fullscreen) => ( + @@ -60,16 +68,12 @@ export const BellyFullscreenSelection = (props: { - {belly_fullscreen ? ( - - ) : ( - No overlay selected. - )} + diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyVisuals.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyVisuals.tsx index 8570f9de5c..6be277f7f1 100644 --- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyVisuals.tsx +++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyVisuals.tsx @@ -164,6 +164,12 @@ export const VoreSelectedBellyVisuals = (props: { = cost; @@ -194,3 +194,31 @@ export function ourTypeToOptions( } return []; } + +export function getOverlays( + state: string, + colors: string[], + colorize: boolean, +): Overlay[] { + if (!colorize) + return [ + { + icon: 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore.dmi', + iconState: state, + }, + ]; + + const base = + 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_base.dmi'; + const layers = [ + 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer1.dmi', + 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer2.dmi', + 'icons/mob/vore_fullscreens/ui_lists/screen_full_vore_list_layer3.dmi', + ]; + + return [base, ...layers].map((icon, i) => ({ + icon, + iconState: state, + color: colors[i], + })); +} diff --git a/tgui/packages/tgui/interfaces/VorePanel/types.ts b/tgui/packages/tgui/interfaces/VorePanel/types.ts index e2b1d46c50..c735d35e7e 100644 --- a/tgui/packages/tgui/interfaces/VorePanel/types.ts +++ b/tgui/packages/tgui/interfaces/VorePanel/types.ts @@ -482,3 +482,9 @@ export type ActionButtonData = { color?: string; needsConfirm?: boolean; }; + +export type Overlay = { + icon: string; + iconState: string; + color?: string; +}; diff --git a/vorestation.dme b/vorestation.dme index 17aae861d9..b07c64a891 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -2319,7 +2319,6 @@ #include "code\modules\asset_cache\assets\spritesheets\robot_icons.dm" #include "code\modules\asset_cache\assets\spritesheets\stacks.dm" #include "code\modules\asset_cache\assets\spritesheets\vending.dm" -#include "code\modules\asset_cache\assets\spritesheets\vore.dm" #include "code\modules\asset_cache\iconforge\batched_spritesheet.dm" #include "code\modules\asset_cache\iconforge\universal_icon.dm" #include "code\modules\asset_cache\transports\asset_transport.dm"