scripted_sequence: Improve support for triggering via radius. This gets the retinal scanner type entities working for example.

This commit is contained in:
Marco Cawthorne 2020-09-10 13:36:19 +02:00
parent f4d4e86400
commit 518deec5c6
6 changed files with 100 additions and 51 deletions

View File

@ -339,17 +339,11 @@ CBaseMonster::FreeState(void)
/* trigger when required */
if (m_strRouteEnded) {
CBaseTrigger trigger = 0;
trigger = (CBaseTrigger)find(trigger, ::targetname, m_strRouteEnded);
if (!trigger) {
dprint(sprintf("^1CBaseMonster::^3FreeState^7: %s doesn't exist. Won't trigger\n", m_strRouteEnded));
}
if (trigger.Trigger != __NULL__) {
dprint(sprintf("^2CBaseMonster::^3FreeState^7: %s triggered %f\n", m_strRouteEnded, time));
trigger.Trigger(this, TRIG_TOGGLE);
} else {
dprint(sprintf("^1CBaseMonster::^3FreeState^7: %s not a valid trigger\n", m_strRouteEnded));
for (entity f = world; (f = find(f, ::targetname, m_strRouteEnded));) {
CBaseTrigger trigger = (CBaseTrigger)f;
if (trigger.Trigger != __NULL__) {
trigger.Trigger(this, TRIG_TOGGLE);
}
}
}

View File

@ -445,6 +445,10 @@ CBaseNPC::Physics(void)
input_timelength = frametime;
input_angles = v_angle;
if (m_iSequenceState != SEQUENCESTATE_NONE) {
m_eFollowing = __NULL__;
}
/* override whatever we did above with this */
if (m_iSequenceState == SEQUENCESTATE_ENDING) {
input_angles = v_angle = angles = m_vecSequenceAngle;

View File

@ -45,16 +45,33 @@ class scripted_sentence:CBaseTrigger
void
scripted_sentence::Trigger(entity act, int unused)
{
entity speaker = find(world, ::targetname, m_strSpeaker);
entity spe;
spe = find(world, ::targetname, m_strSpeaker);
if (!speaker) {
if (!spe) {
/* time to look for a classname instead */
float closest = 9999999;
for (entity c = world; (c = find(c, ::classname, m_strSpeaker));) {
float rad;
rad = vlen(origin - c.origin);
/* pick the closest entity */
if (rad < closest) {
spe = c;
closest = rad;
}
}
}
if (!spe) {
print(sprintf("^1scripted_sentence::^3Trigger^7: Couldn't find %s!\n", m_strSpeaker));
return;
}
dprint(sprintf("^2scripted_sentence::^3Trigger^7: %s on %s\n", m_strSentence, m_strSpeaker));
CBaseNPC npc = (CBaseNPC)speaker;
CBaseNPC npc = (CBaseNPC)spe;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_SENTENCE);
WriteEntity(MSG_MULTICAST, npc);

View File

@ -93,46 +93,20 @@ class scripted_sequence:CBaseTrigger
void(void) scripted_sequence;
virtual void(entity, int) Trigger;
virtual void(entity) RunOnEntity;
virtual void(void) InitIdle;
virtual void(void) Respawn;
virtual void(void) touch;
virtual void(string, string) SpawnKey;
};
void
scripted_sequence::Trigger(entity act, int unused)
{
scripted_sequence::RunOnEntity(entity targ)
{
CBaseMonster f;
float duration;
if (!m_iEnabled) {
return;
}
/* aaaaand it's gone */
if (!(spawnflags & SSFL_REPEATABLE)) {
m_iEnabled = FALSE;
}
dprint(sprintf("^2scripted_sequence::^3Trigger^7: with spawnflags %d\n", spawnflags));
f = (CBaseMonster)find(world, ::targetname, m_strMonster);
/* target doesn't exist/hasn't spawned */
if (!f) {
/* time to look for a classname instead */
for (entity c = world; (c = find(c, ::classname, m_strMonster));) {
/* within radius */
if (vlen(origin - c.origin) < m_flSearchRadius) {
f = (CBaseMonster)c;
break;
}
}
/* cancel out. this trigger is broken. */
if (!f) {
dprint(sprintf("^1scripted_sequence::^3Trigger^7: Unknown target %s\n", m_strMonster));
return;
}
}
f = (CBaseMonster)targ;
dprint(sprintf("\tName: %s\n", targetname));
dprint(sprintf("\tTarget: %s\n", m_strMonster));
@ -211,6 +185,40 @@ scripted_sequence::Trigger(entity act, int unused)
dprint(sprintf("\tEnding: %f\n", f.nextthink));
}
void
scripted_sequence::Trigger(entity act, int unused)
{
CBaseMonster f;
if (!m_iEnabled)
return;
dprint(sprintf("^2scripted_sequence::^3Trigger^7: with spawnflags %d\n", spawnflags));
f = (CBaseMonster)find(world, ::targetname, m_strMonster);
/* target doesn't exist/hasn't spawned */
if (!f) {
for (entity c = world; (c = find(c, ::classname, m_strMonster));) {
/* within radius */
if (vlen(origin - c.origin) < m_flSearchRadius) {
f = (CBaseMonster)c;
break;
}
}
/* cancel out. this trigger is not yet ready. */
if (!f) {
return;
}
}
/* aaaaand it's gone */
if (!(spawnflags & SSFL_REPEATABLE))
m_iEnabled = FALSE;
RunOnEntity((entity)f);
}
void
scripted_sequence::InitIdle(void)
{
@ -243,11 +251,36 @@ scripted_sequence::InitIdle(void)
f.m_vecSequenceAngle = angles;
}
void
scripted_sequence::touch(void)
{
if (other.classname != m_strMonster)
return;
if (!m_iEnabled)
return;
/* aaaaand it's gone */
if (!(spawnflags & SSFL_REPEATABLE))
m_iEnabled = FALSE;
RunOnEntity(other);
}
void
scripted_sequence::Respawn(void)
{
m_iEnabled = TRUE;
target = m_oldstrTarget;
if (m_flSearchRadius) {
SetSolid(SOLID_TRIGGER);
mins[0] = mins[1] = mins[2] = -(m_flSearchRadius/2);
maxs[0] = maxs[1] = maxs[2] = (m_flSearchRadius/2);
setsize(this, mins, maxs);
} else {
SetSolid(SOLID_NOT);
}
if (m_strIdleAnim) {
think = InitIdle;
@ -259,9 +292,6 @@ void
scripted_sequence::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "target":
target = strValue;
break;
case "m_iszEntity":
m_strMonster = strValue;
break;
@ -288,7 +318,6 @@ void
scripted_sequence::scripted_sequence(void)
{
CBaseTrigger::CBaseTrigger();
m_oldstrTarget = target;
}
CLASSEXPORT(aiscripted_sequence, scripted_sequence)

View File

@ -50,6 +50,11 @@ trigger_multiple::touch(void)
if (GetMaster() == FALSE)
return;
if (spawnflags & TM_NOCLIENTS && other.flags & FL_CLIENT)
return;
if (!(spawnflags & TM_MONSTERS) && other.flags & FL_MONSTER)
return;
if (Rules_IsTeamPlay() == TRUE) {
if (m_iTeam > 0 && eActivator.team != m_iTeam + 1) {
return;

View File

@ -32,13 +32,13 @@ void GamePMove_Fall(player target, float impactspeed)
#ifdef SERVER
float fFallDamage = (impactspeed - 580) * (100 / (1024 - 580));
Damage_Apply(target, world, fFallDamage, 0, DMG_FALL);
Sound_Play(target, CHAN_AUTO, "player.fall");
Sound_Play(target, CHAN_VOICE, "player.fall");
#endif
target.punchangle += [15,0,(input_sequence & 1) ? 15 : -15];
} else if (impactspeed > 400) {
target.punchangle += [15,0,0];
#ifdef SERVER
Sound_Play(target, CHAN_AUTO, "player.lightfall");
Sound_Play(target, CHAN_VOICE, "player.lightfall");
#endif
}
}