AI: add ai_debugNav, and ai_debugLogic cvars. Add cooldown timer for targets

This commit is contained in:
Marco Cawthorne 2023-05-30 12:06:16 -07:00
parent 3bbeea3343
commit bd7cb44784
Signed by: eukara
GPG key ID: CE2032F0A2882A22
6 changed files with 125 additions and 33 deletions

View file

@ -14,6 +14,15 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
var bool autocvar_ai_debugLogic = false;
void
_NSMonster_Log(string msg)
{
if (autocvar_ai_debugLogic == true)
print(sprintf("%f %s\n", time, msg));
}
#define NSMonster_Log(...) _NSMonster_Log(sprintf(__VA_ARGS__))
/** /**
Bitfield enumeration for NSMonster its SendFlags field. Bitfield enumeration for NSMonster its SendFlags field.
@ -32,7 +41,7 @@ typedef enumflags
MONFL_CHANGED_FLAGS, MONFL_CHANGED_FLAGS,
MONFL_CHANGED_SOLID, MONFL_CHANGED_SOLID,
MONFL_CHANGED_FRAME, MONFL_CHANGED_FRAME,
MONFL_CHANGED_SKIN, MONFL_CHANGED_SKINHEALTH,
MONFL_CHANGED_MOVETYPE, MONFL_CHANGED_MOVETYPE,
MONFL_CHANGED_EFFECTS, MONFL_CHANGED_EFFECTS,
MONFL_CHANGED_BODY, MONFL_CHANGED_BODY,
@ -261,6 +270,9 @@ private:
/* animation cycles */ /* animation cycles */
float m_flAnimTime; float m_flAnimTime;
/* timer for keeping track of the target */
float m_flTrackingTime;
PREDICTED_VECTOR_N(view_ofs) PREDICTED_VECTOR_N(view_ofs)
nonvirtual void _LerpTurnToEnemy(float); nonvirtual void _LerpTurnToEnemy(float);

View file

@ -23,6 +23,33 @@ NSMonster::NSMonster(void)
remove(this); remove(this);
return; return;
} }
m_ssLast = __NULL__;
oldnet_velocity = g_vec_null;
m_flPitch = 1.0f;
m_iFlags = 0i;
base_mins = g_vec_null;
base_maxs = g_vec_null;
base_health = 100;
m_strRouteEnded = __NULL__;
m_iSequenceRemove = 0i;
m_iSequenceState = 0i;
m_flSequenceEnd = 0.0f;
m_flSequenceSpeed = 0.0f;
m_vecSequenceAngle = g_vec_null;
m_iSequenceFlags = 0i;
m_iMoveState = 0i;
m_iTriggerCondition = 0i;
m_strTriggerTarget = __NULL__;
m_flBaseTime = 0.0f;
m_eEnemy = __NULL__;
m_flAttackThink = 0.0f;
m_iMState = 0i;
m_iOldMState = 0i;
m_vecLKPos = g_vec_null;
m_flSeeTime = 0.0f;
m_flAnimTime = 0.0f;
m_flTrackingTime = 0.0f;
#endif #endif
} }
@ -266,7 +293,7 @@ NSMonster::AlertNearby(void)
if (vlen(origin - w.origin) > 512) if (vlen(origin - w.origin) > 512)
continue; continue;
//NSLog("Alert! %s get %s", w.classname, m_eEnemy.classname); //NSMonster_Log("Alert! %s get %s", w.classname, m_eEnemy.classname);
NSMonster f = (NSMonster)w; NSMonster f = (NSMonster)w;
/* we shouldn't override this when they already got a target */ /* we shouldn't override this when they already got a target */
@ -302,15 +329,42 @@ NSMonster::IsValidEnemy(entity enny)
return TRUE; return TRUE;
} }
static bool
NSMonster_TraceAgainsTarget(NSMonster monster, NSEntity target)
{
traceline(monster.GetEyePos(), target.GetOrigin(), MOVE_NORMAL, monster);
/* we have line of sight with the player */
if (trace_fraction == 1.0f || trace_ent == target) {
return true;
}
return false;
}
void void
NSMonster::SeeThink(void) NSMonster::SeeThink(void)
{ {
if (m_flAttackThink < time) if (m_flAttackThink < time)
if (m_eEnemy) { if (m_eEnemy) {
/* check if we should invalidate current enemy */ /* check if we should invalidate current enemy */
if (IsValidEnemy(m_eEnemy)) if (IsValidEnemy(m_eEnemy)) {
/* only update 1/4th of a second */
if (m_flSeeTime > time)
return; return;
m_flSeeTime = time + 0.25f;
/* see if we can trace our target, if yes, update our timestamp */
if (NSMonster_TraceAgainsTarget(this, (NSEntity) m_eEnemy) == true) {
m_flTrackingTime = time;
}
/* if we haven't gotten a trace in 5 seconds, give up. */
if ((m_flTrackingTime + 5.0) > time)
return;
}
/* enemy is not valid anymore, reset it, clear route and search for new enemy */ /* enemy is not valid anymore, reset it, clear route and search for new enemy */
RouteClear(); RouteClear();
@ -350,15 +404,13 @@ NSMonster::SeeThink(void)
if (flDot < SeeFOV()/180) if (flDot < SeeFOV()/180)
continue; continue;
traceline(GetEyePos(), w.origin, MOVE_EVERYTHING, this);
/* we have line of sight with the player */ /* we have line of sight with the player */
if (trace_fraction == 1.0f || trace_ent == w) { if (NSMonster_TraceAgainsTarget(this, (NSEntity)w) == true) {
if (m_eEnemy != w) { if (m_eEnemy != w) {
m_eEnemy = w; m_eEnemy = w;
m_flTrackingTime = time;
AlertNearby(); AlertNearby();
} }
return; return;
} }
} }
@ -386,7 +438,10 @@ NSMonster::GetRunSpeed(void)
void void
NSMonster::_LerpTurnToEnemy(float flSpeed) NSMonster::_LerpTurnToEnemy(float flSpeed)
{ {
/* only continue if we're in one of the three states. */
if (GetState() != MONSTER_AIMING) if (GetState() != MONSTER_AIMING)
if (GetState() != MONSTER_CHASING)
if (GetState() != MONSTER_FOLLOWING)
return; return;
if (!m_eEnemy) if (!m_eEnemy)
@ -451,7 +506,7 @@ NSMonster::AttackThink(void)
if (GetState() == MONSTER_AIMING) { if (GetState() == MONSTER_AIMING) {
int m; int m;
_LerpTurnToEnemy(1000); _LerpTurnToEnemy(30);
if (MeleeCondition() == TRUE) if (MeleeCondition() == TRUE)
m = AttackMelee(); m = AttackMelee();
@ -482,14 +537,14 @@ NSMonster::AttackRanged(void)
void void
NSMonster::AttackDraw(void) NSMonster::AttackDraw(void)
{ {
NSLog("^1%s::AttackDraw: Not defined!", classname); NSMonster_Log("^1%s::AttackDraw: Not defined!", classname);
m_flAttackThink = time + 0.5f; m_flAttackThink = time + 0.5f;
} }
void void
NSMonster::AttackHolster(void) NSMonster::AttackHolster(void)
{ {
NSLog("^1%s::AttackHolster: Not defined!", classname); NSMonster_Log("^1%s::AttackHolster: Not defined!", classname);
m_flAttackThink = time + 0.5f; m_flAttackThink = time + 0.5f;
} }
@ -526,7 +581,7 @@ NSMonster::FreeState(void)
if (m_iSequenceRemove) { if (m_iSequenceRemove) {
Hide(); Hide();
} }
NSLog("^2%s::^3FreeState^7: (%i, %S)", classname, m_iSequenceRemove, to_trigger); NSMonster_Log("^2%s::^3FreeState^7: (%i, %S)", classname, m_iSequenceRemove, to_trigger);
} }
void void
@ -534,7 +589,7 @@ NSMonster::FreeStateMoved(void)
{ {
vector new_origin; vector new_origin;
new_origin = gettaginfo(this, 1); new_origin = gettaginfo(this, 1);
NSLog("^2%s::^3FreeStateMoved^7: moved to %v", classname, new_origin); NSMonster_Log("^2%s::^3FreeStateMoved^7: moved to %v", classname, new_origin);
SetOrigin(new_origin); SetOrigin(new_origin);
DropToFloor(); DropToFloor();
FreeState(); FreeState();
@ -554,13 +609,13 @@ NSMonster::RouteEnded(void)
m_iSequenceState = SEQUENCESTATE_ENDING; m_iSequenceState = SEQUENCESTATE_ENDING;
think = (m_iSequenceFlags & SSFL_NOSCRIPTMOVE) ? FreeState : FreeStateMoved; think = (m_iSequenceFlags & SSFL_NOSCRIPTMOVE) ? FreeState : FreeStateMoved;
nextthink = time + duration; nextthink = time + duration;
NSLog("^2%s::^3CheckRoute^7: %s overriding anim for %f seconds (modelindex %d, frame %d)", \ NSMonster_Log("^2%s::^3CheckRoute^7: %s overriding anim for %f seconds (modelindex %d, frame %d)", \
classname, this.targetname, duration, modelindex, m_flSequenceEnd); classname, this.targetname, duration, modelindex, m_flSequenceEnd);
} else { } else {
/* we still need to trigger targets */ /* we still need to trigger targets */
think = (m_iSequenceFlags & SSFL_NOSCRIPTMOVE) ? FreeState : FreeStateMoved; think = (m_iSequenceFlags & SSFL_NOSCRIPTMOVE) ? FreeState : FreeStateMoved;
nextthink = time; nextthink = time;
NSLog("^2%s::^3CheckRoute^7: %s has no anim, finished sequence", \ NSMonster_Log("^2%s::^3CheckRoute^7: %s has no anim, finished sequence", \
classname, this.targetname); classname, this.targetname);
} }
} }
@ -674,7 +729,7 @@ NSMonster::IsAlive(void)
void void
NSMonster::StateChanged(monsterState_t oldState, monsterState_t newState) NSMonster::StateChanged(monsterState_t oldState, monsterState_t newState)
{ {
NSLog("^2%s::^3StateChanged^7: state changed from %d to %d", \ NSMonster_Log("^2%s::^3StateChanged^7: state changed from %d to %d", \
classname, oldState, newState); classname, oldState, newState);
} }
@ -823,6 +878,9 @@ NSMonster::Pain(void)
m_eEnemy = g_dmg_eAttacker; m_eEnemy = g_dmg_eAttacker;
/* an alert monster will take a while to calm back down */ /* an alert monster will take a while to calm back down */
if (GetState() != MONSTER_ALERT)
if (GetState() != MONSTER_FOLLOWING)
if (GetState() != MONSTER_CHASING)
SetState(MONSTER_ALERT); SetState(MONSTER_ALERT);
/* alert all nearby friendlies */ /* alert all nearby friendlies */
@ -937,7 +995,8 @@ NSMonster::EvaluateEntity(void)
EVALUATE_VECTOR(maxs, 1, MONFL_CHANGED_SIZE) EVALUATE_VECTOR(maxs, 1, MONFL_CHANGED_SIZE)
EVALUATE_VECTOR(maxs, 2, MONFL_CHANGED_SIZE) EVALUATE_VECTOR(maxs, 2, MONFL_CHANGED_SIZE)
EVALUATE_FIELD(frame, MONFL_CHANGED_FRAME) EVALUATE_FIELD(frame, MONFL_CHANGED_FRAME)
EVALUATE_FIELD(skin, MONFL_CHANGED_SKIN) EVALUATE_FIELD(skin, MONFL_CHANGED_SKINHEALTH)
EVALUATE_FIELD(health, MONFL_CHANGED_SKINHEALTH)
EVALUATE_FIELD(effects, MONFL_CHANGED_EFFECTS) EVALUATE_FIELD(effects, MONFL_CHANGED_EFFECTS)
EVALUATE_FIELD(m_iBody, MONFL_CHANGED_BODY) EVALUATE_FIELD(m_iBody, MONFL_CHANGED_BODY)
EVALUATE_FIELD(scale, MONFL_CHANGED_SCALE) EVALUATE_FIELD(scale, MONFL_CHANGED_SCALE)
@ -985,7 +1044,8 @@ NSMonster::SendEntity(entity ePEnt, float flChanged)
SENDENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE) SENDENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE)
SENDENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE) SENDENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE)
SENDENTITY_BYTE(frame, MONFL_CHANGED_FRAME) SENDENTITY_BYTE(frame, MONFL_CHANGED_FRAME)
SENDENTITY_FLOAT(skin, MONFL_CHANGED_SKIN) SENDENTITY_FLOAT(skin, MONFL_CHANGED_SKINHEALTH)
SENDENTITY_FLOAT(health, MONFL_CHANGED_SKINHEALTH)
SENDENTITY_FLOAT(effects, MONFL_CHANGED_EFFECTS) SENDENTITY_FLOAT(effects, MONFL_CHANGED_EFFECTS)
SENDENTITY_BYTE(m_iBody, MONFL_CHANGED_BODY) SENDENTITY_BYTE(m_iBody, MONFL_CHANGED_BODY)
SENDENTITY_FLOAT(scale, MONFL_CHANGED_SCALE) SENDENTITY_FLOAT(scale, MONFL_CHANGED_SCALE)
@ -1060,7 +1120,8 @@ NSMonster::ReceiveEntity(float flNew, float flChanged)
READENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE) READENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE)
READENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE) READENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE)
READENTITY_BYTE(frame, MONFL_CHANGED_FRAME) READENTITY_BYTE(frame, MONFL_CHANGED_FRAME)
READENTITY_FLOAT(skin, MONFL_CHANGED_SKIN) READENTITY_FLOAT(skin, MONFL_CHANGED_SKINHEALTH)
READENTITY_FLOAT(health, MONFL_CHANGED_SKINHEALTH)
READENTITY_FLOAT(effects, MONFL_CHANGED_EFFECTS) READENTITY_FLOAT(effects, MONFL_CHANGED_EFFECTS)
READENTITY_BYTE(m_iBody, MONFL_CHANGED_BODY) READENTITY_BYTE(m_iBody, MONFL_CHANGED_BODY)
READENTITY_FLOAT(scale, MONFL_CHANGED_SCALE) READENTITY_FLOAT(scale, MONFL_CHANGED_SCALE)
@ -1094,6 +1155,9 @@ NSMonster::_RenderDebugViewCone(void)
float flDot; float flDot;
vector testOrg; vector testOrg;
if (health <= 0 || solid == SOLID_CORPSE)
return;
if (autocvar(r_showViewCone, 0) == 0) if (autocvar(r_showViewCone, 0) == 0)
return; return;

View file

@ -14,6 +14,15 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
var bool autocvar_ai_debugNav = false;
void
_NSNavAI_Log(string msg)
{
if (autocvar_ai_debugNav == true)
print(sprintf("%f %s\n", time, msg));
}
#define NSNavAI_Log(...) _NSNavAI_Log(sprintf(__VA_ARGS__))
#ifndef MAX_AMMO_TYPES #ifndef MAX_AMMO_TYPES
#define MAX_AMMO_TYPES 16 #define MAX_AMMO_TYPES 16
#endif #endif

View file

@ -107,7 +107,7 @@ NSNavAI::CheckRoute(void)
flDist = floor(vlen(evenpos - origin)); flDist = floor(vlen(evenpos - origin));
if (flDist < 8) { if (flDist < 8) {
NSLog("^2%s::^3CheckRoute^7: " \ NSNavAI_Log("^2%s::^3CheckRoute^7: " \
"%s reached node", classname, targetname); "%s reached node", classname, targetname);
m_iCurNode--; m_iCurNode--;
velocity = [0,0,0]; /* clamp friction */ velocity = [0,0,0]; /* clamp friction */
@ -119,7 +119,7 @@ NSNavAI::CheckRoute(void)
/* can we walk directly to our target destination? */ /* can we walk directly to our target destination? */
if (trace_fraction == 1.0) { if (trace_fraction == 1.0) {
NSLog("^2%s::^3CheckRoute^7: Walking directly to last node at '%v'", \ NSNavAI_Log("^2%s::^3CheckRoute^7: Walking directly to last node at '%v'", \
classname, m_vecLastNode); classname, m_vecLastNode);
m_iCurNode = -1; m_iCurNode = -1;
} }
@ -137,7 +137,7 @@ NSNavAI::CheckRoute(void)
if (!trace_startsolid && trace_fraction == 1.0f) { if (!trace_startsolid && trace_fraction == 1.0f) {
evenpos = vecNextNode; evenpos = vecNextNode;
m_iCurNode = iNextNode; m_iCurNode = iNextNode;
NSLog("^2%s::^3CheckRoute^7: skipping to next node %i at '%v'", \ NSNavAI_Log("^2%s::^3CheckRoute^7: skipping to next node %i at '%v'", \
classname, iNextNode, vecNextNode); classname, iNextNode, vecNextNode);
} }
} }
@ -146,7 +146,7 @@ NSNavAI::CheckRoute(void)
if (m_iCurNode < -1) { if (m_iCurNode < -1) {
RouteClear(); RouteClear();
RouteEnded(); RouteEnded();
NSLog("^2%s::^3CheckRoute^7: %s reached end", classname, targetname); NSNavAI_Log("^2%s::^3CheckRoute^7: %s reached end", classname, targetname);
} }
/* crouch attempt */ /* crouch attempt */
@ -234,11 +234,11 @@ NSNavAI::RouteToPosition(vector destination)
/* can we walk directly to our target destination? */ /* can we walk directly to our target destination? */
if (trace_fraction == 1.0) { if (trace_fraction == 1.0) {
NSLog("^2%s::^3RouteToPosition^7: " \ NSNavAI_Log("^2%s::^3RouteToPosition^7: " \
"Walking directly to last node", classname); "Walking directly to last node", classname);
p.m_iCurNode = -1; p.m_iCurNode = -1;
} else { } else {
NSLog("^2%s::^3RouteToPosition^7: " \ NSNavAI_Log("^2%s::^3RouteToPosition^7: " \
"Path obstructed, calculating route", classname); "Path obstructed, calculating route", classname);
/* run through all nodes, mark the closest direct path possible */ /* run through all nodes, mark the closest direct path possible */

View file

@ -14,6 +14,10 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifdef CLIENT
noref .float health;
#endif
typedef enumflags typedef enumflags
{ {
SRFENT_CHANGED_ORIGIN_X, SRFENT_CHANGED_ORIGIN_X,
@ -47,6 +51,7 @@ private:
float m_flBurnNext; float m_flBurnNext;
PREDICTED_FLOAT(armor) PREDICTED_FLOAT(armor)
PREDICTED_FLOAT_N(health)
#ifdef SERVER #ifdef SERVER
/* fire/burning */ /* fire/burning */

View file

@ -680,7 +680,8 @@ NSTalkMonster::SendEntity(entity ePEnt, float flChanged)
SENDENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE) SENDENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE)
SENDENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE) SENDENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE)
SENDENTITY_BYTE(frame, MONFL_CHANGED_FRAME) SENDENTITY_BYTE(frame, MONFL_CHANGED_FRAME)
SENDENTITY_FLOAT(skin, MONFL_CHANGED_SKIN) SENDENTITY_FLOAT(skin, MONFL_CHANGED_SKINHEALTH)
SENDENTITY_FLOAT(health, MONFL_CHANGED_SKINHEALTH)
SENDENTITY_FLOAT(effects, MONFL_CHANGED_EFFECTS) SENDENTITY_FLOAT(effects, MONFL_CHANGED_EFFECTS)
SENDENTITY_BYTE(m_iBody, MONFL_CHANGED_BODY) SENDENTITY_BYTE(m_iBody, MONFL_CHANGED_BODY)
SENDENTITY_FLOAT(scale, MONFL_CHANGED_SCALE) SENDENTITY_FLOAT(scale, MONFL_CHANGED_SCALE)
@ -732,7 +733,7 @@ NSTalkMonster::ProcessWordQue(void)
SentenceSample(m_pSentenceQue[m_iSentencePos].m_strSnd); SentenceSample(m_pSentenceQue[m_iSentencePos].m_strSnd);
NSLog("^2NSEntity::^3ProcessWordQue^7: Speaking %s", m_pSentenceQue[m_iSentencePos].m_strSnd); NSMonster_Log("^2NSEntity::^3ProcessWordQue^7: Speaking %s", m_pSentenceQue[m_iSentencePos].m_strSnd);
m_iSentencePos++; m_iSentencePos++;
if (m_iSentencePos == m_iSentenceCount) { if (m_iSentencePos == m_iSentenceCount) {
@ -856,7 +857,8 @@ NSTalkMonster::ReceiveEntity(float flNew, float flChanged)
READENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE) READENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE)
READENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE) READENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE)
READENTITY_BYTE(frame, MONFL_CHANGED_FRAME) READENTITY_BYTE(frame, MONFL_CHANGED_FRAME)
READENTITY_FLOAT(skin, MONFL_CHANGED_SKIN) READENTITY_FLOAT(skin, MONFL_CHANGED_SKINHEALTH)
READENTITY_FLOAT(health, MONFL_CHANGED_SKINHEALTH)
READENTITY_FLOAT(effects, MONFL_CHANGED_EFFECTS) READENTITY_FLOAT(effects, MONFL_CHANGED_EFFECTS)
READENTITY_BYTE(m_iBody, MONFL_CHANGED_BODY) READENTITY_BYTE(m_iBody, MONFL_CHANGED_BODY)
READENTITY_FLOAT(scale, MONFL_CHANGED_SCALE) READENTITY_FLOAT(scale, MONFL_CHANGED_SCALE)
@ -899,14 +901,14 @@ NSTalkMonster_ParseSentence(void)
if (ent) { if (ent) {
if (ent.classname != "NSTalkMonster" && ent.classname != "ambient_generic") if (ent.classname != "NSTalkMonster" && ent.classname != "ambient_generic")
NSLog("^3 NSTalkMonster_ParseSentence ^7: Entity %d not a NSTalkMonster!", e); NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d not a NSTalkMonster!", e);
else { else {
targ = (NSTalkMonster)ent; targ = (NSTalkMonster)ent;
targ.Sentence(sentence); targ.Sentence(sentence);
NSLog("^3 NSTalkMonster_ParseSentence ^7: Entity %d saying %s", e, sentence); NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d saying %s", e, sentence);
} }
} else { } else {
NSLog("^3 NSTalkMonster_ParseSentence ^7: Entity %d not in PVS", e); NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d not in PVS", e);
} }
} }
#endif #endif