News:

One Minute Game Review by The Happy Friar: https://ugetube.com/@OneMinteGameReviews
Also on Rumble: https://rumble.com/c/c-1115371

idTech 4 (aka Doom 3 tech) Discord Server! https://discord.gg/9wtCGHa

Main Menu

How to debug AI scripts?

Started by bitterman, September 19, 2016, 05:45:52 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

bitterman

I looking for more advanced debugging techniques than sys.println when I test custom AI script.

When I see moveStatus as "0" or getPos as "0 0 0" I sure about only one thing - something went wrong.

Now I think about complex script function to dump a debugging info to console/log.

Something like this:



bind R [run 'dump' script]

sys.println [pos, status, etc]


And second question: Is there an AI script events reference (except doom_events.script)?

Thanks.

******************************


extern idCVar ai_debugScript;
extern idCVar ai_debugMove;
extern idCVar ai_debugTrajectory;
extern idCVar ai_testPredictPath;
extern idCVar ai_showCombatNodes;
extern idCVar ai_showPaths;
extern idCVar ai_showObstacleAvoidance;
extern idCVar ai_blockedFailSafe;
extern idCVar ai_showHealth;


idCVar ai_debugScript("ai_debugScript","-1",CVAR_GAME | CVAR_INTEGER, "displays script calls for the specified monster entity number" );
idCVar ai_debugMove("ai_debugMove","0",CVAR_GAME | CVAR_BOOL, "draws movement information for monsters" );
idCVar ai_debugTrajectory("ai_debugTrajectory","0",CVAR_GAME | CVAR_BOOL, "draws trajectory tests for monsters" );
idCVar ai_testPredictPath("ai_testPredictPath","0",CVAR_GAME | CVAR_BOOL, "" );
idCVar ai_showCombatNodes("ai_showCombatNodes","0",CVAR_GAME | CVAR_BOOL, "draws attack cones for monsters" );
idCVar ai_showPaths("ai_showPaths","0",CVAR_GAME | CVAR_BOOL, "draws path_* entities" );
idCVar ai_showObstacleAvoidance("ai_showObstacleAvoidance","0",CVAR_GAME | CVAR_INTEGER, "draws obstacle avoidance information for monsters.  if 2, draws obstacles for player, as well", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
idCVar ai_blockedFailSafe("ai_blockedFailSafe","1",CVAR_GAME | CVAR_BOOL, "enable blocked fail safe handling" );
idCVar ai_showHealth("ai_showHealth","0",CVAR_GAME | CVAR_BOOL, "Draws the AI's health above its head" );



*************************

to examine mecanim

to exam Half-Life AI, Schedules and Tasks

bitterman

#1
Can anyone describe this things and what they doing (in simple words, just for main definition)?

- BecomeSolid/CanBecomeSolid

- FacingIdeal

- AttackCone/CombatCone

- CombatNodes

- ChargeAttack

It's from AI_Events.cpp.

Thanks.

************************

Attack_cone

monster_default.def

"attack_cone" "70"


BielBdeLuna

all those ircc are c++ functions called from script code

facing ideal: there are two facing values the current facing direction and the ideal direction the idAi plans to aim (that is the direction the the enemy, or the direction to the next path target)

combat node: those entities that can be used so enemies display combat animations (firing from behind a box, so crouching and un-crouching from behind it as a protection) an example of this can be the two pistol zombieman in mc_underground after you activate the bridge, the second runs to a box, when he sees the player, in order to hide behind it, and he keeps shooting from behind it

attack cone, is the cone from the monster vision that he uses to determine if the enemy is aligned to the ideal direction or not, and I think combat cone, has to do with the same alignment when the monster is chasing the enemy

become solid/canBecomeSolid is pretty explanatory isn't it? I guess this has to do with corpses (that no longer are solid to the player) or with disappearing enemies like Wraiths

charge attack is any attack the monster runs towards the enemy to perform a melee attack (lost soul fly towards the enemy to hurt him as their charge attack)






bitterman

#3
Yes, thanks.

Not so easy with combat node/attack cone.

ai_attackcone defines in path.def and described as "combat node" (spawnclass idCombatNode).

ai_showCombatNodes shows nothing with monsters but I have an interesting picture:

/*
=====================
idAI::Event_EnemyInCombatCone
=====================
*/
void idAI::Event_EnemyInCombatCone( idEntity *ent, int use_current_enemy_location ) {

idCombatNode *node;
bool result;
idActor *enemyEnt = enemy.GetEntity();
        ...

//Allow the level designers define attack nodes that the enemy should never leave.
//This is different that the turrent type combat nodes because they can play an animation

if(ent->spawnArgs.GetBool("neverLeave", "0")) {
idThread::ReturnInt( true );
return;
}


******************************

Quote from: BielBdeLuna on September 20, 2016, 04:17:29 AM
combat node: those entities that can be used so enemies display combat animations (firing from behind a box, so crouching and un-crouching from behind it as a protection) an example of this can be the two pistol zombieman in mc_underground after you activate the bridge, the second runs to a box, when he sees the player, in order to hide behind it, and he keeps shooting from behind it

That's right, here is fragment from mc_underground.map:

// entity 409
{
"fov" "35"
"min" "256"
"max" "1000"
"height" "256"
"offset" "-64 160 0"
"classname" "ai_attackcone"
"name" "ai_attackcone_1"
"origin" "276 124 0"
"angle" "270"
"min_wait" ".5"
"max_wait" "2"
"anim" "stepoutright"
"num_shots" "6"
}

// entity 410
{
"anim" "step_right"
"classname" "monster_zsec_pistol"
"name" "zsec_bridge"
"origin" "288 124 0"
"angle" "270"
"hide" "2"
"target" "ai_attackcone_1"
"frame" "2"
}


So should I place on map two entity (AI and ai_attackcone) and specify key/val "target" "ai_attackcone" for AI?

Hmm... but how exactly the character/AI will come to this place?

****************************

Perhaps if player touches cone of ai_attackcone (it will change color from red to yellow) then AI/character with this key/val ("target" "ai_attackcone_1") will go to ai_attackcone position and play animation from key "anim".

It should be checked.



bitterman

#4
ai_monster_base.script

/*
=====================
monster_base::combat_attack_cone
=====================
*/
void monster_base::combat_attack_cone( entity node ) {
vector ang;
vector pos;
float min_wait;
float max_wait;
float num_shots;
float wait_end;
float current_time;
float count;
boolean exit;
boolean attack;
boolean do_melee;
boolean dont_wait;
string prefix;

// run to the combat node
run = true;
>>> moveToEntity( node );<<<
while( !AI_MOVE_DONE ) {
if ( AI_ENEMY_IN_FOV ) {
lookAtEnemy( 1 );
}
// exit out if we can't get there or we can do a melee attack
do_melee = testMeleeAttack();
if ( AI_DEST_UNREACHABLE || do_melee || !enemyInCombatCone( node, false ) || AI_ENEMY_DEAD || !node ) {
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
return;
}
waitFrame();
}

if ( !node ) {
// level designers sometimes remove the combat node, so check for it so the thread doesn't get killed
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
return;
}

// set our anim prefix
prefix = node.getKey( "anim" );
if ( prefix == "" ) {
>>> sys.error( "Missing 'anim' key on entity '" + node.getName() + "'" );    <<<<
}
setAnimPrefix( prefix );
>>> checkNodeAnim( node, prefix, "out" ); <<<
checkNodeAnim( node, prefix, "fire" );
checkNodeAnim( node, prefix, "in" );
checkNodeAnim( node, prefix, "wait" );

min_wait = node.getFloatKey( "min_wait" );
max_wait = node.getFloatKey( "max_wait" );
num_shots = node.getFloatKey( "num_shots" );
dont_wait = getIntKey( "wake_on_attackcone" );
if ( dont_wait ) {
setKey( "wake_on_attackcone", "0" );
}


BielBdeLuna

I've never tried the combat nodes extensively, but for what I could gather, you just put them in the map, and the AI script calls a c++ that returns the combat nodes that is closest to the player, it's pretty straight forward, and for what I could see very buggy (animations, and so the monsters) jumped from place to place incorrectly (with jumpy animations, not well blended) when there where too many combat nodes around, I think the combat nodes need to be targeted by the monster in order to get called latter.

combat nodes and path corners can have their own individual animations, so can be used for special case animations