void AIClientApp::HandlePythonAICrash() { // Note: If python crashed during initialization then the AI has not // been associated with a PlayerConnection so the server will not // know the AI's PlayerName. std::stringstream err_msg; err_msg << "AIClientApp failed due to error in python AI code for " << PlayerName() << ". Exiting Soon."; ErrorLogger() << err_msg.str() << " id = " << PlayerID(); Networking().SendMessage( ErrorMessage(str(FlexibleFormat(UserString("ERROR_PYTHON_AI_CRASHED")) % PlayerName()) , true)); }
/* ================== FindPlayerByName ================== */ int FindPlayerByName(char *name) { int i; char buf[MAX_INFO_STRING]; for (i = 0; i < level.maxplayers; i++) { PlayerName(i, buf, sizeof(buf)); if (!Q_stricmp(buf, name)) return i; } for (i = 0; i < level.maxplayers; i++) { PlayerName(i, buf, sizeof(buf)); if (stristr(buf, name)) return i; } return -1; }
// static member(s) AIClientApp::AIClientApp(const std::vector<std::string>& args) : m_player_name(""), m_max_aggression(0) { if (args.size() < 2) { std::cerr << "The AI client should not be executed directly! Run freeorion to start the game."; ExitApp(1); } // read command line args m_player_name = args.at(1); if (args.size() >=3) { m_max_aggression = boost::lexical_cast<int>(args.at(2)); } // Force the log file if requested. if (GetOptionsDB().Get<std::string>("log-file").empty()) { const std::string AICLIENT_LOG_FILENAME((GetUserDataDir() / (m_player_name + ".log")).string()); GetOptionsDB().Set("log-file", AICLIENT_LOG_FILENAME); } // Force the log threshold if requested. auto force_log_level = GetOptionsDB().Get<std::string>("log-level"); if (!force_log_level.empty()) OverrideAllLoggersThresholds(to_LogLevel(force_log_level)); InitLoggingSystem(GetOptionsDB().Get<std::string>("log-file"), "AI"); InitLoggingOptionsDBSystem(); InfoLogger() << FreeOrionVersionString(); DebugLogger() << PlayerName() + " ai client initialized."; }
/* ================== FindEnemyByName ================== */ int FindEnemyByName(bot_state_t *bs, char *name) { int i; char buf[MAX_INFO_STRING]; for (i = 0; i < level.maxplayers; i++) { if (BotSameTeam(bs, i)) continue; PlayerName(i, buf, sizeof(buf)); if (!Q_stricmp(buf, name)) return i; } for (i = 0; i < level.maxplayers; i++) { if (BotSameTeam(bs, i)) continue; PlayerName(i, buf, sizeof(buf)); if (stristr(buf, name)) return i; } return -1; }
/* ================== BotMatch_WhatIsMyCommand ================== */ void BotMatch_WhatIsMyCommand(bot_state_t *bs, bot_match_t *match) { char netname[MAX_NETNAME]; PlayerName(bs->playernum, netname, sizeof(netname)); if (Q_stricmp(netname, bs->teamleader) != 0) return; bs->forceorders = qtrue; }
/* ================== BotChat_HitNoKill ================== */ int BotChat_HitNoKill(bot_state_t *bs) { char name[32], *weap; float rnd; aas_entityinfo_t entinfo; if (bot_nochat.integer) return qfalse; if (bs->lastchat_time > FloatTime() - TIME_BETWEENCHATTING) return qfalse; if (BotNumActivePlayers() <= 1) return qfalse; rnd = Characteristic_BFloat(bs->character, CHARACTERISTIC_CHAT_HITNOKILL, 0, 1); //don't chat in teamplay if (TeamPlayIsOn()) return qfalse; // don't chat in tournament mode if (gametype == GT_TOURNAMENT) return qfalse; //if fast chat is off if (!bot_fastchat.integer) { if (random() > rnd * 0.5) return qfalse; } if (!BotValidChatPosition(bs)) return qfalse; // if (BotVisibleEnemies(bs)) return qfalse; // BotEntityInfo(bs->enemy, &entinfo); if (EntityIsShooting(&entinfo)) return qfalse; // PlayerName(bs->enemy, name, sizeof(name)); weap = BotWeaponNameForMeansOfDeath(g_entities[bs->enemy].player->lasthurt_mod); // BotAI_BotInitialChat(bs, "hit_nokill", name, weap, NULL); bs->lastchat_time = FloatTime(); bs->chatto = CHAT_ALL; return qtrue; }
/* ================== BotChat_HitTalking ================== */ int BotChat_HitTalking(bot_state_t *bs) { char name[32], *weap; int lasthurt_player; float rnd; if (bot_nochat.integer) return qfalse; if (bs->lastchat_time > FloatTime() - TIME_BETWEENCHATTING) return qfalse; if (BotNumActivePlayers() <= 1) return qfalse; lasthurt_player = g_entities[bs->playernum].player->lasthurt_player; if (!lasthurt_player) return qfalse; if (lasthurt_player == bs->playernum) return qfalse; // if (lasthurt_player < 0 || lasthurt_player >= MAX_CLIENTS) return qfalse; // rnd = Characteristic_BFloat(bs->character, CHARACTERISTIC_CHAT_HITTALKING, 0, 1); //don't chat in teamplay if (TeamPlayIsOn()) return qfalse; // don't chat in tournament mode if (gametype == GT_TOURNAMENT) return qfalse; //if fast chat is off if (!bot_fastchat.integer) { if (random() > rnd * 0.5) return qfalse; } if (!BotValidChatPosition(bs)) return qfalse; // PlayerName(g_entities[bs->playernum].player->lasthurt_player, name, sizeof(name)); weap = BotWeaponNameForMeansOfDeath(g_entities[bs->playernum].player->lasthurt_mod); // BotAI_BotInitialChat(bs, "hit_talking", name, weap, NULL); bs->lastchat_time = FloatTime(); bs->chatto = CHAT_ALL; return qtrue; }
/* ================== BotVoiceChat_StopLeader ================== */ void BotVoiceChat_StopLeader(bot_state_t *bs, int playernum, int mode) { char netname[MAX_MESSAGE_SIZE]; if (!Q_stricmp(bs->teamleader, PlayerName(playernum, netname, sizeof(netname)))) { bs->teamleader[0] = '\0'; notleader[playernum] = qtrue; } }
/* ================== 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 playerNum; bot_match_t addresseematch; BotMatchVariable(match, NETNAME, netname, sizeof(netname)); playerNum = PlayerOnSameTeamFromName(bs, netname); if (playerNum < 0) return qfalse; //if the message is addressed to someone if (match->subtype & ST_ADDRESSED) { BotMatchVariable(match, ADDRESSEE, addressedto, sizeof(addressedto)); //the name of this bot PlayerName(bs->playernum, botname, 128); // while(BotFindMatch(addressedto, &addresseematch, MTCONTEXT_ADDRESSEE)) { if (addresseematch.type == MSG_EVERYONE) { return qtrue; } else if (addresseematch.type == MSG_MULTIPLENAMES) { BotMatchVariable(&addresseematch, TEAMMATE, name, sizeof(name)); if (strlen(name)) { if (stristr(botname, name)) return qtrue; if (stristr(bs->subteam, name)) return qtrue; } BotMatchVariable(&addresseematch, MORE, addressedto, MAX_MESSAGE_SIZE); } else { 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); //EA_Say(bs->playernum, buf); return qfalse; } else { bot_match_t tellmatch; tellmatch.type = 0; //if this message wasn't directed solely to this bot if (!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; }
/* ================== BotMatch_WhoIsTeamLeader ================== */ void BotMatch_WhoIsTeamLeader(bot_state_t *bs, bot_match_t *match) { char netname[MAX_MESSAGE_SIZE]; if (!TeamPlayIsOn()) return; PlayerName(bs->playernum, netname, sizeof(netname)); //if this bot IS the team leader if (!Q_stricmp(netname, bs->teamleader)) { EA_SayTeam(bs->playernum, "I'm the team leader\n"); } }
/* ================== BotVoiceChat_WhoIsLeader ================== */ void BotVoiceChat_WhoIsLeader(bot_state_t *bs, int playernum, int mode) { char netname[MAX_MESSAGE_SIZE]; if (!TeamPlayIsOn()) return; PlayerName(bs->playernum, netname, sizeof(netname)); //if this bot IS the team leader if (!Q_stricmp(netname, bs->teamleader)) { BotAI_BotInitialChat(bs, "iamteamleader", NULL); BotEnterChat(bs->cs, 0, CHAT_TEAM); BotVoiceChatOnly(bs, -1, VOICECHAT_STARTLEADER); } }
void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) { cCSLock Lock(m_CSPacket); AString PlayerName(a_Player.GetColor()); PlayerName.append(a_Player.GetName()); if (PlayerName.length() > 14) { PlayerName.erase(14); } PlayerName += cChatColor::White; WriteByte ((unsigned char)PACKET_PLAYER_LIST_ITEM); WriteString(PlayerName); WriteBool (a_IsOnline); WriteShort (a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0); Flush(); }
/* ================== BotMatch_StartTeamLeaderShip ================== */ void BotMatch_StartTeamLeaderShip(bot_state_t *bs, bot_match_t *match) { int playernum; char teammate[MAX_MESSAGE_SIZE]; if (!TeamPlayIsOn()) return; //if chats for him or herself if (match->subtype & ST_I) { //get the team mate that will be the team leader BotMatchVariable(match, NETNAME, teammate, sizeof(teammate)); strncpy(bs->teamleader, teammate, sizeof(bs->teamleader)); bs->teamleader[sizeof(bs->teamleader)-1] = '\0'; } //chats for someone else else { //get the team mate that will be the team leader BotMatchVariable(match, TEAMMATE, teammate, sizeof(teammate)); playernum = FindPlayerByName(teammate); if (playernum >= 0) PlayerName(playernum, bs->teamleader, sizeof(bs->teamleader)); } }
/* ================== BotMatch_TaskPreference ================== */ void BotMatch_TaskPreference(bot_state_t *bs, bot_match_t *match) { char netname[MAX_NETNAME]; char teammatename[MAX_MESSAGE_SIZE]; int teammate, preference; PlayerName(bs->playernum, netname, sizeof(netname)); if (Q_stricmp(netname, bs->teamleader) != 0) return; BotMatchVariable(match, NETNAME, teammatename, sizeof(teammatename)); teammate = PlayerFromName(teammatename); if (teammate < 0) return; preference = BotGetTeamMateTaskPreference(bs, teammate); switch(match->subtype) { case ST_DEFENDER: { preference &= ~TEAMTP_ATTACKER; preference |= TEAMTP_DEFENDER; break; } case ST_ATTACKER: { preference &= ~TEAMTP_DEFENDER; preference |= TEAMTP_ATTACKER; break; } case ST_ROAMER: { preference &= ~(TEAMTP_ATTACKER|TEAMTP_DEFENDER); break; } } BotSetTeamMateTaskPreference(bs, teammate, preference); // EasyPlayerName(teammate, teammatename, sizeof(teammatename)); BotAI_BotInitialChat(bs, "keepinmind", teammatename, NULL); BotEnterChat(bs->cs, teammate, CHAT_TELL); BotVoiceChatOnly(bs, teammate, VOICECHAT_YES); EA_Action(bs->playernum, ACTION_AFFIRMATIVE); }
void AIClientApp::Run() { ConnectToServer(); try { StartPythonAI(); // join game Networking().SendMessage(JoinGameMessage(PlayerName(), Networking::CLIENT_TYPE_AI_PLAYER, boost::uuids::nil_uuid())); // Start parsing content StartBackgroundParsing(); // respond to messages until disconnected while (1) { try { if (!Networking().IsRxConnected()) break; if (const auto msg = Networking().GetMessage()) HandleMessage(*msg); else std::this_thread::sleep_for(std::chrono::milliseconds(10)); } catch (const boost::python::error_already_set&) { /* If the python interpreter is still running then keep going, otherwise exit.*/ m_AI->HandleErrorAlreadySet(); if (!m_AI->IsPythonRunning()) throw; } } } catch (const NormalExitException&) { // intentionally empty. } catch (const boost::python::error_already_set&) { HandlePythonAICrash(); } Networking().DisconnectFromServer(); }
/* ================== 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); }
/* ================== BotMatch_StopTeamLeaderShip ================== */ void BotMatch_StopTeamLeaderShip(bot_state_t *bs, bot_match_t *match) { int playernum; char teammate[MAX_MESSAGE_SIZE]; char netname[MAX_MESSAGE_SIZE]; if (!TeamPlayIsOn()) return; //get the team mate that stops being the team leader BotMatchVariable(match, TEAMMATE, teammate, sizeof(teammate)); //if chats for him or herself if (match->subtype & ST_I) { BotMatchVariable(match, NETNAME, netname, sizeof(netname)); playernum = FindPlayerByName(netname); } //chats for someone else else { playernum = FindPlayerByName(teammate); } //end else if (playernum >= 0) { if (!Q_stricmp(bs->teamleader, PlayerName(playernum, netname, sizeof(netname)))) { bs->teamleader[0] = '\0'; notleader[playernum] = qtrue; } } }
/* ================== BotVoiceChat_StartLeader ================== */ void BotVoiceChat_StartLeader(bot_state_t *bs, int playernum, int mode) { PlayerName(playernum, bs->teamleader, sizeof(bs->teamleader)); }
/* ================== BotChatTest ================== */ void BotChatTest(bot_state_t *bs) { char name[32]; char *weap; int num, i; num = BotNumInitialChats(bs->cs, "game_enter"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "game_enter", EasyPlayerName(bs->playernum, name, 32), // 0 BotRandomOpponentName(bs), // 1 "[invalid var]", // 2 "[invalid var]", // 3 BotMapTitle(), // 4 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "game_exit"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "game_exit", EasyPlayerName(bs->playernum, name, 32), // 0 BotRandomOpponentName(bs), // 1 "[invalid var]", // 2 "[invalid var]", // 3 BotMapTitle(), // 4 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "level_start"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "level_start", EasyPlayerName(bs->playernum, name, 32), // 0 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "level_end_victory"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "level_end_victory", EasyPlayerName(bs->playernum, name, 32), // 0 BotRandomOpponentName(bs), // 1 BotFirstPlayerInRankings(), // 2 BotLastPlayerInRankings(), // 3 BotMapTitle(), // 4 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "level_end_lose"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "level_end_lose", EasyPlayerName(bs->playernum, name, 32), // 0 BotRandomOpponentName(bs), // 1 BotFirstPlayerInRankings(), // 2 BotLastPlayerInRankings(), // 3 BotMapTitle(), // 4 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "level_end"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "level_end", EasyPlayerName(bs->playernum, name, 32), // 0 BotRandomOpponentName(bs), // 1 BotFirstPlayerInRankings(), // 2 BotLastPlayerInRankings(), // 3 BotMapTitle(), // 4 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } EasyPlayerName(bs->lastkilledby, name, sizeof(name)); num = BotNumInitialChats(bs->cs, "death_drown"); for (i = 0; i < num; i++) { // BotAI_BotInitialChat(bs, "death_drown", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_slime"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_slime", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_lava"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_lava", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_cratered"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_cratered", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_suicide"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_suicide", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_telefrag"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_telefrag", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_gauntlet"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_gauntlet", name, // 0 BotWeaponNameForMeansOfDeath(bs->botdeathtype), // 1 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_rail"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_rail", name, // 0 BotWeaponNameForMeansOfDeath(bs->botdeathtype), // 1 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_bfg"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_bfg", name, // 0 BotWeaponNameForMeansOfDeath(bs->botdeathtype), // 1 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_insult"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_insult", name, // 0 BotWeaponNameForMeansOfDeath(bs->botdeathtype), // 1 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "death_praise"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "death_praise", name, // 0 BotWeaponNameForMeansOfDeath(bs->botdeathtype), // 1 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } // EasyPlayerName(bs->lastkilledplayer, name, 32); // num = BotNumInitialChats(bs->cs, "kill_gauntlet"); for (i = 0; i < num; i++) { // BotAI_BotInitialChat(bs, "kill_gauntlet", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "kill_rail"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "kill_rail", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "kill_telefrag"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "kill_telefrag", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "kill_insult"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "kill_insult", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "kill_praise"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "kill_praise", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "enemy_suicide"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "enemy_suicide", name, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } PlayerName(g_entities[bs->playernum].player->lasthurt_player, name, sizeof(name)); weap = BotWeaponNameForMeansOfDeath(g_entities[bs->playernum].player->lasthurt_player); num = BotNumInitialChats(bs->cs, "hit_talking"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "hit_talking", name, weap, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "hit_nodeath"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "hit_nodeath", name, weap, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "hit_nokill"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "hit_nokill", name, weap, NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } // if (bs->lastkilledplayer == bs->playernum) { strcpy(name, BotRandomOpponentName(bs)); } else { EasyPlayerName(bs->lastkilledplayer, name, sizeof(name)); } // num = BotNumInitialChats(bs->cs, "random_misc"); for (i = 0; i < num; i++) { // BotAI_BotInitialChat(bs, "random_misc", BotRandomOpponentName(bs), // 0 name, // 1 "[invalid var]", // 2 "[invalid var]", // 3 BotMapTitle(), // 4 BotRandomWeaponName(), // 5 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } num = BotNumInitialChats(bs->cs, "random_insult"); for (i = 0; i < num; i++) { BotAI_BotInitialChat(bs, "random_insult", BotRandomOpponentName(bs), // 0 name, // 1 "[invalid var]", // 2 "[invalid var]", // 3 BotMapTitle(), // 4 BotRandomWeaponName(), // 5 NULL); BotEnterChat(bs->cs, 0, CHAT_ALL); } }
/* ================== BotMatch_WhatAreYouDoing ================== */ void BotMatch_WhatAreYouDoing(bot_state_t *bs, bot_match_t *match) { char netname[MAX_MESSAGE_SIZE]; char goalname[MAX_MESSAGE_SIZE]; int playernum; //if not addressed to this bot if (!BotAddressedToBot(bs, match)) return; // switch(bs->ltgtype) { case LTG_TEAMHELP: { EasyPlayerName(bs->teammate, netname, sizeof(netname)); BotAI_BotInitialChat(bs, "helping", netname, NULL); break; } case LTG_TEAMACCOMPANY: { EasyPlayerName(bs->teammate, netname, sizeof(netname)); BotAI_BotInitialChat(bs, "accompanying", netname, NULL); break; } case LTG_DEFENDKEYAREA: { BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname)); BotAI_BotInitialChat(bs, "defending", goalname, NULL); break; } case LTG_GETITEM: { BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname)); BotAI_BotInitialChat(bs, "gettingitem", goalname, NULL); break; } case LTG_KILL: { PlayerName(bs->teamgoal.entitynum, netname, sizeof(netname)); BotAI_BotInitialChat(bs, "killing", netname, NULL); break; } case LTG_CAMP: case LTG_CAMPORDER: { BotAI_BotInitialChat(bs, "camping", NULL); break; } case LTG_PATROL: { BotAI_BotInitialChat(bs, "patrolling", NULL); break; } case LTG_GETFLAG: { BotAI_BotInitialChat(bs, "capturingflag", NULL); break; } case LTG_RUSHBASE: { BotAI_BotInitialChat(bs, "rushingbase", NULL); break; } case LTG_RETURNFLAG: { BotAI_BotInitialChat(bs, "returningflag", NULL); break; } #ifdef MISSIONPACK case LTG_ATTACKENEMYBASE: { BotAI_BotInitialChat(bs, "attackingenemybase", NULL); break; } case LTG_HARVEST: { BotAI_BotInitialChat(bs, "harvesting", NULL); break; } #endif default: { BotAI_BotInitialChat(bs, "roaming", NULL); break; } } //chat what the bot is doing BotMatchVariable(match, NETNAME, netname, sizeof(netname)); playernum = PlayerFromName(netname); BotEnterChat(bs->cs, playernum, CHAT_TELL); }
/* ================== BotPrintTeamGoal ================== */ void BotPrintTeamGoal(bot_state_t *bs) { char netname[MAX_NETNAME]; float t; if (!bot_showteamgoals.integer) { return; } PlayerName(bs->playernum, netname, sizeof(netname)); t = bs->teamgoal_time - FloatTime(); 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; } #ifdef MISSIONPACK case LTG_ATTACKENEMYBASE: { BotAI_Print(PRT_MESSAGE, "%s: I'm gonna attack the enemy base for %1.0f secs\n", netname, t); break; } case LTG_HARVEST: { BotAI_Print(PRT_MESSAGE, "%s: I'm gonna harvest for %1.0f secs\n", netname, t); break; } #endif 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 > FloatTime()) { t = bs->ctfroam_time - FloatTime(); 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); } } } }
/* ================== BotSetInfoConfigString ================== */ void BotSetInfoConfigString(bot_state_t *bs) { char goalname[MAX_MESSAGE_SIZE]; char netname[MAX_MESSAGE_SIZE]; char action[MAX_MESSAGE_SIZE]; char *leader, carrying[32], *cs; bot_goal_t goal; // PlayerName(bs->playernum, netname, sizeof(netname)); if (Q_stricmp(netname, bs->teamleader) == 0) leader = "L"; else leader = ""; strcpy(carrying, ""); if (gametype == GT_CTF) { if (BotCTFCarryingFlag(bs)) { strcpy(carrying, "F"); } } #ifdef MISSIONPACK else if (gametype == GT_1FCTF) { if (Bot1FCTFCarryingFlag(bs)) { strcpy(carrying, "F"); } } else if (gametype == GT_HARVESTER) { if (BotHarvesterCarryingCubes(bs)) { if (BotTeam(bs) == TEAM_RED) Com_sprintf(carrying, sizeof(carrying), "%2d", bs->inventory[INVENTORY_REDCUBE]); else Com_sprintf(carrying, sizeof(carrying), "%2d", bs->inventory[INVENTORY_BLUECUBE]); } } #endif switch(bs->ltgtype) { case LTG_TEAMHELP: { EasyPlayerName(bs->teammate, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "helping %s", goalname); break; } case LTG_TEAMACCOMPANY: { EasyPlayerName(bs->teammate, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "accompanying %s", goalname); break; } case LTG_DEFENDKEYAREA: { BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "defending %s", goalname); break; } case LTG_GETITEM: { BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "getting item %s", goalname); break; } case LTG_KILL: { PlayerName(bs->teamgoal.entitynum, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "killing %s", goalname); break; } case LTG_CAMP: case LTG_CAMPORDER: { Com_sprintf(action, sizeof(action), "camping"); break; } case LTG_PATROL: { Com_sprintf(action, sizeof(action), "patrolling"); break; } case LTG_GETFLAG: { Com_sprintf(action, sizeof(action), "capturing flag"); break; } case LTG_RUSHBASE: { Com_sprintf(action, sizeof(action), "rushing base"); break; } case LTG_RETURNFLAG: { Com_sprintf(action, sizeof(action), "returning flag"); break; } case LTG_ATTACKENEMYBASE: { Com_sprintf(action, sizeof(action), "attacking the enemy base"); break; } case LTG_HARVEST: { Com_sprintf(action, sizeof(action), "harvesting"); break; } default: { BotGetTopGoal(bs->gs, &goal); BotGoalName(goal.number, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "roaming %s", goalname); break; } } cs = va("l\\%s\\c\\%s\\a\\%s\\n\\%s", leader, carrying, action, bs->ainodename); trap_SetConfigstring (CS_BOTINFO + bs->playernum, cs); }
AIClientApp::~AIClientApp() { Networking().DisconnectFromServer(); DebugLogger() << "AIClientApp exited cleanly for ai client " << PlayerName(); }