Files
Bubberstation/code/datums/components/hazard_area.dm
Ghom 999bde8f84 Most screen alerts now fit the player's hud style. (#93493)
## About The Pull Request
Most screen alerts that use the midnight hud style no longer have the
button baked in their icon. Other screen alerts with their own
background or shape (robot and mech alerts, atmos, heretic buffs or
debuffs etc.) are not affected. Also updated a couple sprites but didn't
spend too much time on them. Mostly reusing existing assets.

Montage of how the alerts look on threee different hud styles
(Operative, Trasen-Knox, Detective, ALSO I FIXED THE BUCKLED ALERT
ALREADY):
<img width="293" height="323" alt="image"
src="https://github.com/user-attachments/assets/3a2b972b-aa5a-4c27-a454-c8c39acf6e20"
/>
It looks only a smidge iffy on the syndicate since the top and bottom
borders aren't layered over all the overlays, but it isn't something to
worry about in this PR.

## Why It's Good For The Game
Screen alerts always had the midnight hud button baked in their icon
states (now overlays), which completely disregard the player's hud
setting, much unlike action alerts buttons. Melbert has also said that
it'd be nice if the code for action buttons could also be used in screen
alerts and viceversa, to slim things down. That's obviously not what I'm
doing today, but having most of the screen alerts already without the
baked background will surely help if we ever pursue that objective.

## Changelog

🆑
refactor: Refactored screen alerts a little. Most should now fit the
player's hud style. Report any issue.
imageadd: A few screen alerts have been polished/updated a little.
/🆑
2025-10-31 15:30:39 -06:00

174 lines
7.3 KiB
Plaintext

/**
* This is a relatively simple component that attempts to deter the parent of the component away
* from a specific area or areas. By default it simply applies a penalty where all movement is
* four times slower than usual and any action that would affect your 'next move' has a penalty
* multiplier of 4 attached.
*/
/datum/component/hazard_area
/// The blacklist of areas that the parent will be penalized for entering
var/list/area_blacklist
/// The whitelist of areas that the parent is allowed to be in. If set this overrides the blacklist
var/list/area_whitelist
/// A list of areas that have been created and are considered to not be hazardous
var/list/area_created
/// A variable storing the typepath of the last checked area to prevent any further logic running if it has not changed
VAR_PRIVATE/last_parent_area
/datum/component/hazard_area/Initialize(area_blacklist, area_whitelist)
. = ..()
if(!ismob(parent))
return COMPONENT_INCOMPATIBLE
if(!islist(area_blacklist) && !islist(area_whitelist))
stack_trace("[type] - neither area_blacklist nor area_whitelist were provided.")
return COMPONENT_INCOMPATIBLE
src.area_blacklist = area_blacklist
src.area_whitelist = area_whitelist
area_created = new
/datum/component/hazard_area/RegisterWithParent()
var/mob/parent_mob = parent
parent_mob.become_area_sensitive(type)
RegisterSignal(parent_mob, COMSIG_ENTER_AREA, PROC_REF(handle_parent_area_change))
RegisterSignal(parent_mob, COMSIG_LADDER_TRAVEL, PROC_REF(reject_ladder_movement))
RegisterSignal(parent_mob, COMSIG_VEHICLE_RIDDEN, PROC_REF(reject_vehicle))
RegisterSignal(SSdcs, COMSIG_AREA_CREATED, PROC_REF(on_area_creation))
/datum/component/hazard_area/UnregisterFromParent()
var/mob/parent_mob = parent
UnregisterSignal(parent_mob, list(COMSIG_ENTER_AREA, COMSIG_LADDER_TRAVEL, COMSIG_VEHICLE_RIDDEN))
UnregisterSignal(SSdcs, COMSIG_AREA_CREATED)
parent_mob.lose_area_sensitivity(type)
/datum/component/hazard_area/Destroy(force)
. = ..()
area_created = null
/**
* This signal handler checks the area the target ladder is in and if hazardous prevents them from using it
*/
/datum/component/hazard_area/proc/reject_ladder_movement(mob/source, obj/entrance_ladder, exit_ladder, going_up)
SIGNAL_HANDLER
if(check_area_hazardous(get_area(exit_ladder)))
entrance_ladder.balloon_alert(parent, "the path is too dangerous for you!")
return LADDER_TRAVEL_BLOCK
/**
* A simple signal handler that informs the parent they cannot ride a vehicle and ejects them
*/
/datum/component/hazard_area/proc/reject_vehicle(mob/source, obj/vehicle/vehicle)
SIGNAL_HANDLER
if(!check_area_hazardous(last_parent_area))
return
vehicle.balloon_alert(parent, "you slip and fall off!")
if(isliving(parent)) // We don't know for certain if we are a mob/living subtype
var/mob/living/parent_living = parent
parent_living.Stun(0.5 SECONDS)
return EJECT_FROM_VEHICLE
/**
* Checks if the area being checked is considered hazardous
* The whitelist is checked first if it exists, otherwise it checks if it is in the blacklist
*
* * checking - This should be the typepath of the area being checked, but there is a conversion handler if you pass in a reference instead
*/
/datum/component/hazard_area/proc/check_area_hazardous(area/checking)
if(LAZYFIND(area_created, checking))
return FALSE
if(!ispath(checking))
checking = checking.type
if(area_whitelist)
return !(checking in area_whitelist)
return checking in area_blacklist
/**
* This signal handler does a few house cleaning tasks when a new area is created.
* If the created area already exists in the blacklist or whitelist it simply returns,
* however if it isn't we check for an overwritten area and if non-hazardous setup the area to
* allow the parent.
* If there aren't any overwritten area's it assumes it to be non-hazardous, abuse it and you will weep -ZephyrTFA
*/
/datum/component/hazard_area/proc/on_area_creation(datum/source, area/created, list/area/overwritten, mob/creator)
SIGNAL_HANDLER
if(created.type in area_whitelist)
return // in whitelist, probably expanded an already whitelisted area
if(created.type in area_blacklist)
return // in blacklist, expanding a blacklisted area doesnt magically give you permission to enter
if(length(overwritten))
for(var/area/overwritten_area in overwritten)
if(check_area_hazardous(overwritten_area.type))
return // Overwrote a hazardous area, still hazardous fool
area_created -= overwritten_area // While its not guaranteed to be in the area_created list it's a good idea to ensure we dont have handing refs
area_created += created // Congrats, you are now allowed in this area
return
// No overwritten area, which means its a brand new area, for now we are going to be nice and assume its non-hazardous
// If people abuse this in the future to put rooms right next to the station add an is_station_level check
area_created += created
/**
* This proc handles the status effect applied to the parent, most noteably applying or removing it as required
*/
/datum/component/hazard_area/proc/update_parent_status_effect()
if(QDELETED(parent))
return
var/mob/living/parent_living = parent
var/datum/status_effect/hazard_area/effect = parent_living.has_status_effect(/datum/status_effect/hazard_area)
var/should_have_status_effect = check_area_hazardous(last_parent_area)
if(should_have_status_effect && !effect) // Should have the status - and doesnt
parent_living.apply_status_effect(/datum/status_effect/hazard_area)
if(parent_living.buckled)
parent_living.buckled.balloon_alert(parent, "you fall off!")
parent_living.buckled.unbuckle_mob(parent_living, force=TRUE)
return
if(!should_have_status_effect && effect) // Shouldn't have the status - and does
parent_living.remove_status_effect(/datum/status_effect/hazard_area)
/**
* This signal should be called whenever our parent moves.
*/
/datum/component/hazard_area/proc/handle_parent_area_change(mob/source, area/new_area)
SIGNAL_HANDLER
if(new_area.type == last_parent_area)
return
last_parent_area = new_area.type
INVOKE_ASYNC(src, PROC_REF(update_parent_status_effect))
/// The dedicated status effect for the hazard_area component - use with caution and know what it does!
/datum/status_effect/hazard_area
id = "hazard_area"
status_type = STATUS_EFFECT_UNIQUE
alert_type = /atom/movable/screen/alert/status_effect/hazard_area
/datum/status_effect/hazard_area/nextmove_modifier()
return 4
/datum/status_effect/hazard_area/on_apply()
. = ..()
owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/hazard_area, update=TRUE)
owner.add_actionspeed_modifier(/datum/actionspeed_modifier/status_effect/hazard_area, update=TRUE)
/datum/status_effect/hazard_area/on_remove()
. = ..()
owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/hazard_area, update=TRUE)
owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/status_effect/hazard_area, update=TRUE)
/datum/status_effect/hazard_area/get_examine_text()
return span_notice("[owner.p_They()] appear[owner.p_s()] to be largely immobilized through unknown means.")
/atom/movable/screen/alert/status_effect/hazard_area
name = "Hazardous Area"
desc = "The area you are currently within is incredibly hazardous to you. Check your surroundings and vacate as soon as possible."
use_user_hud_icon = TRUE
overlay_state = "hazard_area"