예제 #1
0
// 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
}
예제 #2
0
// 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
}
예제 #3
0
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
}