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.
*/
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.
@ -32,7 +41,7 @@ typedef enumflags
MONFL_CHANGED_FLAGS,
MONFL_CHANGED_SOLID,
MONFL_CHANGED_FRAME,
MONFL_CHANGED_SKIN,
MONFL_CHANGED_SKINHEALTH,
MONFL_CHANGED_MOVETYPE,
MONFL_CHANGED_EFFECTS,
MONFL_CHANGED_BODY,
@ -261,6 +270,9 @@ private:
/* animation cycles */
float m_flAnimTime;
/* timer for keeping track of the target */
float m_flTrackingTime;
PREDICTED_VECTOR_N(view_ofs)
nonvirtual void _LerpTurnToEnemy(float);

View File

@ -23,6 +23,33 @@ NSMonster::NSMonster(void)
remove(this);
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
}
@ -266,7 +293,7 @@ NSMonster::AlertNearby(void)
if (vlen(origin - w.origin) > 512)
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;
/* we shouldn't override this when they already got a target */
@ -302,14 +329,41 @@ NSMonster::IsValidEnemy(entity enny)
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
NSMonster::SeeThink(void)
{
if (m_flAttackThink < time)
if (m_eEnemy) {
/* check if we should invalidate current enemy */
if (IsValidEnemy(m_eEnemy))
return;
if (IsValidEnemy(m_eEnemy)) {
/* only update 1/4th of a second */
if (m_flSeeTime > time)
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 */
RouteClear();
@ -350,15 +404,13 @@ NSMonster::SeeThink(void)
if (flDot < SeeFOV()/180)
continue;
traceline(GetEyePos(), w.origin, MOVE_EVERYTHING, this);
/* 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) {
m_eEnemy = w;
m_flTrackingTime = time;
AlertNearby();
}
return;
}
}
@ -386,8 +438,11 @@ NSMonster::GetRunSpeed(void)
void
NSMonster::_LerpTurnToEnemy(float flSpeed)
{
/* only continue if we're in one of the three states. */
if (GetState() != MONSTER_AIMING)
return;
if (GetState() != MONSTER_CHASING)
if (GetState() != MONSTER_FOLLOWING)
return;
if (!m_eEnemy)
return;
@ -451,7 +506,7 @@ NSMonster::AttackThink(void)
if (GetState() == MONSTER_AIMING) {
int m;
_LerpTurnToEnemy(1000);
_LerpTurnToEnemy(30);
if (MeleeCondition() == TRUE)
m = AttackMelee();
@ -482,14 +537,14 @@ NSMonster::AttackRanged(void)
void
NSMonster::AttackDraw(void)
{
NSLog("^1%s::AttackDraw: Not defined!", classname);
NSMonster_Log("^1%s::AttackDraw: Not defined!", classname);
m_flAttackThink = time + 0.5f;
}
void
NSMonster::AttackHolster(void)
{
NSLog("^1%s::AttackHolster: Not defined!", classname);
NSMonster_Log("^1%s::AttackHolster: Not defined!", classname);
m_flAttackThink = time + 0.5f;
}
@ -526,7 +581,7 @@ NSMonster::FreeState(void)
if (m_iSequenceRemove) {
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
@ -534,7 +589,7 @@ NSMonster::FreeStateMoved(void)
{
vector new_origin;
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);
DropToFloor();
FreeState();
@ -554,13 +609,13 @@ NSMonster::RouteEnded(void)
m_iSequenceState = SEQUENCESTATE_ENDING;
think = (m_iSequenceFlags & SSFL_NOSCRIPTMOVE) ? FreeState : FreeStateMoved;
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);
} else {
/* we still need to trigger targets */
think = (m_iSequenceFlags & SSFL_NOSCRIPTMOVE) ? FreeState : FreeStateMoved;
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);
}
}
@ -674,7 +729,7 @@ NSMonster::IsAlive(void)
void
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);
}
@ -823,7 +878,10 @@ NSMonster::Pain(void)
m_eEnemy = g_dmg_eAttacker;
/* an alert monster will take a while to calm back down */
SetState(MONSTER_ALERT);
if (GetState() != MONSTER_ALERT)
if (GetState() != MONSTER_FOLLOWING)
if (GetState() != MONSTER_CHASING)
SetState(MONSTER_ALERT);
/* alert all nearby friendlies */
AlertNearby();
@ -937,7 +995,8 @@ NSMonster::EvaluateEntity(void)
EVALUATE_VECTOR(maxs, 1, MONFL_CHANGED_SIZE)
EVALUATE_VECTOR(maxs, 2, MONFL_CHANGED_SIZE)
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(m_iBody, MONFL_CHANGED_BODY)
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[2], MONFL_CHANGED_SIZE)
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_BYTE(m_iBody, MONFL_CHANGED_BODY)
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[2], MONFL_CHANGED_SIZE)
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_BYTE(m_iBody, MONFL_CHANGED_BODY)
READENTITY_FLOAT(scale, MONFL_CHANGED_SCALE)
@ -1094,6 +1155,9 @@ NSMonster::_RenderDebugViewCone(void)
float flDot;
vector testOrg;
if (health <= 0 || solid == SOLID_CORPSE)
return;
if (autocvar(r_showViewCone, 0) == 0)
return;

View File

@ -14,6 +14,15 @@
* 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
#define MAX_AMMO_TYPES 16
#endif

View File

@ -107,7 +107,7 @@ NSNavAI::CheckRoute(void)
flDist = floor(vlen(evenpos - origin));
if (flDist < 8) {
NSLog("^2%s::^3CheckRoute^7: " \
NSNavAI_Log("^2%s::^3CheckRoute^7: " \
"%s reached node", classname, targetname);
m_iCurNode--;
velocity = [0,0,0]; /* clamp friction */
@ -119,7 +119,7 @@ NSNavAI::CheckRoute(void)
/* can we walk directly to our target destination? */
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);
m_iCurNode = -1;
}
@ -137,7 +137,7 @@ NSNavAI::CheckRoute(void)
if (!trace_startsolid && trace_fraction == 1.0f) {
evenpos = vecNextNode;
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);
}
}
@ -146,7 +146,7 @@ NSNavAI::CheckRoute(void)
if (m_iCurNode < -1) {
RouteClear();
RouteEnded();
NSLog("^2%s::^3CheckRoute^7: %s reached end", classname, targetname);
NSNavAI_Log("^2%s::^3CheckRoute^7: %s reached end", classname, targetname);
}
/* crouch attempt */
@ -234,11 +234,11 @@ NSNavAI::RouteToPosition(vector destination)
/* can we walk directly to our target destination? */
if (trace_fraction == 1.0) {
NSLog("^2%s::^3RouteToPosition^7: " \
NSNavAI_Log("^2%s::^3RouteToPosition^7: " \
"Walking directly to last node", classname);
p.m_iCurNode = -1;
} else {
NSLog("^2%s::^3RouteToPosition^7: " \
NSNavAI_Log("^2%s::^3RouteToPosition^7: " \
"Path obstructed, calculating route", classname);
/* 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.
*/
#ifdef CLIENT
noref .float health;
#endif
typedef enumflags
{
SRFENT_CHANGED_ORIGIN_X,
@ -47,6 +51,7 @@ private:
float m_flBurnNext;
PREDICTED_FLOAT(armor)
PREDICTED_FLOAT_N(health)
#ifdef SERVER
/* fire/burning */

View File

@ -680,7 +680,8 @@ NSTalkMonster::SendEntity(entity ePEnt, float flChanged)
SENDENTITY_COORD(maxs[1], MONFL_CHANGED_SIZE)
SENDENTITY_COORD(maxs[2], MONFL_CHANGED_SIZE)
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_BYTE(m_iBody, MONFL_CHANGED_BODY)
SENDENTITY_FLOAT(scale, MONFL_CHANGED_SCALE)
@ -732,7 +733,7 @@ NSTalkMonster::ProcessWordQue(void)
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++;
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[2], MONFL_CHANGED_SIZE)
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_BYTE(m_iBody, MONFL_CHANGED_BODY)
READENTITY_FLOAT(scale, MONFL_CHANGED_SCALE)
@ -899,14 +901,14 @@ NSTalkMonster_ParseSentence(void)
if (ent) {
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 {
targ = (NSTalkMonster)ent;
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 {
NSLog("^3 NSTalkMonster_ParseSentence ^7: Entity %d not in PVS", e);
NSMonster_Log("^3 NSTalkMonster_ParseSentence ^7: Entity %d not in PVS", e);
}
}
#endif