diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm index 032bcaa4e03..9901ba66588 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm @@ -15,3 +15,6 @@ ///FROM mob/living/simple_animal/hostile/ooze/eat_atom(): (atom/target, edible_flags) #define COMSIG_OOZE_EAT_ATOM "ooze_eat_atom" #define COMPONENT_ATOM_EATEN (1<<0) + +///Called when a /mob/living/simple_animal/hostile fines a new target: (atom/source, new_target) +#define COMSIG_HOSTILE_FOUND_TARGET "comsig_hostile_found_target" diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 5d6402938a8..b3025c4ccc1 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -4,11 +4,12 @@ #define CHANNEL_VOX 1022 #define CHANNEL_JUKEBOX 1021 #define CHANNEL_HEARTBEAT 1020 //sound channel for heartbeats -#define CHANNEL_AMBIENCE 1019 -#define CHANNEL_BUZZ 1018 -#define CHANNEL_TRAITOR 1017 -#define CHANNEL_CHARGED_SPELL 1016 -#define CHANNEL_ELEVATOR 1015 +#define CHANNEL_BOSS_MUSIC 1019 +#define CHANNEL_AMBIENCE 1018 +#define CHANNEL_BUZZ 1017 +#define CHANNEL_TRAITOR 1016 +#define CHANNEL_CHARGED_SPELL 1015 +#define CHANNEL_ELEVATOR 1014 ///Default range of a sound. #define SOUND_RANGE 17 diff --git a/code/datums/components/boss_music.dm b/code/datums/components/boss_music.dm new file mode 100644 index 00000000000..fa8635e0061 --- /dev/null +++ b/code/datums/components/boss_music.dm @@ -0,0 +1,65 @@ +/** + * Attaches to a hostile simplemob 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() + +/datum/component/boss_music/Initialize( + boss_track, + track_duration, +) + . = ..() + if(!ishostile(parent)) + return COMPONENT_INCOMPATIBLE + src.boss_track = boss_track + src.track_duration = track_duration + +/datum/component/boss_music/Destroy(force, silent) + . = ..() + 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() + . = ..() + RegisterSignal(parent, COMSIG_HOSTILE_FOUND_TARGET, PROC_REF(on_target_found)) + +/datum/component/boss_music/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_HOSTILE_FOUND_TARGET) + return ..() + +///Handles giving the boss music to a new target the fauna has recieved. +///Keeps track of them to not repeatedly overwrite its own track. +/datum/component/boss_music/proc/on_target_found(atom/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 + 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) + +///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) + old_target.stop_sound_channel(CHANNEL_BOSS_MUSIC) diff --git a/code/datums/components/geiger_sound.dm b/code/datums/components/geiger_sound.dm index 76ac0c62507..3a8a22df383 100644 --- a/code/datums/components/geiger_sound.dm +++ b/code/datums/components/geiger_sound.dm @@ -86,7 +86,7 @@ return ..(mid_sounds[get_perceived_radiation_danger(last_radiation_pulse, last_insulation_to_target)]) -/datum/looping_sound/geiger/stop() +/datum/looping_sound/geiger/stop(null_parent = FALSE) . = ..() last_radiation_pulse = null diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm index 449f55ae660..54185efdb8d 100644 --- a/code/datums/looping_sounds/_looping_sound.dm +++ b/code/datums/looping_sounds/_looping_sound.dm @@ -52,8 +52,9 @@ var/loop_started = FALSE /// If we're using cut_mid, this is the list we cut from var/list/cut_list - /// The index of the current song we're playing in the mid_sounds list, only used if in_order is used - var/audio_index = 1 + ///The index of the current song we're playing in the mid_sounds list, only used if in_order is used + ///This is immediately set to 1, so we start the index at 0 + var/audio_index = 0 // Args /// Do we skip the starting sounds? diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 3bdebc8b467..50e581844de 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -670,6 +670,7 @@ LoseTarget() /mob/living/simple_animal/hostile/proc/add_target(new_target) + SEND_SIGNAL(src, COMSIG_HOSTILE_FOUND_TARGET, new_target) if(target) UnregisterSignal(target, COMSIG_QDELETING) target = new_target diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 7564bbd8c51..22b7240907b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -90,6 +90,7 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/hierophant/Initialize(mapload) . = ..() spawned_beacon = new(loc) + AddComponent(/datum/component/boss_music, 'sound/lavaland/hiero_boss.ogg', 145 SECONDS) /mob/living/simple_animal/hostile/megafauna/hierophant/Destroy() QDEL_NULL(spawned_beacon) @@ -293,7 +294,7 @@ Difficulty: Hard new /obj/effect/temp_visual/hierophant/telegraph/diagonal(T, src) else new /obj/effect/temp_visual/hierophant/telegraph(T, src) - playsound(T,'sound/effects/bin_close.ogg', 200, TRUE) + playsound(T, 'sound/effects/bin_close.ogg', 75, TRUE) SLEEP_CHECK_DEATH(2, src) new /obj/effect/temp_visual/hierophant/blast/damaging(T, src, FALSE) for(var/d in directions) @@ -341,8 +342,8 @@ Difficulty: Hard var/turf/source = get_turf(src) new /obj/effect/temp_visual/hierophant/telegraph(T, src) new /obj/effect/temp_visual/hierophant/telegraph(source, src) - playsound(T,'sound/magic/wand_teleport.ogg', 200, TRUE) - playsound(source,'sound/machines/airlockopen.ogg', 200, TRUE) + playsound(T,'sound/magic/wand_teleport.ogg', 80, TRUE) + playsound(source,'sound/machines/airlockopen.ogg', 80, TRUE) blinking = TRUE SLEEP_CHECK_DEATH(2, src) //short delay before we start... new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, src) @@ -374,14 +375,14 @@ Difficulty: Hard if(!T) return new /obj/effect/temp_visual/hierophant/telegraph(T, src) - playsound(T,'sound/effects/bin_close.ogg', 200, TRUE) + playsound(T,'sound/effects/bin_close.ogg', 75, TRUE) SLEEP_CHECK_DEATH(2, src) for(var/t in RANGE_TURFS(1, T)) new /obj/effect/temp_visual/hierophant/blast/damaging(t, src, FALSE) //expanding square /proc/hierophant_burst(mob/caster, turf/original, burst_range, spread_speed = 0.5) - playsound(original,'sound/machines/airlockopen.ogg', 200, TRUE) + playsound(original,'sound/machines/airlockopen.ogg', 750, TRUE) var/last_dist = 0 for(var/t in spiral_range_turfs(burst_range, original)) var/turf/T = t @@ -489,7 +490,7 @@ Difficulty: Hard if(!stat && .) var/obj/effect/temp_visual/hierophant/squares/HS = new(old_loc) HS.setDir(movement_dir) - playsound(src, 'sound/mecha/mechmove04.ogg', 150, TRUE, -4) + playsound(src, 'sound/mecha/mechmove04.ogg', 80, TRUE, -4) if(target) arena_trap(target) @@ -680,7 +681,7 @@ Difficulty: Hard var/turf/T = get_turf(src) if(!T) return - playsound(T,'sound/magic/blind.ogg', 125, TRUE, -5) //make a sound + playsound(T,'sound/magic/blind.ogg', 65, TRUE, -5) //make a sound sleep(0.6 SECONDS) //wait a little bursting = TRUE do_damage(T) //do damage and mark us as bursting @@ -739,7 +740,7 @@ Difficulty: Hard /obj/effect/temp_visual/hierophant/blast/visual/Initialize(mapload, new_caster) . = ..() var/turf/src_turf = get_turf(src) - playsound(src_turf,'sound/magic/blind.ogg', 125, TRUE, -5) + playsound(src_turf,'sound/magic/blind.ogg', 65, TRUE, -5) /obj/effect/hierophant name = "hierophant beacon" @@ -756,7 +757,7 @@ Difficulty: Hard if(club.beacon == src) to_chat(user, span_notice("You start removing your hierophant beacon...")) if(do_after(user, 50, target = src)) - playsound(src,'sound/magic/blind.ogg', 200, TRUE, -4) + playsound(src,'sound/magic/blind.ogg', 100, TRUE, -4) new /obj/effect/temp_visual/hierophant/telegraph/teleport(get_turf(src), user) to_chat(user, span_hierophant_warning("You collect [src], reattaching it to the club!")) club.beacon = null diff --git a/sound/lavaland/hiero_boss.ogg b/sound/lavaland/hiero_boss.ogg new file mode 100644 index 00000000000..23412b5346d Binary files /dev/null and b/sound/lavaland/hiero_boss.ogg differ diff --git a/tgstation.dme b/tgstation.dme index bc9a4c4f2ec..fe67d0a6b32 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -901,6 +901,7 @@ #include "code\datums\components\blood_walk.dm" #include "code\datums\components\bloodysoles.dm" #include "code\datums\components\boomerang.dm" +#include "code\datums\components\boss_music.dm" #include "code\datums\components\bullet_intercepting.dm" #include "code\datums\components\bumpattack.dm" #include "code\datums\components\burning.dm"