mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 21:18:37 +01:00
## 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. /🆑
165 lines
6.0 KiB
Plaintext
165 lines
6.0 KiB
Plaintext
/**
|
|
* Automatically shoot at a target if they do anything while this is active on them.
|
|
* Currently not given to any mob, but retained so admins can use it.
|
|
*/
|
|
/datum/action/cooldown/mob_cooldown/watcher_overwatch
|
|
name = "Overwatch"
|
|
desc = "Keep a close eye on the target's actions, automatically firing upon them if they act."
|
|
button_icon = 'icons/mob/actions/actions_ecult.dmi'
|
|
button_icon_state = "eye"
|
|
background_icon_state = "bg_demon"
|
|
overlay_icon_state = "bg_demon_border"
|
|
cooldown_time = 20 SECONDS
|
|
click_to_activate = TRUE
|
|
shared_cooldown = NONE
|
|
/// Furthest range we can activate ability at
|
|
var/max_range = 7
|
|
/// Type of projectile to fire
|
|
var/projectile_type = /obj/projectile/temp/watcher
|
|
/// Sound the projectile we fire makes
|
|
var/projectile_sound = 'sound/items/weapons/pierce.ogg'
|
|
/// Time to watch for
|
|
var/overwatch_duration = 3 SECONDS
|
|
|
|
/datum/action/cooldown/mob_cooldown/watcher_overwatch/New(Target, original)
|
|
. = ..()
|
|
melee_cooldown_time = overwatch_duration
|
|
|
|
/datum/action/cooldown/mob_cooldown/watcher_overwatch/PreActivate(atom/target)
|
|
if (target == owner)
|
|
return
|
|
if (ismecha(target))
|
|
var/obj/vehicle/sealed/mecha/mech = target
|
|
var/list/drivers = mech.return_drivers()
|
|
if (!length(drivers))
|
|
return
|
|
target = drivers[1]
|
|
if (!isliving(target))
|
|
return
|
|
if (get_dist(owner, target) > max_range)
|
|
return
|
|
return ..()
|
|
|
|
/datum/action/cooldown/mob_cooldown/watcher_overwatch/Activate(mob/living/target)
|
|
var/mob/living/living_owner = owner
|
|
living_owner.face_atom(target)
|
|
living_owner.Stun(overwatch_duration, ignore_canstun = TRUE)
|
|
target.apply_status_effect(/datum/status_effect/overwatch, overwatch_duration, owner, projectile_type, projectile_sound)
|
|
owner.visible_message(span_warning("[owner]'s eye locks on to [target]!"))
|
|
StartCooldown()
|
|
return TRUE
|
|
|
|
/// Status effect which tracks whether our overwatched mob moves or acts
|
|
/datum/status_effect/overwatch
|
|
id = "watcher_overwatch"
|
|
duration = 5 SECONDS
|
|
status_type = STATUS_EFFECT_MULTIPLE
|
|
alert_type = /atom/movable/screen/alert/status_effect/overwatch
|
|
/// Distance at which we break off the ability
|
|
var/watch_range = 9
|
|
/// Visual effect to make the status obvious
|
|
var/datum/beam/link
|
|
/// Which watcher is watching?
|
|
var/mob/living/watcher
|
|
/// Type of projectile to fire
|
|
var/projectile_type
|
|
/// Noise to make when we shoot beam
|
|
var/projectile_sound
|
|
/// Did the overwatch ever trigger during our run?
|
|
var/overwatch_triggered = FALSE
|
|
/// Signals which trigger a hostile response
|
|
var/static/list/forbidden_actions = list(
|
|
COMSIG_MOB_ABILITY_FINISHED,
|
|
COMSIG_MOB_ATTACK_HAND,
|
|
COMSIG_MOB_DROVE_MECH,
|
|
COMSIG_MOB_FIRED_GUN,
|
|
COMSIG_MOB_ITEM_ATTACK,
|
|
COMSIG_MOB_THROW,
|
|
COMSIG_MOB_USED_MECH_EQUIPMENT,
|
|
COMSIG_MOB_USED_CLICK_MECH_MELEE,
|
|
COMSIG_MOVABLE_MOVED,
|
|
)
|
|
|
|
/datum/status_effect/overwatch/on_creation(mob/living/new_owner, set_duration, mob/living/watcher, projectile_type, projectile_sound)
|
|
if (isnull(watcher) || isnull(projectile_type))
|
|
return FALSE
|
|
if (HAS_TRAIT(new_owner, TRAIT_OVERWATCH_IMMUNE))
|
|
return FALSE
|
|
src.watcher = watcher
|
|
src.projectile_type = projectile_type
|
|
src.projectile_sound = projectile_sound
|
|
if (!isnull(set_duration))
|
|
duration = set_duration
|
|
return ..()
|
|
|
|
/datum/status_effect/overwatch/on_apply()
|
|
. = ..()
|
|
if (!.)
|
|
return FALSE
|
|
owner.add_traits(list(TRAIT_OVERWATCHED, TRAIT_OVERWATCH_IMMUNE), REF(src))
|
|
owner.do_alert_animation()
|
|
owner.Immobilize(0.25 SECONDS) // Just long enough that they don't trigger it by mistake
|
|
owner.playsound_local(owner, 'sound/machines/chime.ogg', 50, TRUE)
|
|
var/atom/beam_origin = ismecha(owner.loc) ? owner.loc : owner
|
|
link = beam_origin.Beam(watcher, icon_state = "r_beam", override_target_pixel_x = 0)
|
|
RegisterSignals(owner, forbidden_actions, PROC_REF(opportunity_attack))
|
|
RegisterSignals(owner, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH), PROC_REF(on_participant_died))
|
|
RegisterSignals(watcher, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH), PROC_REF(on_participant_died))
|
|
|
|
/datum/status_effect/overwatch/on_remove()
|
|
UnregisterSignal(owner, forbidden_actions + list(COMSIG_QDELETING, COMSIG_LIVING_DEATH))
|
|
QDEL_NULL(link)
|
|
owner.remove_traits(list(TRAIT_OVERWATCHED, TRAIT_OVERWATCH_IMMUNE), REF(src))
|
|
if (!QDELETED(owner))
|
|
owner.apply_status_effect(/datum/status_effect/overwatch_immune)
|
|
return ..()
|
|
|
|
/datum/status_effect/overwatch/Destroy()
|
|
QDEL_NULL(link)
|
|
if (!isnull(watcher)) // Side effects in Destroy? Well it turns out `on_remove` is also just called on Destroy. But only if the owner isn't deleting.
|
|
INVOKE_ASYNC(src, PROC_REF(unregister_watcher), watcher)
|
|
watcher = null
|
|
|
|
return ..()
|
|
|
|
/// Clean up our association with the caster of this ability.
|
|
/datum/status_effect/overwatch/proc/unregister_watcher(mob/living/former_overwatcher)
|
|
if (!overwatch_triggered)
|
|
former_overwatcher.Stun(2 SECONDS, ignore_canstun = TRUE)
|
|
UnregisterSignal(former_overwatcher, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH))
|
|
|
|
/// Uh oh, you did something within my threat radius, now we're going to shoot you
|
|
/datum/status_effect/overwatch/proc/opportunity_attack()
|
|
SIGNAL_HANDLER
|
|
if (!can_see(watcher, owner, length = watch_range))
|
|
qdel(src)
|
|
return
|
|
overwatch_triggered = TRUE
|
|
watcher.do_alert_animation()
|
|
INVOKE_ASYNC(watcher, TYPE_PROC_REF(/atom/, fire_projectile), projectile_type, owner, projectile_sound)
|
|
|
|
/// Can't overwatch you if I don't exist
|
|
/datum/status_effect/overwatch/proc/on_participant_died()
|
|
SIGNAL_HANDLER
|
|
qdel(src)
|
|
|
|
/atom/movable/screen/alert/status_effect/overwatch
|
|
name = "Overwatched"
|
|
desc = "Freeze! You are being watched!"
|
|
use_user_hud_icon = TRUE
|
|
overlay_state = "aimed"
|
|
|
|
/// Blocks further applications of the ability for a little while
|
|
/datum/status_effect/overwatch_immune
|
|
id = "watcher_overwatch_immunity"
|
|
duration = 10 SECONDS // To stop watcher tendrils spamming the shit out of you
|
|
alert_type = null
|
|
|
|
/datum/status_effect/overwatch_immune/on_apply()
|
|
. = ..()
|
|
ADD_TRAIT(owner, TRAIT_OVERWATCH_IMMUNE, TRAIT_STATUS_EFFECT(id))
|
|
|
|
/datum/status_effect/overwatch_immune/on_remove()
|
|
REMOVE_TRAIT(owner, TRAIT_OVERWATCH_IMMUNE, TRAIT_STATUS_EFFECT(id))
|
|
return ..()
|