From ae6866737260ee77ecccf7b87a7a23cd3455a15a Mon Sep 17 00:00:00 2001 From: Kano <89972582+kano-dot@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:57:04 +0300 Subject: [PATCH] Ports large object transparency from TGMC (#21508) Ports https://github.com/tgstation/TerraGov-Marine-Corps/pull/3528 Credit goes to original coders. This PR makes large objects transparent when something important is behind it. For now the list of large objects and the things make them transparent by using this component as follows: Large objects: - Trees - Cranes - Old shipping containers (new ones doesn't allow anything to go behind it) The things make them transparent: - Mobs - Carts - Portable generators - Nuke ## Images https://github.com/user-attachments/assets/a4f8ddfc-0fde-4b2d-8bd8-d15e1c6e8e0b ### Asset Licenses The following assets that **have not** been created by myself are included in this PR: | Path | Original Author | License | | --- | --- | --- | | code/datums/components/large_object_transparency.dm | nemvar (TGMC) | AGPLv3 | --- aurorastation.dme | 1 + code/__DEFINES/dcs/signals.dm | 6 + code/__DEFINES/flags.dm | 6 + .../components/large_object_transparency.dm | 116 ++++++++++++++++++ .../game/atom/atoms_initializing_EXPENSIVE.dm | 11 +- .../gamemodes/technomancer/instability.dm | 1 + code/game/machinery/nuclear_bomb.dm | 2 + code/game/objects/structures/carts/carts.dm | 1 + code/game/objects/structures/coastal.dm | 4 + code/game/objects/structures/urban.dm | 4 + code/game/turfs/turf_changing.dm | 1 + .../overmap/exoplanets/decor/flora/_tree.dm | 4 + code/modules/power/portgen.dm | 1 + ...-dot-let_me_make_myself_very_clear_gif.yml | 7 ++ 14 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 code/datums/components/large_object_transparency.dm create mode 100644 html/changelogs/kano-dot-let_me_make_myself_very_clear_gif.yml diff --git a/aurorastation.dme b/aurorastation.dme index 98e98e20c58..7afbd72766a 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -472,6 +472,7 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\connect_mob_behalf.dm" #include "code\datums\components\drift.dm" +#include "code\datums\components\large_object_transparency.dm" #include "code\datums\components\leanable.dm" #include "code\datums\components\local_network.dm" #include "code\datums\components\orbiter.dm" diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 071b7ebfc4c..7982de6f0d8 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -15,11 +15,17 @@ // /atom signals +/// Called from atom/Initialize() of target: (atom/target) +#define COMSIG_ATOM_INITIALIZED_ON "atom_initialized_on" + // /area signals #define COMSIG_AREA_FIRE_ALARM "fire_alarm" // /turf signals +/// From base of turf/ChangeTurf(): (path) +#define COMSIG_TURF_CHANGE "turf_change" + // /atom/movable signals #define COMSIG_MOVABLE_HEAR "movable_hear" diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 63192fcf332..fdf4f4c766d 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -66,6 +66,11 @@ GLOBAL_LIST_INIT(mimic_defines, list("ZM_MIMIC_BELOW", ///Shuttle transition will delete this. #define MOVABLE_FLAG_DEL_SHUTTLE FLAG(3) +// Atom flags + +/// Use when this shouldn't be obscured by large icons. +#define CRITICAL_ATOM FLAG(20) + // Obj flags /// Can this object be rotated? @@ -109,3 +114,4 @@ GLOBAL_LIST_INIT(mimic_defines, list("ZM_MIMIC_BELOW", #define ITEM_FLAG_NO_MOVE FLAG(12) /// Can be used for surgery, giving the "You're not sure what you can do with this." message if no surgery is available. #define ITEM_FLAG_SURGERY FLAG(13) + diff --git a/code/datums/components/large_object_transparency.dm b/code/datums/components/large_object_transparency.dm new file mode 100644 index 00000000000..27082a5cebd --- /dev/null +++ b/code/datums/components/large_object_transparency.dm @@ -0,0 +1,116 @@ +///Makes large icons partially see through if high priority atoms are behind them. +/datum/component/large_transparency + /// Can be positive or negative. Determines how far away from parent the first registered turf is. + var/x_offset + var/y_offset + /// Has to be positive or 0. + var/x_size + var/y_size + /// The alpha values this switches in between. + var/initial_alpha + var/target_alpha + /// If this is supposed to prevent clicks if it's transparent. + var/toggle_click + /// Atom's original mouse opacity, cached for restoring + var/initial_mouse_opacity + var/list/registered_turfs + var/amounthidden = 0 + +/datum/component/large_transparency/Initialize(_x_offset = 0, _y_offset = 1, _x_size = 0, _y_size = 1, _initial_alpha = null, _target_alpha = 140, _toggle_click = TRUE) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + x_offset = _x_offset + y_offset = _y_offset + x_size = _x_size + y_size = _y_size + var/atom/at = parent + + if(isnull(_initial_alpha)) + initial_alpha = at.alpha + + else + initial_alpha = _initial_alpha + target_alpha = _target_alpha + toggle_click = _toggle_click + initial_mouse_opacity = at.mouse_opacity + registered_turfs = list() + + +/datum/component/large_transparency/Destroy() + registered_turfs.Cut() + return ..() + +/datum/component/large_transparency/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(OnMove)) + RegisterWithTurfs() + +/datum/component/large_transparency/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_MOVABLE_MOVED) + UnregisterFromTurfs() + +/datum/component/large_transparency/proc/RegisterWithTurfs() + var/turf/current_tu = get_turf(parent) + if(!current_tu) + return + var/turf/lowleft_tu = locate(clamp(current_tu.x + x_offset, 0, world.maxx), clamp(current_tu.y + y_offset, 0, world.maxy), current_tu.z) + var/turf/upright_tu = locate(min(lowleft_tu.x + x_size, world.maxx), min(lowleft_tu.y + y_size, world.maxy), current_tu.z) + registered_turfs = block(lowleft_tu, upright_tu) //small problems with z level edges but nothing gamebreaking. + //register the signals + for(var/regist_tu in registered_turfs) + if(!regist_tu) + continue + RegisterSignals(regist_tu, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_INITIALIZED_ON), PROC_REF(objectEnter)) + RegisterSignal(regist_tu, COMSIG_ATOM_EXITED, PROC_REF(objectLeave)) + RegisterSignal(regist_tu, COMSIG_TURF_CHANGE, PROC_REF(OnTurfChange)) + for(var/thing in regist_tu) + var/atom/check_atom = thing + if(!(check_atom.atom_flags & CRITICAL_ATOM)) + continue + amounthidden++ + if(amounthidden) + reduceAlpha() + +/datum/component/large_transparency/proc/UnregisterFromTurfs() + var/list/signal_list = list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED, COMSIG_TURF_CHANGE, COMSIG_ATOM_INITIALIZED_ON) + for(var/regist_tu in registered_turfs) + UnregisterSignal(regist_tu, signal_list) + registered_turfs.Cut() + +/datum/component/large_transparency/proc/OnMove() + SIGNAL_HANDLER + amounthidden = 0 + restoreAlpha() + UnregisterFromTurfs() + RegisterWithTurfs() + +/datum/component/large_transparency/proc/OnTurfChange() + SIGNAL_HANDLER + addtimer(CALLBACK(src, PROC_REF(OnMove)), 1, TIMER_UNIQUE|TIMER_OVERRIDE) //*pain + +/datum/component/large_transparency/proc/objectEnter(datum/source, atom/enterer) + SIGNAL_HANDLER + if(!(enterer.atom_flags & CRITICAL_ATOM)) + return + if(!amounthidden) + reduceAlpha() + amounthidden++ + +/datum/component/large_transparency/proc/objectLeave(datum/source, atom/leaver, direction) + SIGNAL_HANDLER + if(!(leaver.atom_flags & CRITICAL_ATOM)) + return + amounthidden = max(0, amounthidden - 1) + if(!amounthidden) + restoreAlpha() + +/datum/component/large_transparency/proc/reduceAlpha() + var/atom/par_atom = parent + par_atom.alpha = target_alpha + if(toggle_click) + par_atom.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + +/datum/component/large_transparency/proc/restoreAlpha() + var/atom/par_atom = parent + par_atom.alpha = initial_alpha + if(toggle_click) + par_atom.mouse_opacity = initial_mouse_opacity diff --git a/code/game/atom/atoms_initializing_EXPENSIVE.dm b/code/game/atom/atoms_initializing_EXPENSIVE.dm index 7587e8fb914..6e93664a28e 100644 --- a/code/game/atom/atoms_initializing_EXPENSIVE.dm +++ b/code/game/atom/atoms_initializing_EXPENSIVE.dm @@ -129,19 +129,22 @@ reagents.maximum_volume += max(LAZYACCESS(reagents_to_add, v) - REAGENTS_FREE_SPACE(reagents), 0) reagents.add_reagent(v, LAZYACCESS(reagents_to_add, v), LAZYACCESS(reagent_data, v)) - if (light_power && light_range) + if(light_power && light_range) update_light() - if (opacity && isturf(loc)) + if(loc) + SEND_SIGNAL(loc, COMSIG_ATOM_INITIALIZED_ON, src) // used for large_object_transparency component + + if(isturf(loc) && opacity) var/turf/T = loc T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. #ifdef AO_USE_LIGHTING_OPACITY - if (!mapload) + if(!mapload) T.regenerate_ao() #endif - if (update_icon_on_init) + if(update_icon_on_init) SSicon_update.add_to_queue(src) //Finally an aurora snowflake code that matters, diff --git a/code/game/gamemodes/technomancer/instability.dm b/code/game/gamemodes/technomancer/instability.dm index 7c4ea6e1109..9357fefb54f 100644 --- a/code/game/gamemodes/technomancer/instability.dm +++ b/code/game/gamemodes/technomancer/instability.dm @@ -10,6 +10,7 @@ /mob/living + atom_flags = CRITICAL_ATOM var/instability = 0 var/last_instability = 0 // Used to calculate instability delta. var/last_instability_event = null // most recent world.time that something bad happened due to instability. diff --git a/code/game/machinery/nuclear_bomb.dm b/code/game/machinery/nuclear_bomb.dm index 4defdc5d264..7d7e136275d 100644 --- a/code/game/machinery/nuclear_bomb.dm +++ b/code/game/machinery/nuclear_bomb.dm @@ -6,6 +6,8 @@ GLOBAL_VAR(bomb_set) icon = 'icons/obj/nuke.dmi' icon_state = "idle" density = 1 + atom_flags = CRITICAL_ATOM + var/deployable = 0 var/extended = 0 var/lighthack = 0 diff --git a/code/game/objects/structures/carts/carts.dm b/code/game/objects/structures/carts/carts.dm index 18acf44e6bf..056df92bdce 100644 --- a/code/game/objects/structures/carts/carts.dm +++ b/code/game/objects/structures/carts/carts.dm @@ -8,6 +8,7 @@ ABSTRACT_TYPE(/obj/structure/cart) build_amt = 15 material = DEFAULT_WALL_MATERIAL slowdown = 0 + atom_flags = CRITICAL_ATOM var/movesound = 'sound/effects/roll.ogg' var/driving var/mob/living/pulling diff --git a/code/game/objects/structures/coastal.dm b/code/game/objects/structures/coastal.dm index 688bc0e8aa5..a2e3fa6b9bb 100644 --- a/code/game/objects/structures/coastal.dm +++ b/code/game/objects/structures/coastal.dm @@ -45,3 +45,7 @@ density = TRUE layer = 9 pixel_x = -16 + +/obj/structure/crane/Initialize() + . = ..() + AddComponent(/datum/component/large_transparency) diff --git a/code/game/objects/structures/urban.dm b/code/game/objects/structures/urban.dm index 02862770124..a411ecaada2 100644 --- a/code/game/objects/structures/urban.dm +++ b/code/game/objects/structures/urban.dm @@ -416,6 +416,10 @@ ABSTRACT_TYPE(/obj/structure/stairs/urban/road_ramp) density = TRUE layer = ABOVE_HUMAN_LAYER +/obj/structure/shipping_container_old/Initialize() + . = ..() + AddComponent(/datum/component/large_transparency) + /obj/effect/overlay/container_logo name = "Hephaestus Industries emblem" icon = 'icons/obj/structure/industrial/shipping_containers_old.dmi' diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm index 65252328c4d..15e6e087cea 100644 --- a/code/game/turfs/turf_changing.dm +++ b/code/game/turfs/turf_changing.dm @@ -60,6 +60,7 @@ var/old_is_open = is_open() var/list/old_resources = resources ? resources.Copy() : null + SEND_SIGNAL(src, COMSIG_TURF_CHANGE, path) changing_turf = TRUE if(connections) diff --git a/code/modules/overmap/exoplanets/decor/flora/_tree.dm b/code/modules/overmap/exoplanets/decor/flora/_tree.dm index da2d9666fea..cc6ee853a36 100644 --- a/code/modules/overmap/exoplanets/decor/flora/_tree.dm +++ b/code/modules/overmap/exoplanets/decor/flora/_tree.dm @@ -13,6 +13,10 @@ var/stumptype = /obj/structure/flora/stump //stump to make when chopped var/static/list/fall_forbid = list(/obj/structure/flora, /obj/effect, /obj/structure/bonfire, /obj/structure/pit) +/obj/structure/flora/tree/Initialize() + . = ..() + AddComponent(/datum/component/large_transparency) + /obj/structure/flora/tree/proc/update_desc() desc = initial(desc) switch(chop_health / max_chop_health) diff --git a/code/modules/power/portgen.dm b/code/modules/power/portgen.dm index 4674576f3cd..710478f7968 100644 --- a/code/modules/power/portgen.dm +++ b/code/modules/power/portgen.dm @@ -7,6 +7,7 @@ var/base_icon = "portgen0" density = TRUE anchored = FALSE + atom_flags = CRITICAL_ATOM var/active = FALSE var/power_gen = 5000 diff --git a/html/changelogs/kano-dot-let_me_make_myself_very_clear_gif.yml b/html/changelogs/kano-dot-let_me_make_myself_very_clear_gif.yml new file mode 100644 index 00000000000..2077c8fe661 --- /dev/null +++ b/html/changelogs/kano-dot-let_me_make_myself_very_clear_gif.yml @@ -0,0 +1,7 @@ + +author: Kano + +delete-after: True + +changes: + - qol: "Ported large object transparency from TGMC, allowing to see some things hiding behind large icons."