mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 00:55:20 +01:00
8f73588d9a
## About The Pull Request I thought megafauna were hard to refactor into simple mobs, and they kinda are, but also enough work has been done on them through various refactors (e.g. mob abilities) that it's not _too_ bad, but I didn't really relish working on it. Regardless, it's refactored! A few more of the ol' simple mobs flushed down the toilet, with a bunch more features to make porting over more `megafauna` to the basic mob's `boss` framework even simpler. There's some weird patterns that are introduced in here to better fit the old system's parity, but I don't really mind having done that since it's more important to get stuff out of the simple mob framework and into something a bit easier to work with and extend. Here are all of the changes I can recall having made: * A lot of the documentation regarding the blood drunk miner did not actually meet reality. The current refactor reflects what the code was actually doing, not what was documented. * The code regarding using the saw's `melee attack chain` stuff wasn't changed. Sorry but I can't even start to unravel that, I just overrode the whole attack thing because it's not really incorporable from what I was finding. * Basic mobs operate differently than simple mobs, thus this mob will be "harder" for a shorter amount of time as people are not used to the current timings/pathfinding behavior/cooldowns/etc. of the modern blood drunk miner. The overall difficulty didn't feel too different to me in my playtesting, but changes can certainly be made if someone can tell me which variable to fix. * Basic Bosses now appear in the orbit menu as mob POIs, parity with megafauna * Basic Bosses can now use the boss music component. ## Why It's Good For The Game Cleans up the code by incorporating it into a modern framework that already accounts for a lot of the stuff that was taken for granted 8-9 years ago when this was first implemented, and tries to keep any possible number the same in doing so. Should be much easier to add new graphics or overhaul the boss's AI to transform it into something even more interesting should someone choose to do so. Let me know if I fucked up with signals/ai behavior patterns/etc. somewhere as it's been a while since I touched this stuff and I had to clean out a lot of cobwebs in my brain to get to this implementation. ## Changelog 🆑 balance: Miners Beware: Blood Drunk Miners have been refactored into basic mobs. This means their timings and such may be a bit more unpredictable than what you're used to. The difficulty should be about the same, but do approach with caution lest you get devoured... /🆑 Hopefully more people can pitch in with refactoring megafauna now... not too bad anymore after I fixed some of the jank...
86 lines
3.3 KiB
Plaintext
86 lines
3.3 KiB
Plaintext
/**
|
|
* Attaches to a mob and plays that music while they have a target.
|
|
*/
|
|
/datum/component/boss_music
|
|
///The music track we will play to players.
|
|
var/boss_track
|
|
///How long the track is, used to clear players out when the music is supposed to end.
|
|
var/track_duration
|
|
|
|
///List of all mobs listening to the boss music currently. Cleared on Destroy or after `track_duration`.
|
|
var/list/datum/weakref/players_listening_refs = list()
|
|
///List of callback timers, used to clear out mobs listening to boss music after `track_duration`.
|
|
var/list/music_callbacks = list()
|
|
|
|
/// Signal that we listen to on our parent to know when to start boss music.
|
|
/// On basic mobs, the signal should be a variant of `COMSIG_AI_BLACKBOARD_KEY_SET()`, feeding in whatever key you want.
|
|
var/signal = null
|
|
|
|
/datum/component/boss_music/Initialize(boss_track, signal)
|
|
. = ..()
|
|
if(!ismob(parent) || isnull(signal))
|
|
return COMPONENT_INCOMPATIBLE
|
|
src.boss_track = boss_track
|
|
src.signal = signal
|
|
track_duration = SSsounds.get_sound_length(boss_track)
|
|
|
|
/datum/component/boss_music/Destroy(force)
|
|
. = ..()
|
|
for(var/callback in music_callbacks)
|
|
deltimer(callback)
|
|
music_callbacks = null
|
|
|
|
for(var/player_refs in players_listening_refs)
|
|
clear_target(player_refs)
|
|
players_listening_refs = null
|
|
|
|
/datum/component/boss_music/RegisterWithParent()
|
|
. = ..()
|
|
if(isbasicmob(parent))
|
|
RegisterSignal(parent, signal, PROC_REF(basic_target_found))
|
|
else
|
|
RegisterSignal(parent, signal, PROC_REF(on_target_found))
|
|
|
|
/datum/component/boss_music/UnregisterFromParent()
|
|
UnregisterSignal(parent, signal)
|
|
return ..()
|
|
|
|
/// Handler wrapper for basic mobs getting a target. The signal we pass to basic mobs passes along the blackboard key which we can access off parent.
|
|
/datum/component/boss_music/proc/basic_target_found(mob/source, key)
|
|
SIGNAL_HANDLER
|
|
var/mob/new_target = source.ai_controller.blackboard[key]
|
|
on_target_found(source, new_target)
|
|
|
|
///Handles giving the boss music to a new target the fauna has received.
|
|
///Keeps track of them to not repeatedly overwrite its own track.
|
|
/datum/component/boss_music/proc/on_target_found(mob/source, mob/new_target)
|
|
SIGNAL_HANDLER
|
|
|
|
if(QDELETED(source) || !istype(new_target))
|
|
return
|
|
|
|
var/datum/weakref/new_ref = WEAKREF(new_target)
|
|
if(new_ref in players_listening_refs)
|
|
return
|
|
|
|
players_listening_refs += new_ref
|
|
RegisterSignal(new_target, COMSIG_LIVING_DEATH, PROC_REF(on_mob_death))
|
|
music_callbacks += addtimer(CALLBACK(src, PROC_REF(clear_target), new_ref), track_duration, TIMER_STOPPABLE)
|
|
new_target.playsound_local(new_target, boss_track, 200, FALSE, channel = CHANNEL_BOSS_MUSIC, pressure_affected = FALSE, use_reverb = FALSE)
|
|
|
|
///Called when a mob listening to boss music dies- ends their music early.
|
|
/datum/component/boss_music/proc/on_mob_death(mob/living/source)
|
|
SIGNAL_HANDLER
|
|
var/datum/weakref/player_ref = WEAKREF(source)
|
|
clear_target(player_ref)
|
|
|
|
///Removes `old_target` from the list of players listening, and stops their music if it is still playing.
|
|
///This allows them to have music played again if they re-enter combat with this fauna.
|
|
/datum/component/boss_music/proc/clear_target(datum/weakref/old_ref)
|
|
players_listening_refs -= old_ref
|
|
|
|
var/mob/old_target = old_ref?.resolve()
|
|
if(old_target)
|
|
UnregisterSignal(old_target, COMSIG_LIVING_DEATH)
|
|
old_target.stop_sound_channel(CHANNEL_BOSS_MUSIC)
|