Skip to content

Commit 9a6d44a

Browse files
committed
JABot improvements. Bot gets angry when hurt, and will chase an enemy across the map until it is dead. Bot will use tball self to teleport away when its health is critically low.
1 parent 5ecc937 commit 9a6d44a

File tree

7 files changed

+78
-21
lines changed

7 files changed

+78
-21
lines changed

src/ai/ai.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,7 @@ void debug_printf(char *fmt, ...);
132132
void safe_cprintf (edict_t *ent, int printlevel, char *fmt, ...);
133133
void safe_centerprintf (edict_t *ent, char *fmt, ...);
134134
void safe_bprintf (int printlevel, char *fmt, ...);
135-
void AI_DebugPrintf(char* fmt, ...);//GHz
135+
void AI_DebugPrintf(char* fmt, ...);//GHz
136+
137+
//ai_class_dmbot.c
138+
void BOT_DMclass_Pain(edict_t* self, edict_t* other, float kick, int damage);//GHz

src/ai/ai_class_dmbot.c

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ void BOT_DMclass_Move(edict_t *self, usercmd_t *ucmd)
105105
// Falling off ledge
106106
if(!self->groundentity && !self->ai.is_step && !self->ai.is_swim )
107107
{
108-
gi.dprintf("falling off a ledge...\n");
108+
//gi.dprintf("falling off a ledge...\n");
109109
AI_ChangeAngle(self);
110110
if (current_link_type == LINK_JUMPPAD ) {
111111
//gi.dprintf("walk forward\n");
@@ -127,7 +127,7 @@ void BOT_DMclass_Move(edict_t *self, usercmd_t *ucmd)
127127
{
128128
trace_t trace;
129129
vec3_t v1, v2;
130-
gi.dprintf("jumping over\n");
130+
//gi.dprintf("jumping over\n");
131131
//check floor in front, if there's none... Jump!
132132
VectorCopy( self->s.origin, v1 );
133133
VectorCopy( self->ai.move_vector, v2 );
@@ -137,7 +137,7 @@ void BOT_DMclass_Move(edict_t *self, usercmd_t *ucmd)
137137
trace = gi.trace( v1, tv(-2, -2, -AI_JUMPABLE_HEIGHT), tv(2, 2, 0), v1, self, MASK_AISOLID );
138138
if( !trace.startsolid && trace.fraction == 1.0 )
139139
{
140-
gi.dprintf("jump!\n");
140+
//gi.dprintf("jump!\n");
141141
//jump!
142142
ucmd->forwardmove = 400;
143143
//prevent double jumping on crates
@@ -315,6 +315,20 @@ void BOT_DMclass_CombatMovement( edict_t *self, usercmd_t *ucmd )
315315

316316
AI_DebugPrintf("BOT_DMclass_CombatMovement()\n");
317317

318+
//if (CanTball(self, false))
319+
// gi.dprintf("bot can tball\n");
320+
//gi.dprintf("bot has %d tballs\n", self->client->pers.inventory[ITEM_INDEX(Fdi_TBALL)]);
321+
//GHz: health critically low and have a tball?
322+
if (self->health <= 0.2 * self->max_health && CanTball(self, false) && self->client->pers.inventory[ITEM_INDEX(Fdi_TBALL)])
323+
{
324+
//gi.dprintf("bot tried to tball\n");
325+
// use tball to teleport away!
326+
self->client->pers.inventory[ITEM_INDEX(Fdi_TBALL)]--;
327+
Tball_Aura(self, self->s.origin);
328+
// if we were angry at someone, forget it so that we can focus on rearming/healing
329+
self->enemy = NULL;
330+
}
331+
318332
if(!self->enemy) {
319333

320334
//do whatever (tmp move wander)
@@ -387,7 +401,7 @@ qboolean BOT_DMclass_FindEnemy(edict_t* self)
387401
vec3_t dist;
388402

389403
// we already set up an enemy this frame (reacting to attacks)
390-
if (self->enemy != NULL)
404+
if (self->enemy && self->enemy->inuse && visible(self, self->enemy))//GHz: don't bother finding a new enemy if the last one is still visible
391405
return true;
392406

393407
if (level.time < pregame_time->value) // No enemies in pregame lol
@@ -779,8 +793,15 @@ void BOT_DMclass_WeightPlayers(edict_t *self)
779793
}
780794
}
781795
}
782-
else //if not at ctf every player has some value
783-
self->ai.status.playersWeights[i] = 0.3;
796+
else
797+
{
798+
// GHz: chase enemies!
799+
if (self->enemy && self->enemy->inuse && AIEnemies[i] == self->enemy)
800+
self->ai.status.playersWeights[i] = 0.9;
801+
else
802+
//if not at ctf every player has some value
803+
self->ai.status.playersWeights[i] = 0.3;
804+
}
784805

785806
}
786807
}
@@ -971,7 +992,8 @@ void BOT_DMclass_UpdateStatus( edict_t *self )
971992
{
972993
AI_DebugPrintf("BOT_DMclass_UpdateStatus()\n");
973994

974-
self->enemy = NULL;
995+
if (!G_EntIsAlive(self->enemy))//GHz: stay angry at this entity--used for LR goal setting
996+
self->enemy = NULL;
975997
self->movetarget = NULL;
976998

977999
// Set up for new client movement: jalfixme
@@ -1146,4 +1168,33 @@ void BOT_DMclass_InitPersistant(edict_t *self)
11461168
}
11471169
}
11481170

1171+
//==========================================
1172+
// BOT_DMclass_Pain
1173+
//==========================================
1174+
qboolean CanTball(edict_t* ent, qboolean print);
1175+
void BOT_DMclass_Pain(edict_t* self, edict_t* other, float kick, int damage)
1176+
{
1177+
if (!self->ai.is_bot)
1178+
return;
1179+
if (!G_EntIsAlive(other))
1180+
return;
1181+
if (other->flags & FL_GODMODE)
1182+
return;
1183+
if (OnSameTeam(self, other))
1184+
return;
1185+
1186+
self->enemy = other;
11491187

1188+
if (AIDevel.debugChased && bot_showcombat->value)
1189+
{
1190+
if (other->ai.is_bot)
1191+
safe_cprintf(AIDevel.chaseguy, PRINT_HIGH, "%s: is angry at %s!\n",
1192+
self->ai.pers.netname, other->ai.pers.netname);
1193+
else if (other->client)
1194+
safe_cprintf(AIDevel.chaseguy, PRINT_HIGH, "%s: is angry at %s!\n",
1195+
self->ai.pers.netname, other->client->pers.netname);
1196+
else
1197+
safe_cprintf(AIDevel.chaseguy, PRINT_HIGH, "%s: is angry at %s!\n",
1198+
self->ai.pers.netname, other->classname);
1199+
}
1200+
}

src/ai/ai_main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,13 +298,15 @@ void AI_PickLongRangeGoal(edict_t *self)
298298

299299
if(cost == INVALID || cost < 4) // ignore invalid and very short hops
300300
continue;
301-
301+
302302
//precomputed player weights
303303
weight = self->ai.status.playersWeights[i];
304304

305305
//weight *= random(); // Allow random variations
306306
weight /= cost; // Check against cost of getting there
307307

308+
//gi.dprintf("LR enemy goal %s weight %f\n", AIEnemies[i]->classname, weight);
309+
308310
if(weight > best_weight)
309311
{
310312
best_weight = weight;
@@ -333,7 +335,7 @@ void AI_PickLongRangeGoal(edict_t *self)
333335
self->ai.tries = 0; // Reset the count of how many times we tried this goal
334336

335337
if(goal_ent != NULL && AIDevel.debugChased && bot_showlrgoal->value)
336-
safe_cprintf(AIDevel.chaseguy, PRINT_HIGH, "%s: selected a %s at node %d for LR goal.\n",self->ai.pers.netname, goal_ent->classname, goal_node);
338+
safe_cprintf(AIDevel.chaseguy, PRINT_HIGH, "%s: selected %s (wt %f) @ node %d for LR goal.\n",self->ai.pers.netname, goal_ent->classname, best_weight, goal_node);
337339

338340
AI_SetGoal(self,goal_node, true);
339341
}

src/ai/ai_movement.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@ qboolean AI_CanMove1(edict_t *self, int direction)
127127
{
128128
if (tr.ent->takedamage && tr.ent->solid != SOLID_NOT)
129129
self->enemy = tr.ent;
130-
gi.dprintf("blocked1\n");
130+
//gi.dprintf("blocked1\n");
131131
return false;
132132
}
133133
if(tr.fraction != 1.0 || tr.contents & (CONTENTS_SOLID))
134134
{
135-
gi.dprintf("blocked2\n");
135+
//gi.dprintf("blocked2\n");
136136
return false;
137137
}
138138

@@ -275,7 +275,7 @@ qboolean AI_SpecialMove(edict_t *self, usercmd_t *ucmd)
275275
tr = gi.trace( self->s.origin, self->mins, self->maxs, boxorigin, self, MASK_AISOLID);
276276
if (!tr.startsolid && tr.fraction == 1.0) // not bloqued
277277
{
278-
gi.dprintf("not blocked?\n");
278+
//gi.dprintf("not blocked?\n");
279279
return false;
280280
}
281281

@@ -314,7 +314,7 @@ qboolean AI_SpecialMove(edict_t *self, usercmd_t *ucmd)
314314
tr = gi.trace( boxorigin, boxmins, boxmaxs, boxorigin, self, MASK_AISOLID);
315315
if( !tr.startsolid ) //can move by jumping
316316
{
317-
gi.dprintf("can move by jumping\n");
317+
//gi.dprintf("can move by jumping\n");
318318
ucmd->forwardmove = 400;
319319
ucmd->upmove = 400;
320320

@@ -430,7 +430,7 @@ qboolean AI_MoveToGoalEntity(edict_t *self, usercmd_t *ucmd)
430430
}
431431

432432
AI_DebugPrintf("AI_MoveToGoalEntity()\n");
433-
gi.dprintf("movetarget: %s\n", self->movetarget->classname);
433+
//gi.dprintf("movetarget: %s\n", self->movetarget->classname);
434434

435435
// If a rocket or grenade is around deal with it
436436
// Simple, but effective (could be rewritten to be more accurate)
@@ -457,7 +457,7 @@ qboolean AI_MoveToGoalEntity(edict_t *self, usercmd_t *ucmd)
457457
AI_ChangeAngle(self);
458458
if(!AI_CanMove(self, BOT_MOVE_FORWARD) )
459459
{
460-
gi.dprintf("bot can't move forward\n");//GHz
460+
//gi.dprintf("bot can't move forward\n");//GHz
461461
self->movetarget = NULL;
462462
ucmd->forwardmove = -400;
463463
return false;

src/ai/bot_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ void AI_DebugPrintf (char* fmt, ...)
316316
va_list argptr;
317317
int len;
318318

319-
if (!AIDevel.debugMode)
319+
//if (!AIDevel.debugMode)
320320
return;
321321
va_start(argptr, fmt);
322322
len = vsprintf(bigbuffer, fmt, argptr);

src/ai/bot_spawn.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ in NO WAY supported by Steve Yeager.
4040
///////////////////////////////////////////////////////////////////////
4141
void BOT_Respawn (edict_t *self)
4242
{
43-
gi.dprintf("BOT_Respawn\n");
43+
//gi.dprintf("BOT_Respawn\n");
4444
CopyToBodyQue (self);
4545

4646
PutClientInServer (self);
@@ -465,13 +465,13 @@ void BOT_RemoveBot(char *name)
465465
qboolean freed=false;
466466
edict_t *bot;
467467

468-
gi.dprintf("BOT_RemoveBot\n");
468+
//gi.dprintf("BOT_RemoveBot\n");
469469
for(i=0;i<maxclients->value;i++)
470470
{
471471
bot = g_edicts + i + 1;
472472
if(bot->inuse)
473473
{
474-
gi.dprintf("found %s\n", bot->classname);
474+
//gi.dprintf("found %s\n", bot->classname);
475475
if(bot->ai.is_bot && (strcmp(bot->client->pers.netname,name)==0 || strcmp(name,"all")==0))
476476
{
477477
bot->health = 0;

src/quake2/p_client.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ void SP_info_player_intermission(void)
172172

173173
void player_pain (edict_t *self, edict_t *other, float kick, int damage)
174174
{
175+
BOT_DMclass_Pain(self, other, kick, damage);//GHz
175176
// player pain is handled at the end of the frame in P_DamageFeedback
176177
}
177178

@@ -985,7 +986,7 @@ void player_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damag
985986
self->client->ps.pmove.pm_type = PM_DEAD;
986987
ClientObituary (self, inflictor, attacker);
987988
//TossClientWeapon (self);
988-
if (deathmatch->value)
989+
if (deathmatch->value && !self->ai.is_bot) // GHz: don't send unicast packets to bots!
989990
Cmd_Help_f (self); // show scores
990991
// clear inventory
991992
memset(self->client->pers.inventory, 0, sizeof(self->client->pers.inventory));

0 commit comments

Comments
 (0)