Beispiel #1
0
/*
==================
BotAddressedToBot
==================
*/
int BotAddressedToBot(bot_state_t *bs, bot_match_t *match) {
	char addressedto[MAX_MESSAGE_SIZE];
	char netname[MAX_MESSAGE_SIZE];
	char name[MAX_MESSAGE_SIZE];
	char botname[128];
	int client;
	bot_match_t addresseematch;

	trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
	client = ClientOnSameTeamFromName(bs, netname);
	if (client < 0) return qfalse;
	//if the message is addressed to someone
	if (match->subtype & ST_ADDRESSED) {
		trap_BotMatchVariable(match, ADDRESSEE, addressedto, sizeof(addressedto));
		//the name of this bot
		ClientName(bs->client, botname, 128);
		//
		while(trap_BotFindMatch(addressedto, &addresseematch, MTCONTEXT_ADDRESSEE)) {
			if (addresseematch.type == MSG_EVERYONE) {
				return qtrue;
			}
			else if (addresseematch.type == MSG_MULTIPLENAMES) {
				trap_BotMatchVariable(&addresseematch, TEAMMATE, name, sizeof(name));
				if (strlen(name)) {
					if (stristr(botname, name)) return qtrue;
					if (stristr(bs->subteam, name)) return qtrue;
				}
				trap_BotMatchVariable(&addresseematch, MORE, addressedto, MAX_MESSAGE_SIZE);
			}
			else {
				trap_BotMatchVariable(&addresseematch, TEAMMATE, name, MAX_MESSAGE_SIZE);
				if (strlen(name)) {
					if (stristr(botname, name)) return qtrue;
					if (stristr(bs->subteam, name)) return qtrue;
				}
				break;
			}
		}
		//Com_sprintf(buf, sizeof(buf), "not addressed to me but %s", addressedto);
		//trap_EA_Say(bs->client, buf);
		return qfalse;
	}
	else {
		bot_match_t tellmatch;

		tellmatch.type = 0;
		//if this message wasn't directed solely to this bot
		if (!trap_BotFindMatch(match->string, &tellmatch, MTCONTEXT_REPLYCHAT) ||
				tellmatch.type != MSG_CHATTELL) {
			//make sure not everyone reacts to this message
			if (random() > (float ) 1.0 / (NumPlayersOnSameTeam(bs)-1)) return qfalse;
		}
	}
	return qtrue;
}
Beispiel #2
0
/*
=================
BotAddresseeMatch
=================
*/
qboolean BotAddresseeMatch(bot_state_t *bs, bot_match_t *match)
{
	int teammates;
	char addressee[MAX_MESSAGE_SIZE];
	char name[MAX_MESSAGE_SIZE];
	char *botname;
	bot_match_t submatch;

	// If the message isn't addressed to anyone in particular, the bot may or may not react
	if ( !(match->subtype & ST_ADDRESSED) )
	{
		// If the message was only given to this bot, the bot definitely reacts
		submatch.type = 0;
		if (trap_BotFindMatch(match->string, &submatch, MTCONTEXT_REPLYCHAT) &&
			submatch.type == MSG_CHATTELL)
			return qtrue;

		// The bot still might randomly react, though it's less likely with more teammates
		teammates = BotTeammates(bs);
		if (!teammates)
			return qtrue;
		return (random() <= 1.0 / teammates);
	}

	// Search for the bot's name in the message's addressee list
	botname = SimplifyName(EntityNameFast(bs->ent));
	trap_BotMatchVariable(match, ADDRESSEE, addressee, sizeof(addressee));
	while (trap_BotFindMatch(addressee, &submatch, MTCONTEXT_ADDRESSEE))
	{
		// If matching everyone on the team, automatically respond
		if (submatch.type == MSG_EVERYONE)
			return qtrue;

		// The bot responds if the next name matches its name or its subteam's name
		trap_BotMatchVariable(&submatch, TEAMMATE, name, sizeof(name));
		if (strlen(name))
		{
			if (stristr(botname, name))
				return qtrue;
			if (stristr(bs->subteam, name))
				return qtrue;
		}

		// Exit if this is the last name in the list
		if (submatch.type != MSG_MULTIPLENAMES)
			break;

		// Get the next name in the list
		trap_BotMatchVariable(&submatch, MORE, addressee, sizeof(addressee));
	}

	// The bot was not found in the specific addressee list
	return qfalse;
}
Beispiel #3
0
/*
=======================================================================================================================================
BotGetTime
=======================================================================================================================================
*/
float BotGetTime(bot_match_t *match) {
	bot_match_t timematch;
	char timestring[MAX_MESSAGE_SIZE];
	float t;
	// if the matched string has a time
	if (match->subtype & ST_TIME) {
		// get the time string
		trap_BotMatchVariable(match, TIME, timestring, MAX_MESSAGE_SIZE);
		// match it to find out if the time is in seconds or minutes
		if (trap_BotFindMatch(timestring, &timematch, MTCONTEXT_TIME)) {
			if (timematch.type == MSG_FOREVER) {
				t = 99999999;
			} else {
				trap_BotMatchVariable(&timematch, TIME, timestring, MAX_MESSAGE_SIZE);

				if (timematch.type == MSG_MINUTES) {
					t = atof(timestring) * 60;
				} else if (timematch.type == MSG_SECONDS) {
					t = atof(timestring);
				} else {t = 0;}
			}
			// if there's a valid time
			if (t > 0) {
				return trap_AAS_Time() + t;
			}
		}
	}

	return 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;
}
Beispiel #5
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;
}
Beispiel #6
0
/*
=======================================================================================================================================
BotMatch_HelpAccompany
=======================================================================================================================================
*/
void BotMatch_HelpAccompany(bot_state_t *bs, bot_match_t *match) {
	int client, other, areanum;
	char teammate[MAX_MESSAGE_SIZE], netname[MAX_MESSAGE_SIZE];
	char itemname[MAX_MESSAGE_SIZE];
	bot_match_t teammatematch;
	aas_entityinfo_t entinfo;

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// get the team mate name
	trap_BotMatchVariable(match, TEAMMATE, teammate, sizeof(teammate));
	// get the client to help
	if (trap_BotFindMatch(teammate, &teammatematch, MTCONTEXT_TEAMMATE) &&
		// if someone asks for him or herself
		 teammatematch.type == MSG_ME) {
		// get the netname
		trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
		client = ClientFromName(netname);
		other = qfalse;
	} else {
		// asked for someone else
		client = FindClientByName(teammate);
		// if this is the bot self
		if (client == bs->client) {
			other = qfalse;
		} else if (!BotSameTeam(bs, client)) {
			// FIXME: say "I don't help the enemy"
			return;
		} else {
			other = qtrue;
		}
	}
	// if the bot doesn't know who to help (FindClientByName returned -1)
	if (client < 0) {
		if (other) {
			BotAI_BotInitialChat(bs, "whois", teammate, NULL);
		} else {BotAI_BotInitialChat(bs, "whois", netname, NULL);}

		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// don't help or accompany yourself
	if (client == bs->client) {
		return;
	}

	bs->teamgoal.entitynum = -1;
	BotEntityInfo(client, &entinfo);
	// if info is valid (in PVS)
	if (entinfo.valid) {
		areanum = BotPointAreaNum(entinfo.origin);

		if (areanum && trap_AAS_AreaReachability(areanum)) {
			bs->teamgoal.entitynum = client;
			bs->teamgoal.areanum = areanum;
			VectorCopy(entinfo.origin, bs->teamgoal.origin);
			VectorSet(bs->teamgoal.mins, -8, -8, -8);
			VectorSet(bs->teamgoal.maxs, 8, 8, 8);
		}
	}
	// if no teamgoal yet
	if (bs->teamgoal.entitynum < 0) {
		// if near an item
		if (match->subtype & ST_NEARITEM) {
			// get the match variable
			trap_BotMatchVariable(match, ITEM, itemname, sizeof(itemname));

			if (!BotGetMessageTeamGoal(bs, itemname, &bs->teamgoal)) {
				// BotAI_BotInitialChat(bs, "cannotfind", itemname, NULL);
				// trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
				return;
			}
		}
	}

	if (bs->teamgoal.entitynum < 0) {
		if (other) {
			BotAI_BotInitialChat(bs, "whereis", teammate, NULL);
		} else {BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);}

		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// the team mate
	bs->teammate = client;
	// last time the team mate was assumed visible
	bs->teammatevisible_time = trap_AAS_Time();
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// get the team goal time
	bs->teamgoal_time = BotGetTime(match);
	// set the ltg type
	if (match->type == MSG_HELP) {
		bs->ltgtype = LTG_TEAMHELP;

		if (!bs->teamgoal_time) {
			bs->teamgoal_time = trap_AAS_Time() + TEAM_HELP_TIME;
		}
	} else {
		bs->ltgtype = LTG_TEAMACCOMPANY;

		if (!bs->teamgoal_time) {
			bs->teamgoal_time = trap_AAS_Time() + TEAM_ACCOMPANY_TIME;
		}

		bs->formation_dist = 3.5 * 32;     // 3.5 meter
		bs->arrive_time = 0;
	}
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Beispiel #7
0
/*
=======================================================================================================================================
BotGetPatrolWaypoints
=======================================================================================================================================
*/
int BotGetPatrolWaypoints(bot_state_t *bs, bot_match_t *match) {
	char keyarea[MAX_MESSAGE_SIZE];
	int patrolflags;
	bot_waypoint_t *wp, *newwp, *newpatrolpoints;
	bot_match_t keyareamatch;
	bot_goal_t goal;

	newpatrolpoints = NULL;
	patrolflags = 0;
	trap_BotMatchVariable(match, KEYAREA, keyarea, MAX_MESSAGE_SIZE);

	while (1) {
		if (!trap_BotFindMatch(keyarea, &keyareamatch, MTCONTEXT_PATROLKEYAREA)) {
			trap_EA_SayTeam(bs->client, "what do you say?");
			BotFreeWaypoints(newpatrolpoints);
			bs->patrolpoints = NULL;
			return qfalse;
		}

		trap_BotMatchVariable(&keyareamatch, KEYAREA, keyarea, MAX_MESSAGE_SIZE);

		if (!BotGetMessageTeamGoal(bs, keyarea, &goal)) {
			// BotAI_BotInitialChat(bs, "cannotfind", keyarea, NULL);
			// trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
			BotFreeWaypoints(newpatrolpoints);
			bs->patrolpoints = NULL;
			return qfalse;
		}
		// create a new waypoint
		newwp = BotCreateWayPoint(keyarea, goal.origin, goal.areanum);
		// add the waypoint to the patrol points
		newwp->next = NULL;

		for (wp = newpatrolpoints; wp && wp->next; wp = wp->next);

		if (!wp) {
			newpatrolpoints = newwp;
			newwp->prev = NULL;
		} else {
			wp->next = newwp;
			newwp->prev = wp;
		}

		if (keyareamatch.subtype & ST_BACK) {
			patrolflags = PATROL_LOOP;
			break;
		} else if (keyareamatch.subtype & ST_REVERSE) {
			patrolflags = PATROL_REVERSE;
			break;
		} else if (keyareamatch.subtype & ST_MORE) {
			trap_BotMatchVariable(&keyareamatch, MORE, keyarea, MAX_MESSAGE_SIZE);
		} else {
			break;
		}
	}

	if (!newpatrolpoints || !newpatrolpoints->next) {
		trap_EA_SayTeam(bs->client, "I need more key points to patrol\n");
		BotFreeWaypoints(newpatrolpoints);
		newpatrolpoints = NULL;
		return qfalse;
	}

	BotFreeWaypoints(bs->patrolpoints);
	bs->patrolpoints = newpatrolpoints;
	bs->curpatrolpoint = bs->patrolpoints;
	bs->patrolflags = patrolflags;
	return qtrue;
}
Beispiel #8
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_ENTERGAME
							|MTCONTEXT_INITIALTEAMCHAT
							|MTCONTEXT_CTF)) {
		return qfalse;
	}
	// react to the found message
	switch (match.type) {
	case MSG_HELP:                     // someone calling for help
	case MSG_ACCOMPANY:                // someone calling for company
	{
		BotMatch_HelpAccompany(bs, &match);
		break;
	}

	case MSG_DEFENDKEYAREA:            // teamplay defend a key area
	{
		BotMatch_DefendKeyArea(bs, &match);
		break;
	}

	case MSG_CAMP:                     // camp somewhere
	{
		BotMatch_Camp(bs, &match);
		break;
	}

	case MSG_PATROL:                   // patrol between several key areas
	{
		BotMatch_Patrol(bs, &match);
		break;
	}
#ifdef CTF
	case MSG_GETFLAG:                  // ctf get the enemy flag
	{
		BotMatch_GetFlag(bs, &match);
		break;
	}

	case MSG_RUSHBASE:                 // ctf rush to the base
	{
		BotMatch_RushBase(bs, &match);
		break;
	}

	case MSG_RETURNFLAG:
	{
		BotMatch_ReturnFlag(bs, &match);
		break;
	}
#endif // CTF
	case MSG_GETITEM:
	{
		BotMatch_GetItem(bs, &match);
		break;
	}

	case MSG_JOINSUBTEAM:              // join a sub team
	{
		BotMatch_JoinSubteam(bs, &match);
		break;
	}

	case MSG_LEAVESUBTEAM:             // leave a sub team
	{
		BotMatch_LeaveSubteam(bs, &match);
		break;
	}

	case MSG_WHICHTEAM:
	{
		BotMatch_WhichTeam(bs, &match);
		break;
	}

	case MSG_CHECKPOINT:               // remember a check point
	{
		BotMatch_CheckPoint(bs, &match);
		break;
	}

	case MSG_CREATENEWFORMATION:       // start the creation of a new formation
	{
		trap_EA_SayTeam(bs->client, "the part of my brain to create formations has been damaged");
		break;
	}

	case MSG_FORMATIONPOSITION:        // tell someone his / her position in the formation
	{
		trap_EA_SayTeam(bs->client, "the part of my brain to create formations has been damaged");
		break;
	}

	case MSG_FORMATIONSPACE:           // set the formation space
	{
		BotMatch_FormationSpace(bs, &match);
		break;
	}

	case MSG_DOFORMATION:              // form a certain formation
	{
		break;
	}

	case MSG_DISMISS:                  // dismiss someone
	{
		BotMatch_Dismiss(bs, &match);
		break;
	}

	case MSG_STARTTEAMLEADERSHIP:      // someone will become the team leader
	{
		BotMatch_StartTeamLeaderShip(bs, &match);
		break;
	}

	case MSG_STOPTEAMLEADERSHIP:       // someone will stop being the team leader
	{
		BotMatch_StopTeamLeaderShip(bs, &match);
		break;
	}

	case MSG_WHOISTEAMLAEDER:
	{
		BotMatch_WhoIsTeamLeader(bs, &match);
		break;
	}

	case MSG_WHATAREYOUDOING:          // ask a bot what he / she is doing
	{
		BotMatch_WhatAreYouDoing(bs, &match);
		break;
	}

	case MSG_WHATISMYCOMMAND:
	{
		BotMatch_WhatIsMyCommand(bs, &match);
		break;
	}

	case MSG_WHEREAREYOU:
	{
		BotMatch_WhereAreYou(bs, &match);
		break;
	}

	case MSG_LEADTHEWAY:
	{
		BotMatch_LeadTheWay(bs, &match);
		break;
	}

	case MSG_KILL:
	{
		BotMatch_Kill(bs, &match);
		break;
	}

	case MSG_ENTERGAME:                // someone entered the game
	{
		// NOTE: eliza chats will catch this
		// BotMatchVariable(&match, NETNAME, netname);
		// Com_sprintf(buf, sizeof(buf), "heya %s", netname);
		// EA_Say(bs->client, buf);
		break;
	}

	case MSG_CTF:
	{
		BotMatch_CTF(bs, &match);
		break;
	}

	case MSG_WAIT:
	{
		break;
	}

	default:
	{
		BotAI_Print(PRT_MESSAGE, "unknown match type\n");
		break;
	}
	}

	return qtrue;
}
/*
========================
BotMatch_PatrolWaypoints
========================
*/
qboolean BotMatch_PatrolWaypoints(bot_state_t *bs, bot_match_t *match, gentity_t *sender)
{
	char keyarea[MAX_MESSAGE_SIZE];
	int flags;
	bot_waypoint_t *new_wp, *last_wp, *new_patrol;
	bot_match_t keyareamatch;
	bot_goal_t goal;
	qboolean success;

	// Initialize new patrol to a zero length path
	last_wp = new_patrol = NULL;
	flags = 0;
	success = qfalse;

	// Match successive waypoints in the patrol path
	trap_BotMatchVariable(match, KEYAREA, keyarea, MAX_MESSAGE_SIZE);
	while (1)
	{
		// Fail if the bot can't match the area name
		if (!trap_BotFindMatch(keyarea, &keyareamatch, MTCONTEXT_PATROLKEYAREA)) {
			trap_EA_SayTeam(bs->client, "What did you say?");
			break;
		}

		// Fail if the bot can't find the requested area
		trap_BotMatchVariable(&keyareamatch, KEYAREA, keyarea, MAX_MESSAGE_SIZE);
		if (!GoalFromName(&goal, keyarea, bs))
			break;

		// Try to create a new waypoint
		new_wp = BotCreateWaypoint(keyarea);
		if (new_wp == NULL)
			break;

		// Copy the matched goal to the waypoint
		memcpy(&new_wp->goal, &goal, sizeof(bot_goal_t));

		// Insert waypoint into patrol point list
		new_wp->next = NULL;
		if (last_wp) {
			last_wp->next = new_wp;
			new_wp->prev = last_wp;
		} else {
			// First waypoint in list
			new_patrol = new_wp;
			new_wp->prev = NULL;
		}
		last_wp = new_wp;

		// Check for waypoint message completion
		if (keyareamatch.subtype & ST_REVERSE) {
			success = qtrue;
			flags = PATROL_REVERSE;
			break;
		}

		if (keyareamatch.subtype & ST_BACK) {
			success = qtrue;
			flags = PATROL_LOOP;
			break;
		}

		if ( !(keyareamatch.subtype & ST_MORE) ) {
			success = qtrue;
			flags = PATROL_LOOP;
			break;
		}

		trap_BotMatchVariable(&keyareamatch, MORE, keyarea, MAX_MESSAGE_SIZE);
	}

	// Make sure the bot has at least two patrol points
	if (success && (!new_patrol || !new_patrol->next) ) {
		trap_EA_SayTeam(bs->client, "I need more key points to patrol\n");
		success = qfalse;
	}

	// Check for message match failure
	if (!success) {
		BotFreeWaypoints(new_patrol);
		return qfalse;
	}

	// Free old waypoints and use new waypoints
	BotFreeWaypoints(bs->patrol);
	bs->patrol = new_patrol;
	bs->next_patrol = bs->patrol;
	bs->patrol_flags = flags;

	return qtrue;
}