diff --git a/code/controllers/subsystems/icon_updates.dm b/code/controllers/subsystems/icon_updates.dm index 562e7f78207..8af3dbced20 100644 --- a/code/controllers/subsystems/icon_updates.dm +++ b/code/controllers/subsystems/icon_updates.dm @@ -113,6 +113,8 @@ SUBSYSTEM_DEF(icon_update) var/icon_update_delay = null /atom/proc/update_icon() + SHOULD_NOT_SLEEP(TRUE) + return /** * DO NOT USE diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm index 5b00b63cc66..fd1f302d156 100644 --- a/code/modules/hydroponics/seed.dm +++ b/code/modules/hydroponics/seed.dm @@ -810,6 +810,9 @@ growth_stages = 0 /datum/seed/proc/get_growth_type() + SHOULD_NOT_SLEEP(TRUE) + SHOULD_BE_PURE(TRUE) + if(get_trait(TRAIT_SPREAD) == 2) switch(seed_noun) if(SEED_NOUN_CUTTINGS) @@ -822,28 +825,95 @@ return GROWTH_VINES return 0 +/** + * A list of seed icons, to avoid regenerating images like there's no tomorrow + * + * Only access this by using the `SEED_ICON_CACHE_KEY` macro + * + * The structure is an associative list with the result of `SEED_ICON_CACHE_KEY` as the key + * and an `/image` as the value + */ +GLOBAL_LIST_INIT(seed_icon_cache, list()) + +///Generates a text hash that works as the key for the `seed_icon_cache` GLOB list +#define SEED_ICON_CACHE_KEY(file, state, color, leaves_overlay) "[file]|||[state]|||[color]|||[leaves_overlay]" + /datum/seed/proc/get_icon(growth_stage) - var/image/res = image('icons/obj/hydroponics_growing.dmi', "[get_trait(TRAIT_PLANT_ICON)]-[growth_stage]") + SHOULD_NOT_SLEEP(TRUE) + RETURN_TYPE(/image) + + if(isnull(growth_stage)) + crash_with("No growth stage was supplied when getting the icon!") + + /* Setup a bunch of shit that should have been done in a very different way but alas */ + + //The icon of the plant + var/icon_trait = get_trait(TRAIT_PLANT_ICON) + //The type of growth var/growth_type = get_growth_type() - if(growth_type) - res.icon_state = "[growth_type]-[growth_stage]" + //If it's a vine + var/is_vine = (get_trait(TRAIT_SPREAD) == 2) + //If the icon is a large one + var/is_large_icon = get_trait(TRAIT_LARGE) + //The color of the leaves, if any + var/leaves_color = get_trait(TRAIT_LEAVES_COLOUR) + + /* The part where we select what to request */ + + //Pick what file we want + var/icon_file_to_request + if(is_vine) + icon_file_to_request = 'icons/obj/hydroponics_vines.dmi' + else if(is_large_icon) + icon_file_to_request = 'icons/obj/hydroponics_large.dmi' else - res.icon_state = "[get_trait(TRAIT_PLANT_ICON)]-[growth_stage]" + icon_file_to_request = 'icons/obj/hydroponics_growing.dmi' - if(growth_type == GROWTH_VINES) - res.icon = 'icons/obj/hydroponics_vines.dmi' + //Pick what icon state to request + var/icon_state_to_request = (is_vine) ? "[growth_type]-[growth_stage]" : "[icon_trait]-[growth_stage]" - res.color = get_trait(TRAIT_PLANT_COLOUR) + //Pick the color to assign to the image + var/color_to_request = get_trait(TRAIT_PLANT_COLOUR) - if(get_trait(TRAIT_LARGE)) - res.icon = 'icons/obj/hydroponics_large.dmi' - res.pixel_x = -8 - res.pixel_y = -16 + //The leaves color overlay to request + var/leaves_overlay_to_request = (leaves_color) ? "[icon_trait]-[growth_stage]-leaves" : null - if(get_trait(TRAIT_LEAVES_COLOUR)) - var/image/I = image(res.icon, "[get_trait(TRAIT_PLANT_ICON)]-[growth_stage]-leaves") - I.color = get_trait(TRAIT_LEAVES_COLOUR) - I.appearance_flags = RESET_COLOR - res.add_overlay(I) + /* Find or generate the image and return it */ - return res + //See if we have this in our cache + if(SEED_ICON_CACHE_KEY(icon_file_to_request, icon_state_to_request, color_to_request, leaves_overlay_to_request) in GLOB.seed_icon_cache) + return GLOB.seed_icon_cache[SEED_ICON_CACHE_KEY(icon_file_to_request, icon_state_to_request, color_to_request, leaves_overlay_to_request)] + + //No luck, it's not in the cache, time to generate it + else + + //Check that there's a valid icon state we can use, abort otherwise + var/valid_icon_states = icon_states(icon_file_to_request, 2) + if(!(icon_state_to_request in valid_icon_states)) + crash_with("A seed icon was requested with an invalid icon state! Icon file: [icon_file_to_request] ---- Icon state: [icon_state_to_request]") + + var/image/generated_image = image(icon_file_to_request, icon_state_to_request) + + //Assign the requested + generated_image.color = color_to_request + + //If it's a large icon, offset it + if(is_large_icon) + generated_image.pixel_x = -8 + generated_image.pixel_y = -16 + + //If leaves are requested, add them as overlays + if(leaves_overlay_to_request) + var/image/leaves_image = image(icon_file_to_request, leaves_overlay_to_request) + leaves_image.color = leaves_color + leaves_image.appearance_flags = RESET_COLOR + //Add ourself as overlays to the generated image + generated_image.add_overlay(leaves_image) + + //Store the image in the cache, so we won't have to keep generating it + GLOB.seed_icon_cache[SEED_ICON_CACHE_KEY(icon_file_to_request, icon_state_to_request, color_to_request, leaves_overlay_to_request)] = generated_image + + //Return the image + return generated_image + +#undef SEED_ICON_CACHE_KEY diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm index c37429eb651..2736ed14492 100644 --- a/code/modules/hydroponics/spreading/spreading.dm +++ b/code/modules/hydroponics/spreading/spreading.dm @@ -1,13 +1,12 @@ #define DEFAULT_SEED "glowshroom" #define VINE_GROWTH_STAGES 5 -/proc/spacevine_infestation(var/potency_min=70, var/potency_max=100, var/maturation_min=5, var/maturation_max=15) - set waitfor = FALSE - +/proc/spacevine_infestation(var/potency_min=70, var/potency_max=100, var/maturation_min=1, var/maturation_max=3) var/turf/T = pick_subarea_turf(/area/hallway, list(/proc/is_station_turf, /proc/not_turf_contains_dense_objects)) if(T) var/datum/seed/seed = SSplants.create_random_seed(TRUE, SEED_NOUN_PITS) seed.set_trait(TRAIT_SPREAD,2) // So it will function properly as vines. + seed.growth_stages = VINE_GROWTH_STAGES seed.set_trait(TRAIT_POTENCY,rand(potency_min, potency_max)) // 70-100 potency will help guarantee a wide spread and powerful effects. seed.set_trait(TRAIT_MATURATION,rand(maturation_min, maturation_max)) @@ -53,6 +52,8 @@ var/max_health = 100 var/growth_threshold = 0 var/growth_type = 0 + + ///The maximum growth of this plant effect, aka the maximum stage var/max_growth = 0 var/list/neighbors = list() var/obj/effect/plant/parent @@ -118,10 +119,11 @@ spread_chance = seed.get_trait(TRAIT_POTENCY) spread_distance = (growth_type ? round(spread_chance * 0.6) : round(spread_chance * 0.3)) update_icon() - addtimer(CALLBACK(src, PROC_REF(post_initialize)), 1) + return INITIALIZE_HINT_LATELOAD // Plants will sometimes be spawned in the turf adjacent to the one they need to end up in, for the sake of correct dir/etc being set. -/obj/effect/plant/proc/post_initialize() +/obj/effect/plant/LateInitialize() + . = ..() set_dir(calc_dir()) update_icon() SSplants.add_plant(src) @@ -165,10 +167,12 @@ last_biolum = null /obj/effect/plant/proc/refresh_icon() + SHOULD_NOT_SLEEP(TRUE) + overlays.Cut() var/growth = 0 if(growth_threshold) - growth = min(max_growth,round(health/growth_threshold)) + growth = min(max_growth, round(health/growth_threshold)) var/at_fringe = get_dist(src,parent) if(spread_distance > 5) if(at_fringe >= (spread_distance-3)) @@ -176,7 +180,11 @@ if(at_fringe >= (spread_distance-2)) max_growth-- - var/our_icon = seed.get_icon(growth) + var/image/our_icon = seed.get_icon(growth) + + if(!istype(our_icon)) + crash_with("The plant didn't return an icon!") + add_overlay(our_icon) if(growth>2 && growth == max_growth) diff --git a/html/changelogs/fluffyghost-anotherattemptatfixingvines.yml b/html/changelogs/fluffyghost-anotherattemptatfixingvines.yml new file mode 100644 index 00000000000..ddcbda6e5c0 --- /dev/null +++ b/html/changelogs/fluffyghost-anotherattemptatfixingvines.yml @@ -0,0 +1,45 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: FluffyGhost + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Hopefully fixed the vines icons once and for all." + - refactor: "Plant icons and icon generation now use a cache to store the images of the plants, saving processing time when the image is requested as they're not regenerated each time." + - backend: "Requesting a plant icon state that doesn't exist now throws a runtime." + - backend: "Some SDMM markings, DMDoc, minor adjustments around." + - backend: "Atom update icons are now marked as not sleepable." diff --git a/icons/obj/hydroponics_vines.dmi b/icons/obj/hydroponics_vines.dmi index 924a06bd057..34dda02f37d 100644 Binary files a/icons/obj/hydroponics_vines.dmi and b/icons/obj/hydroponics_vines.dmi differ