From 72e5c6f2efddd77471a3de15680df34e4a91b874 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Sat, 29 Aug 2020 00:07:53 +0200 Subject: [PATCH] random_speaker: Initial implementation. This entity appears in Gunman Chronicles. --- src/gs-entbase/server.src | 1 + src/gs-entbase/server/random_speaker.cpp | 148 +++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 src/gs-entbase/server/random_speaker.cpp diff --git a/src/gs-entbase/server.src b/src/gs-entbase/server.src index cd71a9da..d09d9e0f 100644 --- a/src/gs-entbase/server.src +++ b/src/gs-entbase/server.src @@ -85,6 +85,7 @@ server/monster_furniture.cpp server/monster_generic.cpp server/monstermaker.cpp server/multisource.cpp +server/random_speaker.cpp server/scripted_sentence.cpp server/scripted_sequence.cpp #endlist diff --git a/src/gs-entbase/server/random_speaker.cpp b/src/gs-entbase/server/random_speaker.cpp new file mode 100644 index 00000000..052ca970 --- /dev/null +++ b/src/gs-entbase/server/random_speaker.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*QUAKED random_speaker (1 0 0) (-8 -8 -8) (8 8 8) +"targetname" Name +"target" Target when triggered +"killtarget" Target to kill when triggered +"rsnoise" Path to the sound file +"volume" Volume to play the sound as (normalized, 0.0 - 1.0) +"wait" Minimum time for sound repetition in % +"random" Random % of this added to wait + +This entity plays a .wav file at random intervals. + +To explain the math behind it: +The 'wait' key specifies the minimum time it waits to play itself again, +however we always add a bit of a random interval on top. +The random interval is a set percentage of the specified 'wait' time. +For example, if 'wait' is 10 and 'random' is 50, then it'll always be +a random interval between 10 and 15 seconds in total. + +Trivia: +It was introduced in Gunman Chronicles. +*/ + +class random_speaker:CBaseTrigger +{ + string m_strSample; + float m_flVolume; + float m_flMinPos; + float m_flRandPercent; + + void(void) random_speaker; + + virtual void(entity,int) Trigger; + virtual void(void) Respawn; + virtual void(void) PlaySample; + virtual void(void) Enable; + virtual void(void) Disable; +}; + +void +random_speaker::PlaySample(void) +{ + sound(this, CHAN_VOICE, m_strSample, m_flVolume, ATTN_NONE); + + /* cue the next time we're playing this sample */ + Enable(); +} + +void +random_speaker::Enable(void) +{ + float r; + + m_iValue = 1; + + /* at least wait this amount */ + r = time + m_flMinPos; + + /* then take the specified percentage of 'wait', by random and add it */ + r += (m_flMinPos * (m_flRandPercent / 100)) * random(); + + think = PlaySample; + nextthink = r; + + print("^2random_speaker::^3Disable^7: " \ + "%s playing %s in %d\n", \ + m_strTargetName, m_strSample, r); +} + +void +random_speaker::Disable(void) +{ + dprint("^2random_speaker::^3Disable^7: " \ + "Disabled %s playing %s\n", \ + m_strTargetName, m_strSample); + + m_iValue = 0; + think = __NULL__; + nextthink = 0; +} + +void +random_speaker::Trigger(entity act, int state) +{ + if (GetMaster() == FALSE) + return; + + switch (state) { + case TRIG_OFF: + Disable(); + break; + case TRIG_ON: + Enable(); + break; + default: + if (m_iValue) + Trigger(act, TRIG_OFF); + else + Trigger(act, TRIG_ON); + } + +} + +void +random_speaker::Respawn(void) +{ + Disable(); +} + +void +random_speaker::random_speaker(void) +{ + for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { + case "rsnoise": + m_strSample = argv(i+1); + break; + case "volume": + m_flVolume = stof(argv(i+1)); + break; + case "wait": + m_flMinPos = stof(argv(i+1)); + break; + case "random": + m_flRandPercent = stof(argv(i+1)); + break; + default: + break; + } + } + + CBaseTrigger::CBaseTrigger(); +}