// Generate a chat message from a specified message type, and return // the pointer of the generated message char *CChatManager::GenerateChat(CBaseBot *pClient, const char *type) { static char msg[256]; // for the chat message msg[0] = '\0'; // initialize the string unsigned short usCrc = CRC_Block((unsigned char *)type, strlen(type)); // find if we already have this section int found; for (found = 0; found < m_ChatItem.size(); found++) { if (m_ChatItem[found].type == usCrc) break; } if (found < m_ChatItem.size()) { char sz[256]; strncpy(sz, m_ChatItem[found].PickMessage(), 256); int length = strlen(sz); char *p = sz; while (p != NULL && *p) { if (*p == '%') { char type = *(++p); // skip to next character to get the type int hiscore = -9999, j, count; CClient *pPickedClient = NULL; char buffer[32]; switch (type) { case '%': strncat(msg, "%", 256); break; case 'n': // bot name strncpy(buffer, pClient->GetNetName(), 32); HumanizeName(buffer); strncat(msg, buffer, 256); // append it to the message break; case 'r': // random opponent j = RandomLong(0, g_pServer->GetMaxClients()); for (count = 0; count < g_pServer->GetMaxClients(); count++, j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p != pClient && p->IsValid()) { strncpy(buffer, p->GetNetName(), 32); HumanizeName(buffer); strncat(msg, buffer, 256); // append it to the message break; } } if (count >= g_pServer->GetMaxClients()) return NULL; // can't find any player, don't say anything break; case 'f': // opponent in first place for (j = 0; j < g_pServer->GetMaxClients(); j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p == pClient || !p->IsValid()) continue; if (p->GetFrags() >= hiscore) { hiscore = p->GetFrags(); pPickedClient = p; } } if (pPickedClient) { strncpy(buffer, pPickedClient->GetNetName(), 32); HumanizeName(buffer); // humanize the name strncat(msg, buffer, 256); // append it to the message } else { return NULL; // can't find such a player, don't say anything } break; case 'l': // opponent in last place hiscore = 9999; for (j = 0; j < g_pServer->GetMaxClients(); j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p == pClient || !p->IsValid()) continue; if (p->GetFrags() <= hiscore) { hiscore = p->GetFrags(); pPickedClient = p; } } if (pPickedClient) { strncpy(buffer, pPickedClient->GetNetName(), 32); HumanizeName(buffer); // humanize the name strncat(msg, buffer, 256); // append it to the message } else { return NULL; // can't find such a player, don't say anything } break; case 'm': // map title strncat(msg, g_pServer->GetMapName(), 256); // get the map name break; case 'v': // last victim of this bot if (pClient->Chat()->m_strLastVictim.length() <= 0) return NULL; // we don't have a victim yet, don't say anything strncat(msg, pClient->Chat()->m_strLastVictim.c_str(), 256); break; case 'k': // last player killed this bot if (pClient->Chat()->m_strLastKiller.length() <= 0) return NULL; // this bot hasn't been killed yet, don't say anything strncat(msg, pClient->Chat()->m_strLastKiller.c_str(), 256); break; } p++; // skip to the next character continue; } char *prev = p; p = strchr(p, '%'); // search for the next "%" sign if (p) { *p = '\0'; // if found, terminate the string } strncat(msg, prev, 256); // append the remaining text if (p) { *p = '%'; // restore the '%' } } HumanizeChat(msg); // 'Humanize' the chat message return msg; } return NULL; // not found }
// Generate a reply message from the input message, and return the // pointer of the reply message char *CChatManager::GenerateReply(CBaseBot *pClient, CClient *pFrom, const char *msg) { static char message[256]; // for the reply message message[0] = '\0'; // initialize the string char *p; int i; // find a reply block with the correct keyword for (i = 0; i < m_ChatReply.size(); i++) { if (m_ChatReply[i].IsValidReply(msg)) break; } if (i >= m_ChatReply.size()) { // no replies for this sentence are found if (RandomLong(1, 100) > 50) { // about half the time use a general reply if ((p = GenerateChat(pClient, "GENERAL_REPLIES")) != NULL) { strncpy(message, p, 256); } else { return NULL; // No general replies } } else { return NULL; // don't reply to this message } } else { // we have replies for this sentence, generate the message now p = (char *)m_ChatReply[i].PickMessage(); if (!p) { return NULL; // no message is available, don't proceed } while (p && *p) { if (*p == '%') { char type = *(++p); // skip to next character to get the type int hiscore = -9999, j, count; CClient *pPickedClient = NULL; char buffer[32]; switch (type) { case '%': strncat(message, "%", 256); break; case 'n': // bot name strncpy(buffer, pClient->GetNetName(), 32); HumanizeName(buffer); strncat(message, buffer, 256); // append it to the message break; case 'r': // random opponent j = RandomLong(0, g_pServer->GetMaxClients()); for (count = 0; count < g_pServer->GetMaxClients(); count++, j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p != pClient && p->IsValid()) { strncpy(buffer, p->GetNetName(), 32); HumanizeName(buffer); strncat(message, buffer, 256); // append it to the message break; } } if (count >= g_pServer->GetMaxClients()) return NULL; // can't find any player, don't say anything break; case 'f': // opponent in first place for (j = 0; j < g_pServer->GetMaxClients(); j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p == pClient || !p->IsValid()) continue; if (p->GetFrags() >= hiscore) { hiscore = p->GetFrags(); pPickedClient = p; } } if (pPickedClient) { strncpy(buffer, pPickedClient->GetNetName(), 32); HumanizeName(buffer); // humanize the name strncat(message, buffer, 256); // append it to the message } else { return NULL; // can't find such a player, don't say anything } break; case 'l': // opponent in last place hiscore = 9999; for (j = 0; j < g_pServer->GetMaxClients(); j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p == pClient || !p->IsValid()) continue; if (p->GetFrags() <= hiscore) { hiscore = p->GetFrags(); pPickedClient = p; } } if (pPickedClient) { strncpy(buffer, pPickedClient->GetNetName(), 32); HumanizeName(buffer); // humanize the name strncat(message, buffer, 256); // append it to the message } else { return NULL; // can't find such a player, don't say anything } break; case 'v': // last victim of this bot if (pClient->Chat()->m_strLastVictim.length() <= 0) return NULL; // we don't have a victim yet strncat(message, pClient->Chat()->m_strLastVictim.c_str(), 256); break; case 'k': // last player killed this bot if (pClient->Chat()->m_strLastKiller.length() <= 0) return NULL; // this bot hasn't been killed yet strncat(message, pClient->Chat()->m_strLastKiller.c_str(), 256); break; case 'm': // map title strncat(message, g_pServer->GetMapName(), 256); // get the map name break; // reply specific items case 's': // player to reply strncat(message, pFrom->GetNetName(), 256); break; } p++; // skip to the next character continue; } char *prev = p; p = strchr(p, '%'); // search for the next "%" sign if (p) { *p = '\0'; // if found, terminate the string } strncat(message, prev, 256); // append the remaining text if (p) { *p = '%'; // restore the '%' } } HumanizeChat(message); // 'humanize' the chat message } return message; // return the message }
bool CBaseBot::FindEnemy() { // check if the health is decreased bool fHealthDecreased = m_iPrevHealth > GetHealth(); m_iPrevHealth = GetHealth(); // store away the current health value float cur_dist; if (m_pEnemy && (!m_pEnemy->IsValid() || !m_pEnemy->IsAlive())) m_pEnemy = NULL; // null out the enemy pointer as it's no longer valid Vector vecHisPos; unsigned char cHit; // see if we can still see the current enemy... if (m_pEnemy) { if (FBoxVisible(m_pEnemy, &vecHisPos, &cHit)) { m_vecEnemy = vecHisPos; m_ucVisibility = cHit; } else { m_pEnemy = NULL; // we can no longer see this enemy } } // if we already have an enemy... if (m_pEnemy) { // don't discard important enemies (bomb/flag/hostage carrier, VIP, etc) if (g_pServer->ClientIsImportant(EnemyClient())) return false; // calculate the distance to the enemy cur_dist = (m_pEnemy->GetOrigin() - GetOrigin()).Length(); } else { cur_dist = FLT_MAX; // just some crazy value } // loop through all the clients... for (int i = 0; i < g_pServer->GetMaxClients(); i++) { if (i == entindex() - 1 || (m_pEnemy && i == m_pEnemy->entindex() - 1)) continue; // skip myself and the current enemy CClient *pClient = g_pServer->m_rgpClients[i]; if (!pClient || !pClient->IsValid() || !pClient->IsAlive()) continue; float dist = (pClient->GetOrigin() - GetOrigin()).Length(); // if this enemy is further away than the current one... if (dist > cur_dist && !g_pServer->ClientIsImportant(pClient)) continue; // skip it if (dist > 900 + 4000 * ((GetDifficulty() - 1) / 4.0)) continue; // enemy is too far if (g_pServer->IsTeamplay() && GetTeam() == g_pServer->GetTeam(pClient)) continue; // skip our teammates float fov; // if the bot's health decreased or the enemy is shooting if (!m_pEnemy && (fHealthDecreased || pClient->IsShooting())) fov = 360; else fov = GetFov() * 2 - (GetFov() - (dist > GetFov() * 9 ? GetFov() * 9 : dist) / 9); // check if enemy is in the view cone if (!FInViewCone(pClient, fov)) continue; // enemy isn't in bot's view cone // check if enemy is visible if (!FBoxVisible(pClient, &vecHisPos, &cHit)) { continue; // skip this enemy } // if the enemy is quite far away, not shooting and the bot is not damaged if (!m_pEnemy && dist > 200 && !fHealthDecreased && !pClient->IsShooting()) { // if the bot isn't in the fov of the enemy and the bot doesn't really want to fight if (!pClient->FInViewCone(this, 120) /*&& BotWantsToRetreat()*/) continue; // skip this enemy } m_pEnemy = pClient; // found a new enemy m_vecEnemy = vecHisPos; m_ucVisibility = cHit; DebugMsg(DEBUG_BOTCOMBAT, "Found new enemy: %s", m_pEnemy->GetNetName()); return true; } return false; // no new enemy is found }