コード例 #1
0
ファイル: main.c プロジェクト: icanhas/yantar
/*
 * BotTestAAS
 */
void
BotTestAAS(Vec3 origin)
{
	int areanum;
	aas_areainfo_t info;

	trap_cvarupdate(&bot_testsolid);
	trap_cvarupdate(&bot_testclusters);
	if(bot_testsolid.integer){
		if(!trap_AAS_Initialized()) return;
		areanum = BotPointAreaNum(origin);
		if(areanum) BotAI_Print(PRT_MESSAGE, "\remtpy area");
		else BotAI_Print(PRT_MESSAGE, "\r^1SOLID area");
	}else if(bot_testclusters.integer){
		if(!trap_AAS_Initialized()) return;
		areanum = BotPointAreaNum(origin);
		if(!areanum)
			BotAI_Print(PRT_MESSAGE,
				"\r^1Solid!                              ");
		else{
			trap_AAS_AreaInfo(areanum, &info);
			BotAI_Print(PRT_MESSAGE, "\rarea %d, cluster %d       ",
				areanum,
				info.cluster);
		}
	}
}
コード例 #2
0
/*
==================
BotTeamplayReport
==================
*/
void BotTeamplayReport(void) {
	int i;
	char buf[MAX_INFO_STRING];

	BotAI_Print(PRT_MESSAGE, S_COLOR_RED"RED\n");
	for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
		//
		if ( !botstates[i] || !botstates[i]->inuse ) continue;
		//
		trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
		//if no config string or no name
		if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n"))) continue;
		//skip spectators
		if (atoi(Info_ValueForKey(buf, "t")) == TEAM_RED) {
			BotReportStatus(botstates[i]);
		}
	}
	BotAI_Print(PRT_MESSAGE, S_COLOR_BLUE"BLUE\n");
	for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
		//
		if ( !botstates[i] || !botstates[i]->inuse ) continue;
		//
		trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
		//if no config string or no name
		if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n"))) continue;
		//skip spectators
		if (atoi(Info_ValueForKey(buf, "t")) == TEAM_BLUE) {
			BotReportStatus(botstates[i]);
		}
	}
}
コード例 #3
0
ファイル: ai_main.c プロジェクト: zturtleman/recoil
/*
==================
BotTestAAS
==================
*/
void BotTestAAS(vec3_t origin)
{
    int areanum;
    aas_areainfo_t info;

    if (bot_testsolid->integer)
    {
        if (!botlib_export->aas.AAS_Initialized()) return;
        areanum = BotPointAreaNum(origin);
        if (areanum) BotAI_Print(PRT_MESSAGE, "\remtpy area");
        else BotAI_Print(PRT_MESSAGE, "\r^1SOLID area");
    }
    else if (bot_testclusters->integer)
    {
        if (!botlib_export->aas.AAS_Initialized()) return;
        areanum = BotPointAreaNum(origin);
        if (!areanum)
            BotAI_Print(PRT_MESSAGE, "\r^1Solid!                              ");
        else
        {
            botlib_export->aas.AAS_AreaInfo(areanum, &info);
            BotAI_Print(PRT_MESSAGE, "\rarea %d, cluster %d       ", areanum, info.cluster);
        }
    }
}
コード例 #4
0
//========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//========================================================================
bot_character_t *BotCharacterFromHandle(int handle)
{
	if (handle <= 0 || handle >= MAX_BOT_CHARACTERS)
	{
		BotAI_Print(PRT_FATAL, "character handle %d out of range\n", handle);
		return NULL;
	} //end if
	if (!botcharacters[handle].skill)
	{
		BotAI_Print(PRT_FATAL, "invalid character %d\n", handle);
		return NULL;
	} //end if
	return &botcharacters[handle];
} //end of the function BotCharacterFromHandle
コード例 #5
0
//========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//========================================================================
void BotFreeCharacter2(int handle)
{
	if (handle <= 0 || handle >= MAX_BOT_CHARACTERS)
	{
		BotAI_Print(PRT_FATAL, "character handle %d out of range\n", handle);
		return;
	} //end if
	if (!botcharacters[handle].skill)
	{
		BotAI_Print(PRT_FATAL, "invalid character %d\n", handle);
		return;
	} //end if
	BotFreeCharacterStrings(&botcharacters[handle]);
	Com_Memset(&botcharacters[handle], 0, sizeof (bot_character_t));
} //end of the function BotFreeCharacter2
コード例 #6
0
ファイル: ai_cast.c プロジェクト: natelo/rtcwPub
/*
==============
AICast_ShutdownClient
==============
*/
int AICast_ShutdownClient(int client)
{
	cast_state_t	*cs;
	bot_state_t *bs;

	if (!(bs = botstates[client])) {
		return BLERR_NOERROR;
	}
	if (!bs->inuse) {
		BotAI_Print(PRT_ERROR, "client %d already shutdown\n", client);
		return BLERR_AICLIENTALREADYSHUTDOWN;
	}

	cs = AICast_GetCastState( client );
	//
	memset( cs, 0, sizeof(cast_state_t) );
	numcast--;

	// now do the other bot stuff

#ifdef DEBUG
//	botai_import.DebugLineDelete(bs->debugline);
#endif //DEBUG

	trap_BotFreeMoveState(bs->ms);
	//free the goal state
	trap_BotFreeGoalState(bs->gs);
	//
	//clear the bot state
	memset(bs, 0, sizeof(bot_state_t));
	//set the inuse flag to qfalse
	bs->inuse = qfalse;
	//everything went ok
	return BLERR_NOERROR;
}
コード例 #7
0
ファイル: ai_cast.c プロジェクト: natelo/rtcwPub
/*
==============
AICast_SetupClient
==============
*/
int AICast_SetupClient(int client)
{
	cast_state_t	*cs;
	bot_state_t		*bs;

	if (!botstates[client]) {
		botstates[client] = G_Alloc(sizeof(bot_state_t));
		memset( botstates[client], 0, sizeof(bot_state_t) );
	}
	bs = botstates[client];

	if (bs->inuse) {
		BotAI_Print(PRT_FATAL, "client %d already setup\n", client);
		return qfalse;
	}

	cs = AICast_GetCastState(client);
	cs->bs = bs;

	//allocate a goal state
	bs->gs = trap_BotAllocGoalState(client);

	bs->inuse = qtrue;
	bs->client = client;
	bs->entitynum = client;
	bs->setupcount = qtrue;
	bs->entergame_time = trap_AAS_Time();
	bs->ms = trap_BotAllocMoveState();

	return qtrue;
}
コード例 #8
0
ファイル: ai_self.c プロジェクト: Garey27/quake3-brainworks
/*
==============
BotAimEnemySet

Sets the bot's aim enemy to the inputted enemy and
copies the inputted combat zone description for that
enemy.  If enemy is NULL, the bot's combat zone is
instead reset to a default zone (and the input zone,
which may be NULL, is ignored).  "sighted" is the
time at which the target was first sighted, or -1 if
the target is not currently in line of sight.

NOTE: The combat zone will get copied over even when
the input enemy is the bot's current enemy, but
additional fields will get reset when the input enemy
is a change.  So it's important to call this function
when either the aim enemy or the enemy's combat zone
changes.
==============
*/
void BotAimEnemySet(bot_state_t *bs, gentity_t *enemy, combat_zone_t *zone)
{
	// If the aim enemy changed, update some related data
	if (bs->aim_enemy != enemy)
	{
		// Store the new enemy and their estimate health
		bs->aim_enemy = enemy;
		bs->enemy_health = 125;

		// Look up their last known movement decision
		if (enemy && enemy->client)
			ClientViewDir(enemy->client, bs->aim_enemy_move_dir);

#ifdef DEBUG_AI
		if (bs->debug_flags & BOT_DEBUG_INFO_ENEMY)
			BotAI_Print(PRT_MESSAGE, "%s: Aim Enemy: %s\n",
						EntityNameFast(bs->ent),
						EntityNameFast(bs->aim_enemy));
#endif
	}

	// Update the enemy's combat zone if an enemy exists; otherwise use the last
	// enemy's zone as the default.
	//
	// NOTE: It's likely the bot will make shots after it kills an enemy because
	// the bots continue firing for a few milliseconds after they decide to stop.
	// This code will reset the aim enemy as soon as the target dies, but shots
	// will occur afterwards (and probably miss).  Those misses should get applied
	// to the combat zone the enemy was in at the time of attack decision.
	if (enemy)
		memcpy(&bs->aim_zone, zone, sizeof(combat_zone_t));
}
コード例 #9
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
int Characteristic_Integer(int character, int index)
{
	bot_character_t *ch;

	ch = BotCharacterFromHandle(character);
	if (!ch) return 0;
	//check if the index is in range
	if (!CheckCharacteristicIndex(character, index)) return 0;
	//an integer will just be returned
	if (ch->c[index].type == CT_INTEGER)
	{
		return ch->c[index].value.integer;
	} //end if
	//floats are casted to integers
	else if (ch->c[index].type == CT_FLOAT)
	{
		return (int) ch->c[index].value._float;
	} //end else if
	else
	{
		BotAI_Print(PRT_ERROR, "characteristic %d is not an integer\n", index);
		return 0;
	} //end else if
//	return 0;
} //end of the function Characteristic_Integer
コード例 #10
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
float Characteristic_Float(int character, int index)
{
	bot_character_t *ch;

	ch = BotCharacterFromHandle(character);
	if (!ch) return 0;
	//check if the index is in range
	if (!CheckCharacteristicIndex(character, index)) return 0;
	//an integer will be converted to a float
	if (ch->c[index].type == CT_INTEGER)
	{
		return (float) ch->c[index].value.integer;
	} //end if
	//floats are just returned
	else if (ch->c[index].type == CT_FLOAT)
	{
		return ch->c[index].value._float;
	} //end else if
	//cannot convert a string pointer to a float
	else
	{
		BotAI_Print(PRT_ERROR, "characteristic %d is not a float\n", index);
		return 0;
	} //end else if
//	return 0;
} //end of the function Characteristic_Float
コード例 #11
0
ファイル: ai_cmd.c プロジェクト: ioid3-games/ioid3-rtcw
/*
=======================================================================================================================================
BotGPSToPosition
=======================================================================================================================================
*/
int BotGPSToPosition(char *buf, vec3_t position) {
	int i, j = 0;
	int num, sign;

	for (i = 0; i < 3; i++) {
		num = 0;

		while (buf[j] == ' ') j++;

		if (buf[j] == '-') {
			j++;
			sign = -1;
		} else {
			sign = 1;
		}

		while (buf[j]) {
			if (buf[j] >= '0' && buf[j] <= '9') {
				num = num * 10 + buf[j] - '0';
				j++;
			} else {
				j++;
				break;
			}
		}

		BotAI_Print(PRT_MESSAGE, "%d\n", sign * num);
		position[i] = (float)sign * num;
	}

	return qtrue;
}
コード例 #12
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
int CheckCharacteristicIndex(int character, int index)
{
	bot_character_t *ch;

	ch = BotCharacterFromHandle(character);
	if (!ch) return qfalse;
	if (index < 0 || index >= MAX_CHARACTERISTICS)
	{
		BotAI_Print(PRT_ERROR, "characteristic %d does not exist\n", index);
		return qfalse;
	} //end if
	if (!ch->c[index].type)
	{
		BotAI_Print(PRT_ERROR, "characteristic %d is not initialized\n", index);
		return qfalse;
	} //end if
	return qtrue;
} //end of the function CheckCharacteristicIndex
コード例 #13
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int InterbreedFuzzySeperator_r(fuzzyseperator_t *fs1, fuzzyseperator_t *fs2,
								fuzzyseperator_t *fsout)
{
	if (fs1->child)
	{
		if (!fs2->child || !fsout->child)
		{
			BotAI_Print(PRT_ERROR, "cannot interbreed weight configs, unequal child\n");
			return qfalse;
		} //end if
		if (!InterbreedFuzzySeperator_r(fs2->child, fs2->child, fsout->child))
		{
			return qfalse;
		} //end if
	} //end if
	else if (fs1->type == WT_BALANCE)
	{
		if (fs2->type != WT_BALANCE || fsout->type != WT_BALANCE)
		{
			BotAI_Print(PRT_ERROR, "cannot interbreed weight configs, unequal balance\n");
			return qfalse;
		} //end if
		fsout->weight = (fs1->weight + fs2->weight) / 2;
		if (fsout->weight > fsout->maxweight) fsout->maxweight = fsout->weight;
		if (fsout->weight > fsout->minweight) fsout->minweight = fsout->weight;
	} //end else if
	if (fs1->next)
	{
		if (!fs2->next || !fsout->next)
		{
			BotAI_Print(PRT_ERROR, "cannot interbreed weight configs, unequal next\n");
			return qfalse;
		} //end if
		if (!InterbreedFuzzySeperator_r(fs1->next, fs2->next, fsout->next))
		{
			return qfalse;
		} //end if
	} //end if
	return qtrue;
} //end of the function InterbreedFuzzySeperator_r
コード例 #14
0
/*
==================
BotMatchMessage
==================
*/
int BotMatchMessage(bot_state_t *bs, char *message) {
	bot_match_t match;

	match.type = 0;
	//if it is an unknown message
	if (!trap_BotFindMatch(message, &match, MTCONTEXT_MISC|MTCONTEXT_INITIALTEAMCHAT )) {
		if(bot_developer.integer & AIDBG_CHAT ){
			G_Printf("^2no match for ^1%s\n", message);
		}
		return qfalse;
	}

	if(bot_developer.integer & AIDBG_CHAT){
		G_Printf("^6match %d for^1 %s\n", match.type, message);
	}

	//react to the found message
	switch(match.type)
	{
		case MSG_WRONGWALL:{
			BotMatch_WrongWall(bs, &match);
			break;
		}
		//case MSG_GOFORBALLOON:{				//someone calling for company
		//	BotMatch_GoForBalloon(bs, &match);
		//	break;
		//}
		case MSG_DROPCART:{
			BotMatch_DropCart(bs, &match);
			break;
		}
		case MSG_GETITEM:{
			BotMatch_GetItem(bs, &match);
			break;
		}
		case MSG_ENTERGAME:{			//someone entered the game
			BotMatch_EnterGame(bs, &match);
			break;
		}
		case MSG_CATCHME:{
			BotMatch_CatchMe(bs, &match);
			break;
		}
		default:{
			if(bot_developer.integer)
				BotAI_Print(PRT_MESSAGE, "unknown match type %d\n",match.type);
			break;
		}
	}
	return qtrue;
}
コード例 #15
0
ファイル: ai_main.c プロジェクト: SilverlineDev/mint-arena
/*
==================
Svcmd_BotTeamplayReport_f
==================
*/
void Svcmd_BotTeamplayReport_f(void) {
	int i;

	if (!bot_report.integer) {
		BotAI_Print(PRT_MESSAGE, "Must set bot_report 1 before using botreport command.\n");
		return;
	}

	if (gametype >= GT_TEAM) {
		BotAI_Print(PRT_MESSAGE, S_COLOR_RED"RED\n");
		for (i = 0; i < level.maxplayers; i++) {
			//
			if ( !botstates[i] || !botstates[i]->inuse ) continue;
			//
			if (BotTeam(botstates[i]) == TEAM_RED) {
				BotReportStatus(botstates[i]);
			}
		}
		BotAI_Print(PRT_MESSAGE, S_COLOR_BLUE"BLUE\n");
		for (i = 0; i < level.maxplayers; i++) {
			//
			if ( !botstates[i] || !botstates[i]->inuse ) continue;
			//
			if (BotTeam(botstates[i]) == TEAM_BLUE) {
				BotReportStatus(botstates[i]);
			}
		}
	}
	else {
		for (i = 0; i < level.maxplayers; i++) {
			//
			if ( !botstates[i] || !botstates[i]->inuse ) continue;
			//
			BotReportStatus(botstates[i]);
		}
	}
}
コード例 #16
0
/*
===============
BotMatchMessage

This function returns if the message could be matched.  It does not
mean the bot actually processed the message.

NOTE: Death messages are sent as an EV_OBITUARY event, not actual console
messages.  As such, they are processed by BotCheckEvents() in ai_scan.c.
===============
*/
qboolean BotMatchMessage(bot_state_t *bs, char *message)
{
	bot_match_t match;
	char name[MAX_MESSAGE_SIZE];
	gentity_t *sender;

	// Try to match this message as a CTF teamchat message
	match.type = 0;
	if (!trap_BotFindMatch(message, &match,
						   MTCONTEXT_MISC | MTCONTEXT_INITIALTEAMCHAT | MTCONTEXT_CTF))
		return qfalse;

	// Ignore messages in deathmatch modes, but return true because it's a real message
	if ( !(game_style & GS_TEAM) )
		return qtrue;

	// Check if this message is a team management message
	trap_BotMatchVariable(&match, NETNAME, name, sizeof(name));
	sender = TeammateFromName(bs, name);
	if (BotMatch_Team(bs, &match, sender))
		return qtrue;

	// Ignore messages not from a teammate
	if (!sender)
	{
		Bot_InitialChat(bs, "whois", name, NULL);
		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return qtrue;
	}

	// Ignore other messages if they aren't intended for this bot
	if (!BotAddresseeMatch(bs, &match))
		return qtrue;

	// Check if this message is an order
	if (BotMatch_Order(bs, &match, sender))
		return qtrue;

	// Check if this message is a subteam request
	if (BotMatch_Subteam(bs, &match, sender))
		return qtrue;

	// Still return true because the message matched-- our code just elected not to process it
	BotAI_Print(PRT_WARNING, "Unknown match type %i\n", match.type);
	return qtrue;
}
コード例 #17
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
int Characteristic_BInteger(int character, int index, int min, int max)
{
	int value;
	bot_character_t *ch;

	ch = BotCharacterFromHandle(character);
	if (!ch) return 0;
	if (min > max)
	{
		BotAI_Print(PRT_ERROR, "cannot bound characteristic %d between %d and %d\n", index, min, max);
		return 0;
	} //end if
	value = Characteristic_Integer(character, index);
	if (value < min) return min;
	if (value > max) return max;
	return value;
} //end of the function Characteristic_BInteger
コード例 #18
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
int BotLoadCharacter(char *charfile, float skill)
{
	int firstskill, secondskill, handle;

	//make sure the skill is in the valid range
	if (skill < 1.0) skill = 1.0;
	else if (skill > 5.0) skill = 5.0;
	//skill 1, 4 and 5 should be available in the character files
	if (skill == 1.0 || skill == 4.0 || skill == 5.0)
	{
		return BotLoadCharacterSkill(charfile, skill);
	} //end if
	//check if there's a cached skill
	handle = BotFindCachedCharacter(charfile, skill);
	if (handle)
	{
		BotAI_Print(PRT_DEVELOPER, "loaded cached skill %f from %s\n", skill, charfile);
		return handle;
	} //end if
	if (skill < 4.0)
	{
		//load skill 1 and 4
		firstskill = BotLoadCharacterSkill(charfile, 1);
		if (!firstskill) return 0;
		secondskill = BotLoadCharacterSkill(charfile, 4);
		if (!secondskill) return firstskill;
	} //end if
	else
	{
		//load skill 4 and 5
		firstskill = BotLoadCharacterSkill(charfile, 4);
		if (!firstskill) return 0;
		secondskill = BotLoadCharacterSkill(charfile, 5);
		if (!secondskill) return firstskill;
	} //end else
	//interpolate between the two skills
	handle = BotInterpolateCharacters(firstskill, secondskill, skill);
	if (!handle) return 0;
#if 0 // ZTM: FIXME: add new bot logfile for game to write to?
	//write the character to the log file
	BotDumpCharacter(&botcharacters[handle]);
#endif
	//
	return handle;
} //end of the function BotLoadCharacter
コード例 #19
0
/*
=================
BotCreateWaypoint

Creates a new waypoint with the inputted name.
This function's caller must set up the waypoint's goal.
=================
*/
bot_waypoint_t *BotCreateWaypoint(char *name)
{
	bot_waypoint_t *wp;

	// Make sure a new waypoint can be allocated
	wp = botai_freewaypoints;
	if (!wp) {
		BotAI_Print(PRT_WARNING, "BotCreateWaypoint: Out of waypoints\n");
		return NULL;
	}
	botai_freewaypoints = botai_freewaypoints->next;

	// Set all waypoint information except the goal
	Q_strncpyz( wp->name, name, sizeof(wp->name) );
	wp->next = NULL;
	wp->prev = NULL;
	return wp;
}
コード例 #20
0
//===========================================================================
// config1 and config2 are interbreeded and stored in configout
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void InterbreedWeightConfigs(weightconfig_t *config1, weightconfig_t *config2,
								weightconfig_t *configout)
{
	int i;

	if (config1->numweights != config2->numweights ||
		config1->numweights != configout->numweights)
	{
		BotAI_Print(PRT_ERROR, "cannot interbreed weight configs, unequal numweights\n");
		return;
	} //end if
	for (i = 0; i < config1->numweights; i++)
	{
		InterbreedFuzzySeperator_r(config1->weights[i].firstseperator,
									config2->weights[i].firstseperator,
									configout->weights[i].firstseperator);
	} //end for
} //end of the function InterbreedWeightConfigs
コード例 #21
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
void Characteristic_String(int character, int index, char *buf, int size)
{
	bot_character_t *ch;

	ch = BotCharacterFromHandle(character);
	if (!ch) return;
	//check if the index is in range
	if (!CheckCharacteristicIndex(character, index)) return;
	//an integer will be converted to a float
	if (ch->c[index].type == CT_STRING)
	{
		strncpy(buf, ch->c[index].value.string, size-1);
		buf[size-1] = '\0';
	} //end if
	else
	{
		BotAI_Print(PRT_ERROR, "characteristic %d is not a string\n", index);
	} //end else if
} //end of the function Characteristic_String
コード例 #22
0
ファイル: ai_main.c プロジェクト: SilverlineDev/mint-arena
/*
==================
BotReportStatus
==================
*/
void BotReportStatus(bot_state_t *bs) {
	char buf[MAX_INFO_STRING];
	char netname[MAX_MESSAGE_SIZE];
	char leader[MAX_MESSAGE_SIZE];
	char carrying[MAX_MESSAGE_SIZE];
	char action[MAX_MESSAGE_SIZE];
	char node[MAX_MESSAGE_SIZE];

	trap_GetConfigstring(CS_BOTINFO+bs->playernum, buf, sizeof(buf));

	if (!*buf) {
		return;
	}

	PlayerName(bs->playernum, netname, sizeof(netname));

	Q_strncpyz( leader, Info_ValueForKey(buf, "l"), sizeof(leader) );
	Q_strncpyz( carrying, Info_ValueForKey(buf, "c"), sizeof(carrying) );
	Q_strncpyz( action, Info_ValueForKey(buf, "a"), sizeof(action) );
	Q_strncpyz( node, Info_ValueForKey(buf, "n"), sizeof(node) );
	BotAI_Print(PRT_MESSAGE, "%-20s%-1s%-2s: %s (%s)\n", netname, leader, carrying, action, node);
}
コード例 #23
0
ファイル: ai_main.c プロジェクト: SilverlineDev/mint-arena
/*
==============
BotEntityInfo
==============
*/
void BotEntityInfo(int entnum, aas_entityinfo_t *info) {
	gentity_t *ent;

	if (entnum < 0 || entnum >= level.num_entities)
	{
		BotAI_Print(PRT_FATAL, "BotEntityInfo: entnum %d out of range\n", entnum);
		Com_Memset(info, 0, sizeof(aas_entityinfo_t));
		return;
	} //end if

	ent = &g_entities[entnum];

	info->valid = ent->botvalid;
	info->type = ent->s.eType;
	info->flags = ent->s.eFlags;
	info->update_time = ent->update_time;
	info->ltime = ent->ltime;
	info->number = entnum;
	VectorCopy(ent->visorigin, info->origin);
	VectorCopy(ent->lastAngles, info->angles);
	VectorCopy(ent->lastvisorigin, info->lastvisorigin);
	VectorCopy(ent->s.mins, info->mins);
	VectorCopy(ent->s.maxs, info->maxs);
	info->groundent = ent->s.groundEntityNum;
	if (ent->s.collisionType == CT_SUBMODEL) info->solid = SOLID_BSP;
	else info->solid = SOLID_BBOX;
	info->modelindex = ent->s.modelindex;
	info->modelindex2 = ent->s.modelindex2;
	info->frame = ent->s.frame;
	info->event = ent->s.event;
	info->eventParm = ent->s.eventParm;
	info->powerups = ent->s.powerups;
	info->weapon = ent->s.weapon;
	info->legsAnim = ent->s.legsAnim;
	info->torsoAnim = ent->s.torsoAnim;
}
コード例 #24
0
ファイル: ai_main.c プロジェクト: SilverlineDev/mint-arena
/*
==============
BotAI
==============
*/
int BotAI(int playernum, float thinktime) {
	bot_state_t *bs;
	char buf[1024], *args;
	int j;

	EA_ResetInput(playernum);
	//
	bs = botstates[playernum];
	if (!bs || !bs->inuse) {
		BotAI_Print(PRT_FATAL, "BotAI: player %d is not setup\n", playernum);
		return qfalse;
	}

	//retrieve the current player state
	if (!BotAI_GetPlayerState( playernum, &bs->cur_ps )) {
		BotAI_Print(PRT_FATAL, "BotAI: failed to get player state for player %d\n", playernum);
		return qfalse;
	}

	//retrieve any waiting server commands
	while( trap_BotGetServerCommand(playernum, buf, sizeof(buf)) ) {
		//have buf point to the command and args to the command arguments
		args = strchr( buf, ' ');
		if (!args) continue;
		*args++ = '\0';

		//remove color espace sequences from the arguments
		RemoveColorEscapeSequences( args );

		if (!Q_stricmp(buf, "cp "))
			{ /*CenterPrintf*/ }
		else if (!Q_stricmp(buf, "cs"))
			{ /*ConfigStringModified*/ }
		else if (!Q_stricmp(buf, "print")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			BotQueueConsoleMessage(bs->cs, CMS_NORMAL, args);
		}
		else if (!Q_stricmp(buf, "chat") || !Q_stricmp(buf, "tell")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			BotQueueConsoleMessage(bs->cs, CMS_CHAT, args);
		}
		else if (!Q_stricmp(buf, "tchat")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			BotQueueConsoleMessage(bs->cs, CMS_CHAT, args);
		}
#ifdef MISSIONPACK
		else if (!Q_stricmp(buf, "vchat")) {
			BotVoiceChatCommand(bs, SAY_ALL, args);
		}
		else if (!Q_stricmp(buf, "vtchat")) {
			BotVoiceChatCommand(bs, SAY_TEAM, args);
		}
		else if (!Q_stricmp(buf, "vtell")) {
			BotVoiceChatCommand(bs, SAY_TELL, args);
		}
#endif
		else if (!Q_stricmp(buf, "scores"))
			{ /*FIXME: parse scores?*/ }
		else if (!Q_stricmp(buf, "clientLevelShot"))
			{ /*ignore*/ }
	}
	//add the delta angles to the bot's current view angles
	for (j = 0; j < 3; j++) {
		bs->viewangles[j] = AngleMod(bs->viewangles[j] + SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	}
	//increase the local time of the bot
	bs->ltime += thinktime;
	//
	bs->thinktime = thinktime;
	//origin of the bot
	VectorCopy(bs->cur_ps.origin, bs->origin);
	//eye coordinates of the bot
	VectorCopy(bs->cur_ps.origin, bs->eye);
	bs->eye[2] += bs->cur_ps.viewheight;
	//get the area the bot is in
	bs->areanum = BotPointAreaNum(bs->origin);
	//the real AI
	BotDeathmatchAI(bs, thinktime);
	//set the weapon selection every AI frame
	EA_SelectWeapon(bs->playernum, bs->weaponnum);
	//subtract the delta angles
	for (j = 0; j < 3; j++) {
		bs->viewangles[j] = AngleMod(bs->viewangles[j] - SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	}
	//everything was ok
	return qtrue;
}
コード例 #25
0
ファイル: ai_main.c プロジェクト: SilverlineDev/mint-arena
/*
==============
BotAISetupPlayer
==============
*/
int BotAISetupPlayer(int playernum, struct bot_settings_s *settings, qboolean restart) {
	char filename[MAX_PATH], name[MAX_PATH], gender[MAX_PATH];
	bot_state_t *bs;
	int errnum;

	if (!botstates[playernum]) botstates[playernum] = trap_Alloc(sizeof(bot_state_t), NULL);
	bs = botstates[playernum];

	if (!bs) {
		return qfalse;
	}

	if (bs && bs->inuse) {
		BotAI_Print(PRT_FATAL, "BotAISetupPlayer: player %d already setup\n", playernum);
		return qfalse;
	}

	if (!trap_AAS_Initialized()) {
		BotAI_Print(PRT_FATAL, "AAS not initialized\n");
		return qfalse;
	}

	//load the bot character
	bs->character = BotLoadCharacter(settings->characterfile, settings->skill);
	if (!bs->character) {
		BotAI_Print(PRT_FATAL, "couldn't load skill %f from %s\n", settings->skill, settings->characterfile);
		return qfalse;
	}
	//copy the settings
	memcpy(&bs->settings, settings, sizeof(bot_settings_t));
	//allocate a goal state
	bs->gs = BotAllocGoalState(playernum);
	//load the item weights
	Characteristic_String(bs->character, CHARACTERISTIC_ITEMWEIGHTS, filename, MAX_PATH);
	errnum = BotLoadItemWeights(bs->gs, filename);
	if (errnum != BLERR_NOERROR) {
		BotFreeGoalState(bs->gs);
		BotAI_Print(PRT_FATAL, "BotLoadItemWeights failed\n");
		return qfalse;
	}
	//allocate a weapon state
	bs->ws = BotAllocWeaponState(playernum);
	//load the weapon weights
	Characteristic_String(bs->character, CHARACTERISTIC_WEAPONWEIGHTS, filename, MAX_PATH);
	errnum = BotLoadWeaponWeights(bs->ws, filename);
	if (errnum != BLERR_NOERROR) {
		BotFreeGoalState(bs->gs);
		BotFreeWeaponState(bs->ws);
		BotAI_Print(PRT_FATAL, "BotLoadWeaponWeights failed\n");
		return qfalse;
	}
	//allocate a chat state
	bs->cs = BotAllocChatState();
	//load the chat file
	Characteristic_String(bs->character, CHARACTERISTIC_CHAT_FILE, filename, MAX_PATH);
	Characteristic_String(bs->character, CHARACTERISTIC_CHAT_NAME, name, MAX_PATH);
	errnum = BotLoadChatFile(bs->cs, filename, name);
	if (errnum != BLERR_NOERROR) {
		BotFreeChatState(bs->cs);
		BotFreeGoalState(bs->gs);
		BotFreeWeaponState(bs->ws);
		BotAI_Print(PRT_FATAL, "BotLoadChatFile failed\n");
		return qfalse;
	}
	//get the gender characteristic
	Characteristic_String(bs->character, CHARACTERISTIC_GENDER, gender, MAX_PATH);
	//set the chat gender
	if (*gender == 'f' || *gender == 'F') BotSetChatGender(bs->cs, CHAT_GENDERFEMALE);
	else if (*gender == 'm' || *gender == 'M') BotSetChatGender(bs->cs, CHAT_GENDERMALE);
	else BotSetChatGender(bs->cs, CHAT_GENDERLESS);

	bs->inuse = qtrue;
	bs->playernum = playernum;
	bs->entitynum = playernum;
	bs->setupcount = 4;
	bs->entergame_time = FloatTime();
	bs->ms = BotAllocMoveState(playernum);
	bs->walker = Characteristic_BFloat(bs->character, CHARACTERISTIC_WALKER, 0, 1);
	bs->revenge_enemy = -1;
	numbots++;

	trap_Cvar_Update( &bot_testichat );
	if (bot_testichat.integer) {
		BotChatTest(bs);
	}
	//NOTE: reschedule the bot thinking
	BotScheduleBotThink();
	//if interbreeding start with a mutation
	if (bot_interbreed) {
		BotMutateGoalFuzzyLogic(bs->gs, 1);
	}
	// if we kept the bot state
	if (restart) {
		BotReadSessionData(bs);
	}
	//bot has been setup succesfully
	return qtrue;
}
コード例 #26
0
ファイル: ai_main.c プロジェクト: MAN-AT-ARMS/iortcw-archive
/*
==============
BotAISetupClient
==============
*/
int BotAISetupClient( int client, struct bot_settings_s *settings ) {
	char filename[MAX_PATH], name[MAX_PATH], gender[MAX_PATH];
	bot_state_t *bs;
	int errnum;

	if ( !botstates[client] ) {
		botstates[client] = G_Alloc( sizeof( bot_state_t ) );
	}
	bs = botstates[client];

	if ( bs && bs->inuse ) {
		BotAI_Print( PRT_FATAL, "client %d already setup\n", client );
		return qfalse;
	}

	if ( !trap_AAS_Initialized() ) {
		BotAI_Print( PRT_FATAL, "AAS not initialized\n" );
		return qfalse;
	}

	//load the bot character
	bs->character = trap_BotLoadCharacter( settings->characterfile, settings->skill );
	if ( !bs->character ) {
		BotAI_Print( PRT_FATAL, "couldn't load skill %f from %s\n", settings->skill, settings->characterfile );
		return qfalse;
	}
	//copy the settings
	memcpy( &bs->settings, settings, sizeof( bot_settings_t ) );
	//allocate a goal state
	bs->gs = trap_BotAllocGoalState( client );
	//load the item weights
	trap_Characteristic_String( bs->character, CHARACTERISTIC_ITEMWEIGHTS, filename, MAX_PATH );
	errnum = trap_BotLoadItemWeights( bs->gs, filename );
	if ( errnum != BLERR_NOERROR ) {
		trap_BotFreeGoalState( bs->gs );
		return qfalse;
	}
	//allocate a weapon state
	bs->ws = trap_BotAllocWeaponState();
	//load the weapon weights
	trap_Characteristic_String( bs->character, CHARACTERISTIC_WEAPONWEIGHTS, filename, MAX_PATH );
	errnum = trap_BotLoadWeaponWeights( bs->ws, filename );
	if ( errnum != BLERR_NOERROR ) {
		trap_BotFreeGoalState( bs->gs );
		trap_BotFreeWeaponState( bs->ws );
		return qfalse;
	}
	//allocate a chat state
	bs->cs = trap_BotAllocChatState();
	//load the chat file
	trap_Characteristic_String( bs->character, CHARACTERISTIC_CHAT_FILE, filename, MAX_PATH );
	trap_Characteristic_String( bs->character, CHARACTERISTIC_CHAT_NAME, name, MAX_PATH );
	errnum = trap_BotLoadChatFile( bs->cs, filename, name );
	if ( errnum != BLERR_NOERROR ) {
		trap_BotFreeChatState( bs->cs );
		trap_BotFreeGoalState( bs->gs );
		trap_BotFreeWeaponState( bs->ws );
		return qfalse;
	}
	//get the gender characteristic
	trap_Characteristic_String( bs->character, CHARACTERISTIC_GENDER, gender, MAX_PATH );
	//set the chat gender
	if ( *gender == 'f' || *gender == 'F' ) {
		trap_BotSetChatGender( bs->cs, CHAT_GENDERFEMALE );
	} else if ( *gender == 'm' || *gender == 'M' )  {
		trap_BotSetChatGender( bs->cs, CHAT_GENDERMALE );
	} else { trap_BotSetChatGender( bs->cs, CHAT_GENDERLESS );}

	bs->inuse = qtrue;
	bs->client = client;
	bs->entitynum = client;
	bs->setupcount = 4;
	bs->entergame_time = trap_AAS_Time();
	bs->ms = trap_BotAllocMoveState();
	bs->walker = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_WALKER, 0, 1 );
	numbots++;

	if ( trap_Cvar_VariableIntegerValue( "bot_testichat" ) ) {
		trap_BotLibVarSet( "bot_testichat", "1" );
		BotChatTest( bs );
	}
	//NOTE: reschedule the bot thinking
	BotScheduleBotThink();
	//
	return qtrue;
}
コード例 #27
0
ファイル: ai_main.c プロジェクト: MAN-AT-ARMS/iortcw-archive
/*
==============
BotAI
==============
*/
int BotAI( int client, float thinktime ) {
	bot_state_t *bs;
	char buf[1024], *args;
	int j;

	trap_EA_ResetInput( client, NULL );
	//
	bs = botstates[client];
	if ( !bs || !bs->inuse ) {
		BotAI_Print( PRT_FATAL, "client %d hasn't been setup\n", client );
		return BLERR_AICLIENTNOTSETUP;
	}

	//retrieve the current client state
	BotAI_GetClientState( client, &bs->cur_ps );

	//retrieve any waiting console messages
	while ( trap_BotGetServerCommand( client, buf, sizeof( buf ) ) ) {
		//have buf point to the command and args to the command arguments
		args = strchr( buf, ' ' );
		if ( !args ) {
			continue;
		}
		*args++ = '\0';

		//remove color espace sequences from the arguments
		Q_CleanStr( args );

		//botai_import.Print(PRT_MESSAGE, "ConsoleMessage: \"%s\"\n", buf);
		if ( !Q_stricmp( buf, "cp " ) ) { /*CenterPrintf*/
		} else if ( !Q_stricmp( buf, "cs" ) )                                                      { /*ConfigStringModified*/
		} else if ( !Q_stricmp( buf, "print" ) )                                                                                                                       {
			trap_BotQueueConsoleMessage( bs->cs, CMS_NORMAL, args );
		} else if ( !Q_stricmp( buf, "chat" ) ) {
			trap_BotQueueConsoleMessage( bs->cs, CMS_CHAT, args );
		} else if ( !Q_stricmp( buf, "tchat" ) ) {
			trap_BotQueueConsoleMessage( bs->cs, CMS_CHAT, args );
		} else if ( !Q_stricmp( buf, "scores" ) ) { /*FIXME: parse scores?*/
		} else if ( !Q_stricmp( buf, "clientLevelShot" ) )                                                                    { /*ignore*/
		}
	}
	//add the delta angles to the bot's current view angles
	for ( j = 0; j < 3; j++ ) {
		bs->viewangles[j] = AngleMod( bs->viewangles[j] + SHORT2ANGLE( bs->cur_ps.delta_angles[j] ) );
	}
	//increase the local time of the bot
	bs->ltime += thinktime;
	//
	bs->thinktime = thinktime;
	//origin of the bot
	VectorCopy( bs->cur_ps.origin, bs->origin );
	//eye coordinates of the bot
	VectorCopy( bs->cur_ps.origin, bs->eye );
	bs->eye[2] += bs->cur_ps.viewheight;
	//get the area the bot is in
	bs->areanum = BotPointAreaNum( bs->origin );
	//the real AI
	BotDeathmatchAI( bs, thinktime );
	//set the weapon selection every AI frame
	trap_EA_SelectWeapon( bs->client, bs->weaponnum );
	//subtract the delta angles
	for ( j = 0; j < 3; j++ ) {
		bs->viewangles[j] = AngleMod( bs->viewangles[j] - SHORT2ANGLE( bs->cur_ps.delta_angles[j] ) );
	}
	//everything was ok
	return BLERR_NOERROR;
}
コード例 #28
0
ファイル: ai_cmd.c プロジェクト: ioid3-games/ioid3-rtcw
/*
=======================================================================================================================================
BotPrintTeamGoal
=======================================================================================================================================
*/
void BotPrintTeamGoal(bot_state_t *bs) {
	char netname[MAX_NETNAME];
	float t;

	ClientName(bs->client, netname, sizeof(netname));
	t = bs->teamgoal_time - trap_AAS_Time();

	switch (bs->ltgtype) {
	case LTG_TEAMHELP:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna help a team mate for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_TEAMACCOMPANY:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna accompany a team mate for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_GETFLAG:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna get the flag for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_RUSHBASE:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna rush to the base for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_RETURNFLAG:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna try to return the flag for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_DEFENDKEYAREA:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna defend a key area for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_GETITEM:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna get an item for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_KILL:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna kill someone for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_CAMP:
	case LTG_CAMPORDER:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna camp for %1.0f secs\n", netname, t);
		break;
	}

	case LTG_PATROL:
	{
		BotAI_Print(PRT_MESSAGE, "%s: I'm gonna patrol for %1.0f secs\n", netname, t);
		break;
	}

	default:
	{
		if (bs->ctfroam_time > trap_AAS_Time()) {
			t = bs->ctfroam_time - trap_AAS_Time();
			BotAI_Print(PRT_MESSAGE, "%s: I'm gonna roam for %1.0f secs\n", netname, t);
		} else {
			BotAI_Print(PRT_MESSAGE, "%s: I've got a regular goal\n", netname);
		}
	}
	}
}
コード例 #29
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
weightconfig_t *ReadWeightConfig(char *filename)
{
	int newindent, avail = 0, n;
	pc_token_t token;
	int source;
	fuzzyseperator_t *fs;
	weightconfig_t *config = NULL;
	int starttime;

	starttime = trap_Milliseconds();

	if (!bot_reloadcharacters.integer)
	{
		avail = -1;
		for( n = 0; n < MAX_WEIGHT_FILES; n++ )
		{
			config = weightFileList[n];
			if( !config )
			{
				if( avail == -1 )
				{
					avail = n;
				} //end if
				continue;
			} //end if
			if( strcmp( filename, config->filename ) == 0 )
			{
				//BotAI_Print( PRT_MESSAGE, "retained %s\n", filename );
				return config;
			} //end if
		} //end for

		if( avail == -1 )
		{
			BotAI_Print( PRT_ERROR, "weightFileList was full trying to load %s\n", filename );
			return NULL;
		} //end if
	} //end if

	source = trap_PC_LoadSource(filename, BOTFILESBASEFOLDER);
	if (!source)
	{
		BotAI_Print(PRT_ERROR, "counldn't load %s\n", filename);
		return NULL;
	} //end if
	//
	config = (weightconfig_t *) trap_HeapMalloc(sizeof(weightconfig_t));
	config->numweights = 0;
	Q_strncpyz( config->filename, filename, sizeof(config->filename) );
	//parse the item config file
	while(trap_PC_ReadToken(source, &token))
	{
		if (!strcmp(token.string, "weight"))
		{
			if (config->numweights >= MAX_WEIGHTS)
			{
				PC_SourceWarning(source, "too many fuzzy weights");
				break;
			} //end if
			if (!PC_ExpectTokenType(source, TT_STRING, 0, &token))
			{
				FreeWeightConfig(config);
				trap_PC_FreeSource(source);
				return NULL;
			} //end if
			config->weights[config->numweights].name = (char *) trap_HeapMalloc(strlen(token.string) + 1);
			strcpy(config->weights[config->numweights].name, token.string);
			if (!PC_ExpectAnyToken(source, &token))
			{
				FreeWeightConfig(config);
				trap_PC_FreeSource(source);
				return NULL;
			} //end if
			newindent = qfalse;
			if (!strcmp(token.string, "{"))
			{
				newindent = qtrue;
				if (!PC_ExpectAnyToken(source, &token))
				{
					FreeWeightConfig(config);
					trap_PC_FreeSource(source);
					return NULL;
				} //end if
			} //end if
			if (!strcmp(token.string, "switch"))
			{
				fs = ReadFuzzySeperators_r(source);
				if (!fs)
				{
					FreeWeightConfig(config);
					trap_PC_FreeSource(source);
					return NULL;
				} //end if
				config->weights[config->numweights].firstseperator = fs;
			} //end if
			else if (!strcmp(token.string, "return"))
			{
				fs = (fuzzyseperator_t *) trap_HeapMalloc(sizeof(fuzzyseperator_t));
				fs->index = 0;
				fs->value = MAX_INVENTORYVALUE;
				fs->next = NULL;
				fs->child = NULL;
				if (!ReadFuzzyWeight(source, fs))
				{
					trap_HeapFree(fs);
					FreeWeightConfig(config);
					trap_PC_FreeSource(source);
					return NULL;
				} //end if
				config->weights[config->numweights].firstseperator = fs;
			} //end else if
			else
			{
				PC_SourceError(source, "invalid name %s", token.string);
				FreeWeightConfig(config);
				trap_PC_FreeSource(source);
				return NULL;
			} //end else
			if (newindent)
			{
				if (!PC_ExpectTokenString(source, "}"))
				{
					FreeWeightConfig(config);
					trap_PC_FreeSource(source);
					return NULL;
				} //end if
			} //end if
			config->numweights++;
		} //end if
		else
		{
			PC_SourceError(source, "invalid name %s", token.string);
			FreeWeightConfig(config);
			trap_PC_FreeSource(source);
			return NULL;
		} //end else
	} //end while
	//free the source at the end of a pass
	trap_PC_FreeSource(source);
	//if the file was located in a pak file
	BotAI_Print(PRT_DEVELOPER, "loaded %s\n", filename);
	BotAI_Print(PRT_DEVELOPER, "weights loaded in %d msec\n", trap_Milliseconds() - starttime);
	//
	if (!bot_reloadcharacters.integer)
	{
		weightFileList[avail] = config;
	} //end if
	//
	return config;
} //end of the function ReadWeightConfig
コード例 #30
0
/*
==================
BotReportStatus
==================
*/
void BotReportStatus(bot_state_t *bs) {
	char goalname[MAX_MESSAGE_SIZE];
	char netname[MAX_MESSAGE_SIZE];
	char *leader, flagstatus[32];
	//
	ClientName(bs->client, netname, sizeof(netname));
	if (Q_stricmp(netname, bs->teamleader) == 0) leader = "L";
	else leader = " ";

	strcpy(flagstatus, "  ");
	if (gametype == GT_CTF) {
		if (BotCTFCarryingFlag(bs)) {
			if (BotTeam(bs) == TEAM_RED) strcpy(flagstatus, S_COLOR_RED"F ");
			else strcpy(flagstatus, S_COLOR_BLUE"F ");
		}
	}
#if 1  //def MPACK
	else if (gametype == GT_1FCTF) {
		if (Bot1FCTFCarryingFlag(bs)) {
			if (BotTeam(bs) == TEAM_RED) strcpy(flagstatus, S_COLOR_RED"F ");
			else strcpy(flagstatus, S_COLOR_BLUE"F ");
		}
	}
	else if (gametype == GT_HARVESTER) {
		if (BotHarvesterCarryingCubes(bs)) {
			if (BotTeam(bs) == TEAM_RED) Com_sprintf(flagstatus, sizeof(flagstatus), S_COLOR_RED"%2d", bs->inventory[INVENTORY_REDCUBE]);
			else Com_sprintf(flagstatus, sizeof(flagstatus), S_COLOR_BLUE"%2d", bs->inventory[INVENTORY_BLUECUBE]);
		}
	}
#endif

	switch(bs->ltgtype) {
		case LTG_TEAMHELP:
		{
			EasyClientName(bs->teammate, goalname, sizeof(goalname));
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: helping %s\n", netname, leader, flagstatus, goalname);
			break;
		}
		case LTG_TEAMACCOMPANY:
		{
			EasyClientName(bs->teammate, goalname, sizeof(goalname));
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: accompanying %s\n", netname, leader, flagstatus, goalname);
			break;
		}
		case LTG_DEFENDKEYAREA:
		{
			trap_BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname));
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: defending %s\n", netname, leader, flagstatus, goalname);
			break;
		}
		case LTG_GETITEM:
		{
			trap_BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname));
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: getting item %s\n", netname, leader, flagstatus, goalname);
			break;
		}
		case LTG_KILL:
		{
			ClientName(bs->teamgoal.entitynum, goalname, sizeof(goalname));
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: killing %s\n", netname, leader, flagstatus, goalname);
			break;
		}
		case LTG_CAMP:
		case LTG_CAMPORDER:
		{
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: camping\n", netname, leader, flagstatus);
			break;
		}
		case LTG_PATROL:
		{
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: patrolling\n", netname, leader, flagstatus);
			break;
		}
		case LTG_GETFLAG:
		{
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: capturing flag\n", netname, leader, flagstatus);
			break;
		}
		case LTG_RUSHBASE:
		{
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: rushing base\n", netname, leader, flagstatus);
			break;
		}
		case LTG_RETURNFLAG:
		{
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: returning flag\n", netname, leader, flagstatus);
			break;
		}
		case LTG_ATTACKENEMYBASE:
		{
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: attacking the enemy base\n", netname, leader, flagstatus);
			break;
		}
		case LTG_HARVEST:
		{
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: harvesting\n", netname, leader, flagstatus);
			break;
		}
		default:
		{
			BotAI_Print(PRT_MESSAGE, "%-20s%s%s: roaming\n", netname, leader, flagstatus);
			break;
		}
	}
}