BotLib: Add support for the AIM linkflag, to control when a bot is forced
to look ahead to the current waypoint node.
This commit is contained in:
parent
4bb854f16b
commit
6a48c18171
10 changed files with 83 additions and 38 deletions
|
@ -273,7 +273,7 @@ bot::RunAI(void)
|
||||||
if (m_iCurNode == BOTROUTE_DESTINATION)
|
if (m_iCurNode == BOTROUTE_DESTINATION)
|
||||||
aimpos = m_vecLastNode;
|
aimpos = m_vecLastNode;
|
||||||
else {
|
else {
|
||||||
if (m_iCurNode > 0)
|
if (m_iCurNode > 0 && !(m_pRoute[m_iCurNode].m_iFlags & LF_AIM))
|
||||||
aimpos = m_pRoute[m_iCurNode - 1].m_vecDest;
|
aimpos = m_pRoute[m_iCurNode - 1].m_vecDest;
|
||||||
else
|
else
|
||||||
aimpos = m_pRoute[m_iCurNode].m_vecDest;
|
aimpos = m_pRoute[m_iCurNode].m_vecDest;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
BOTINFO_NONE,
|
||||||
BOTINFO_HEALTH,
|
BOTINFO_HEALTH,
|
||||||
BOTINFO_ARMOR,
|
BOTINFO_ARMOR,
|
||||||
BOTINFO_SPAWNPOINT,
|
BOTINFO_SPAWNPOINT,
|
||||||
|
|
|
@ -21,16 +21,16 @@
|
||||||
* The route must be followed in reverse order (ie: the first node that must be reached
|
* The route must be followed in reverse order (ie: the first node that must be reached
|
||||||
* is at index numnodes-1). If no route is available then the callback will be called with no nodes.
|
* is at index numnodes-1). If no route is available then the callback will be called with no nodes.
|
||||||
*/
|
*/
|
||||||
|
int
|
||||||
int Route_RoundDistance( float flDist )
|
Route_RoundDistance(float flDist)
|
||||||
{
|
{
|
||||||
float r = fabs( flDist ) % 2;
|
float r = fabs(flDist) % 2;
|
||||||
if ( r == 0 ) {
|
if (r == 0) {
|
||||||
return flDist;
|
return flDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( flDist < 0 ) {
|
if (flDist < 0) {
|
||||||
return -( fabs( flDist ) - r );
|
return -(fabs(flDist) - r);
|
||||||
} else {
|
} else {
|
||||||
return flDist + 2 - r;
|
return flDist + 2 - r;
|
||||||
}
|
}
|
||||||
|
@ -42,10 +42,11 @@ int Route_RoundDistance( float flDist )
|
||||||
Spawn_SelectRandom
|
Spawn_SelectRandom
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
entity Route_SelectRandom ( string sEntname )
|
entity
|
||||||
|
Route_SelectRandom(string sEntname)
|
||||||
{
|
{
|
||||||
static entity eLastSpot;
|
static entity eLastSpot;
|
||||||
eLastSpot = find( eLastSpot, classname, sEntname );
|
eLastSpot = find(eLastSpot, classname, sEntname);
|
||||||
return eLastSpot;
|
return eLastSpot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,14 +55,16 @@ entity Route_SelectRandom ( string sEntname )
|
||||||
Route_SelectRandomSpot
|
Route_SelectRandomSpot
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
entity Route_SelectRandomSpot(void)
|
entity
|
||||||
|
Route_SelectRandomSpot(void)
|
||||||
{
|
{
|
||||||
static entity eLastSpot;
|
static entity eLastSpot;
|
||||||
eLastSpot = findfloat( eLastSpot, ::botinfo, BOTINFO_SPAWNPOINT );
|
eLastSpot = findfloat(eLastSpot, ::botinfo, BOTINFO_SPAWNPOINT);
|
||||||
return eLastSpot;
|
return eLastSpot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot_RouteCB( entity ent, vector dest, int numnodes, nodeslist_t *nodelist )
|
void
|
||||||
|
Bot_RouteCB(entity ent, vector dest, int numnodes, nodeslist_t *nodelist)
|
||||||
{
|
{
|
||||||
bot b = (bot)ent;
|
bot b = (bot)ent;
|
||||||
b.m_iNodes = numnodes;
|
b.m_iNodes = numnodes;
|
||||||
|
@ -69,31 +72,32 @@ void Bot_RouteCB( entity ent, vector dest, int numnodes, nodeslist_t *nodelist )
|
||||||
b.m_pRoute = nodelist;
|
b.m_pRoute = nodelist;
|
||||||
b.m_vecLastNode = dest;
|
b.m_vecLastNode = dest;
|
||||||
|
|
||||||
//dprint( "Bot: Route calculated.\n" );
|
//dprint("Bot: Route calculated.\n");
|
||||||
//dprint( sprintf( "Bot: # of nodes: %i\n", bot.m_iNodes ) );
|
//dprint(sprintf("Bot: # of nodes: %i\n", bot.m_iNodes) );
|
||||||
//dprint( sprintf( "Bot: # current node: %i\n", bot.m_iCurNode ) );
|
//dprint(sprintf("Bot: # current node: %i\n", bot.m_iCurNode) );
|
||||||
//dprint( sprintf( "Bot: # endpos: %v\n", dest ) );
|
//dprint(sprintf("Bot: # endpos: %v\n", dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
vector Route_SelectDestination( bot target )
|
vector
|
||||||
|
Route_SelectDestination(bot target)
|
||||||
{
|
{
|
||||||
entity dest = world;
|
entity dest = world;
|
||||||
|
|
||||||
// Need health!
|
// Need health!
|
||||||
if ( target.health < 50 ) {
|
if (target.health < 50) {
|
||||||
entity temp;
|
entity temp;
|
||||||
int bestrange = COST_INFINITE;
|
int bestrange = COST_INFINITE;
|
||||||
int range;
|
int range;
|
||||||
for ( temp = world; ( temp = findfloat( temp, ::botinfo, BOTINFO_HEALTH ) ); ) {
|
for (temp = world; (temp = findfloat(temp, ::botinfo, BOTINFO_HEALTH));) {
|
||||||
range = vlen( temp.origin - target.origin );
|
range = vlen(temp.origin - target.origin);
|
||||||
if ( ( range < bestrange ) && ( temp.solid == SOLID_TRIGGER ) ) {
|
if ((range < bestrange) && (temp.solid == SOLID_TRIGGER)) {
|
||||||
bestrange = range;
|
bestrange = range;
|
||||||
dest = temp;
|
dest = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( dest ) {
|
if (dest) {
|
||||||
//dprint( "Route: Going for health!" );
|
//dprint("Route: Going for health!");
|
||||||
return dest.origin + '0 0 32';
|
return dest.origin + '0 0 32';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,14 +106,3 @@ vector Route_SelectDestination( bot target )
|
||||||
target.m_eDestination = dest;
|
target.m_eDestination = dest;
|
||||||
return dest.origin;
|
return dest.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Route_CanCrouch(bot target, vector endpos)
|
|
||||||
{
|
|
||||||
traceline(target.origin + [0,0,-18], endpos, FALSE, target);
|
|
||||||
|
|
||||||
if ( trace_fraction != 1.0f ) {
|
|
||||||
return FALSE;
|
|
||||||
} else {
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,5 +16,4 @@
|
||||||
|
|
||||||
int Route_RoundDistance( float flDist );
|
int Route_RoundDistance( float flDist );
|
||||||
vector Route_SelectDestination( bot target );
|
vector Route_SelectDestination( bot target );
|
||||||
int Route_CanCrouch(bot target, vector endpos);
|
|
||||||
void Bot_RouteCB( entity ent, vector dest, int numnodes, nodeslist_t *nodelist );
|
void Bot_RouteCB( entity ent, vector dest, int numnodes, nodeslist_t *nodelist );
|
||||||
|
|
|
@ -265,6 +265,31 @@ Way_FlagWalk(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Way_FlagAim(void)
|
||||||
|
{
|
||||||
|
if (g_waylink_status == 0) {
|
||||||
|
g_way1 = Way_FindClosestNode(self.origin);
|
||||||
|
g_waylink_status = 1;
|
||||||
|
env_message_single(self, "^2Selected first waypoint!\n");
|
||||||
|
} else if (g_waylink_status == 1) {
|
||||||
|
g_way2 = Way_FindClosestNode(self.origin);
|
||||||
|
g_waylink_status = 0;
|
||||||
|
|
||||||
|
if (g_way1 != g_way2) {
|
||||||
|
for (int b = 0i; b < g_pWaypoints[g_way1].m_numNeighbours; b++) {
|
||||||
|
if (g_pWaypoints[g_way1].m_pNeighbour[b].m_iNode == g_way2) {
|
||||||
|
g_pWaypoints[g_way1].m_pNeighbour[b].m_iFlags |= LF_AIM;
|
||||||
|
env_message_single(self, "^2Walk-linked the two points!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
env_message_single(self, "^1Failed to link, the two points are the same!\n");
|
||||||
|
}
|
||||||
|
g_way1 = g_way2 = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Way_HelperSpawns()
|
Way_HelperSpawns()
|
||||||
{
|
{
|
||||||
|
@ -461,6 +486,9 @@ Way_Cmd(void)
|
||||||
case "linkwalk":
|
case "linkwalk":
|
||||||
Way_FlagWalk();
|
Way_FlagWalk();
|
||||||
break;
|
break;
|
||||||
|
case "linkaim":
|
||||||
|
Way_FlagAim();
|
||||||
|
break;
|
||||||
case "move":
|
case "move":
|
||||||
vector p;
|
vector p;
|
||||||
int n = Way_FindClosestNode(self.origin);
|
int n = Way_FindClosestNode(self.origin);
|
||||||
|
@ -551,6 +579,12 @@ Way_DrawDebugInfo(void)
|
||||||
R_EndPolygon();
|
R_EndPolygon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fl & LF_AIM) {
|
||||||
|
R_PolygonVertex(org + [0,0,4], [0,1], [0.25,0.25,1], 1);
|
||||||
|
R_PolygonVertex(w2->m_vecOrigin + [0,0,4], [1,1], [0,0,0], 1);
|
||||||
|
R_EndPolygon();
|
||||||
|
}
|
||||||
|
|
||||||
R_PolygonVertex(org, [0,1], [1,0,1], 1);
|
R_PolygonVertex(org, [0,1], [1,0,1], 1);
|
||||||
R_PolygonVertex(w2->m_vecOrigin, [1,1], [0,1,0], 1);
|
R_PolygonVertex(w2->m_vecOrigin, [1,1], [0,1,0], 1);
|
||||||
R_EndPolygon();
|
R_EndPolygon();
|
||||||
|
|
|
@ -21,5 +21,6 @@
|
||||||
#define LF_CROUCH 0x00000004i
|
#define LF_CROUCH 0x00000004i
|
||||||
#define LF_TELEPORT 0x00000008i
|
#define LF_TELEPORT 0x00000008i
|
||||||
#define LF_WALK 0x00000010i
|
#define LF_WALK 0x00000010i
|
||||||
|
#define LF_AIM 0x00000020i
|
||||||
#define LF_USER 0x7fffff00i
|
#define LF_USER 0x7fffff00i
|
||||||
#define LF_DESTINATION 0x80000000i
|
#define LF_DESTINATION 0x80000000i
|
||||||
|
|
|
@ -279,6 +279,9 @@ WAY_FLAGS(int n)
|
||||||
case 3:
|
case 3:
|
||||||
localcmd("sv way linkwalk\n");
|
localcmd("sv way linkwalk\n");
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
localcmd("sv way linkaim\n");
|
||||||
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
Textmenu_Call("WAY_MENU");
|
Textmenu_Call("WAY_MENU");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -26,6 +26,7 @@ void info_player_start(void)
|
||||||
if (autocvar_fcs_swapteams == TRUE) {
|
if (autocvar_fcs_swapteams == TRUE) {
|
||||||
self.classname = "info_player_deathmatch";
|
self.classname = "info_player_deathmatch";
|
||||||
}
|
}
|
||||||
|
self.botinfo = BOTINFO_SPAWNPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -40,6 +41,7 @@ void info_player_deathmatch(void)
|
||||||
if (autocvar_fcs_swapteams == TRUE) {
|
if (autocvar_fcs_swapteams == TRUE) {
|
||||||
self.classname = "info_player_start";
|
self.classname = "info_player_start";
|
||||||
}
|
}
|
||||||
|
self.botinfo = BOTINFO_SPAWNPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Counter-Strike: Source compat */
|
/* Counter-Strike: Source compat */
|
||||||
|
|
|
@ -174,11 +174,16 @@ times the amount of players in a given game.
|
||||||
*/
|
*/
|
||||||
void PlayerPreThink(void)
|
void PlayerPreThink(void)
|
||||||
{
|
{
|
||||||
|
if (self.classname != "player") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOT_INCLUDED
|
#ifdef BOT_INCLUDED
|
||||||
if (clienttype(self) == CLIENTTYPE_BOT) {
|
if (clienttype(self) == CLIENTTYPE_BOT) {
|
||||||
((bot)self).PreFrame();
|
((bot)self).PreFrame();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_grMode.PlayerPreFrame((base_player)self);
|
g_grMode.PlayerPreFrame((base_player)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +198,10 @@ times the amount of players in a given game.
|
||||||
*/
|
*/
|
||||||
void PlayerPostThink(void)
|
void PlayerPostThink(void)
|
||||||
{
|
{
|
||||||
|
if (self.classname != "player") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOT_INCLUDED
|
#ifdef BOT_INCLUDED
|
||||||
if (clienttype(self) == CLIENTTYPE_BOT) {
|
if (clienttype(self) == CLIENTTYPE_BOT) {
|
||||||
((bot)self).PostFrame();
|
((bot)self).PostFrame();
|
||||||
|
@ -247,9 +256,12 @@ with the input_X globals being set to the appropriate data.
|
||||||
*/
|
*/
|
||||||
void SV_RunClientCommand(void)
|
void SV_RunClientCommand(void)
|
||||||
{
|
{
|
||||||
|
if (self.classname != "player") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOT_INCLUDED
|
#ifdef BOT_INCLUDED
|
||||||
/* wait a few seconds, as we may not have been spawned yet */
|
/* wait a few seconds, as we may not have been spawned yet */
|
||||||
if (time > 5.0)
|
|
||||||
if (clienttype(self) == CLIENTTYPE_BOT) {
|
if (clienttype(self) == CLIENTTYPE_BOT) {
|
||||||
((bot)self).RunAI();
|
((bot)self).RunAI();
|
||||||
}
|
}
|
||||||
|
|
4
tfc.fmf
4
tfc.fmf
|
@ -3,6 +3,7 @@ GAME tfc
|
||||||
NAME "Team Fortress"
|
NAME "Team Fortress"
|
||||||
BASEGAME platform
|
BASEGAME platform
|
||||||
BASEGAME logos
|
BASEGAME logos
|
||||||
|
BASEGAME valve
|
||||||
BASEGAME tfc
|
BASEGAME tfc
|
||||||
|
|
||||||
// custom game menu variables
|
// custom game menu variables
|
||||||
|
@ -24,9 +25,8 @@ BASEGAME tfc
|
||||||
-set gameinfo_url_dl "http://www.frag-net.com/mods/tfc.fmf"
|
-set gameinfo_url_dl "http://www.frag-net.com/mods/tfc.fmf"
|
||||||
-set gameinfo_menutrack ""
|
-set gameinfo_menutrack ""
|
||||||
|
|
||||||
DOWNLOADSURL http://www.frag-net.com/dl/tfc_packages
|
DOWNLOADSURL http://www.frag-net.com/dl/valve_packages
|
||||||
UPDATEURL http://www.frag-net.com/mods/tfc.fmf
|
UPDATEURL http://www.frag-net.com/mods/tfc.fmf
|
||||||
INSTALL "tfc_essential;valve_essential;free_essential"
|
|
||||||
|
|
||||||
// you don't really want to change these
|
// you don't really want to change these
|
||||||
RTCBROKER master.frag-net.com:27950
|
RTCBROKER master.frag-net.com:27950
|
||||||
|
|
Loading…
Reference in a new issue