swwmgz_m/zscript/handler/swwm_handler_oneliners.zsc
Marisa the Magician cf17e889d8 Use InterfaceEvents instead of PostUiTick for oneliners, more reliable.
Due to some arbitrary change in GZDoom, which was later merged into VKDoom as
well, PostUiTick no longer consistently gets called after WorldTick.
This is kind of funny and also disappointing and sad because I intentionally
designed that feature this way, on purpose, and now it no longer works as
intended. Who knows how many other mods are affected by this now.
2025-08-21 01:31:55 +02:00

145 lines
5.8 KiB
Text

// oneliner handling
Class LastLine
{
String type;
int lineno;
}
extend Class SWWMHandler
{
transient String oneliner, onelinersnd, onelinertype;
transient int onelinertic, onelinerspan, onelinerlevel;
static int AddOneliner( String type, int level, int delay = 5 )
{
// only Demolitionist can play voice lines
if ( !(players[consoleplayer].mo is 'Demolitionist') )
return 0;
let hnd = SWWMHandler(EventHandler.Find('SWWMHandler'));
if ( !hnd ) return 0;
String voicetype = CVar.FindCVar('swwm_voicetype').GetString();
// suppress non-rage comments when ragekit is active, only screaming allowed
if ( players[consoleplayer].mo.FindInventory('RagekitPower') && (type != "ragekit") ) return 0;
// suppress beep-boop lines if voice channel already in use
if ( ((type == "buttonpush") || (type == "mrtouch") || (type == "mrflick"))
&& players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE)
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/buttonpush1")
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/buttonpush2")
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/buttonpush3")
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/mrtouch1")
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/mrtouch2")
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/mrtouch3")
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/mrtouch4")
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/mrflick1")
&& !players[consoleplayer].mo.IsActorPlayingSound(CHAN_DEMOVOICE,"voice/default/mrflick2") ) return 0;
// check first if it's a multiple option line type
String testme = String.Format("SWWM_SUBS_%s_N%s",voicetype.MakeUpper(),type.MakeUpper());
String locme = StringTable.Localize(testme,false);
if ( testme == locme )
{
// it might be a single option line type
testme = String.Format("SWWM_SUBS_%s_%s",voicetype.MakeUpper(),type.MakeUpper());
locme = StringTable.Localize(testme,false);
if ( testme == locme ) return 0; // nope, the voicepack doesn't have it
hnd.oneliner = String.Format("$SWWM_SUBS_%s_%s",voicetype.MakeUpper(),type.MakeUpper());
hnd.onelinersnd = String.Format("voice/%s/%s",voicetype,type);
hnd.onelinertic = gametic+delay;
hnd.onelinertype = type;
hnd.onelinerspan = int(S_GetLength(hnd.onelinersnd)*GameTicRate);
if ( hnd.onelinerspan == 0 )
{
if ( developer >= 2 ) Console.Printf("No sound for voice line '%s'",type);
hnd.onelinerspan = 35;
}
hnd.onelinerlevel = level;
return hnd.onelinertic+hnd.onelinerspan;
}
int countem = locme.ToInt();
if ( countem == 0 ) return 0; // voicepack doesn't have this
int whichline;
if ( countem == 1 ) whichline = 1; // ez
else
{
bool addme = true;
int idx = -1;
for ( int i=0; i<hnd.gdat.lastlines.Size(); i++ )
{
if ( hnd.gdat.lastlines[i].type != type ) continue;
addme = false;
idx = i;
break;
}
if ( !addme )
{
// clear history up to the last line if full
// this guarantees that there's a non-zero number of candidates
// and that the same line can't happen twice in a row when "looping"
if ( hnd.gdat.lastlines[idx].lines.Size() >= countem )
hnd.gdat.lastlines[idx].lines.Delete(0,hnd.gdat.lastlines[idx].lines.Size()-1);
// check last lines so we don't repeat
Array<int> candidates;
for ( int i=1; i<=countem; i++ )
{
if ( hnd.gdat.lastlines[idx].lines.Find(i) < hnd.gdat.lastlines[idx].lines.Size() )
continue;
candidates.Push(i);
}
whichline = candidates[Random[DemoLines](0,candidates.Size()-1)];
hnd.gdat.lastlines[idx].lines.Push(whichline);
}
else
{
// ez
whichline = Random[DemoLines](1,countem);
let lst = new('OnelinerHistory');
lst.type = type;
lst.lines.Push(whichline);
hnd.gdat.lastlines.Push(lst);
}
}
hnd.oneliner = String.Format("$SWWM_SUBS_%s_%s%d",voicetype.MakeUpper(),type.MakeUpper(),whichline);
hnd.onelinersnd = String.Format("voice/%s/%s%d",voicetype,type,whichline);
hnd.onelinertic = gametic+delay;
hnd.onelinerspan = int(S_GetLength(hnd.onelinersnd)*GameTicRate);
hnd.onelinertype = type;
if ( hnd.onelinerspan == 0 )
{
if ( developer >= 2 ) Console.Printf("No sound for voice line '%s%d'",type,whichline);
hnd.onelinerspan = 35;
}
hnd.onelinerlevel = level;
return hnd.onelinertic+hnd.onelinerspan;
}
static void CancelOneliner( String type )
{
let hnd = SWWMHandler(EventHandler.Find('SWWMHandler'));
if ( !hnd ) return;
if ( (hnd.onelinertype != type) || (hnd.onelinertic < gametic) ) return;
hnd.onelinertic = 0;
hnd.onelinerspan = 0;
}
private void OnelinerTick()
{
if ( !onelinertic || (onelinertic >= gametic) ) return;
if ( players[consoleplayer].health > 0 )
{
if ( onelinerlevel > swwm_mutevoice )
{
int loudlv = swwm_voiceamp;
players[consoleplayer].mo.A_StartSound(onelinersnd,CHAN_DEMOVOICE,CHANF_DEFAULT,1.,ATTN_NONE);
if ( loudlv > 1 ) players[consoleplayer].mo.A_StartSound(onelinersnd,CHAN_DEMOVOICEAUX,CHANF_DEFAULT,1.,ATTN_NONE);
if ( loudlv > 2 ) players[consoleplayer].mo.A_StartSound(onelinersnd,CHAN_DEMOVOICEAUX2,CHANF_DEFAULT,1.,ATTN_NONE);
if ( loudlv > 3 ) players[consoleplayer].mo.A_StartSound(onelinersnd,CHAN_DEMOVOICEAUX3,CHANF_DEFAULT,1.,ATTN_NONE);
}
SendInterfaceEvent(consoleplayer,"swwmmessageliner."..oneliner,onelinerlevel,onelinerspan);
SendNetworkEvent("swwmremoteliner."..onelinersnd,consoleplayer,onelinerlevel);
// hack due to the fact this one can be cancelled early
if ( onelinertype == "falling" ) Demolitionist(players[consoleplayer].mo).facegrin = true;
}
onelinertic = 0;
onelinerspan = 0;
}
}