// // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Copyright (c) YaPB Development Team. // // This software is licensed under the BSD-style license. // Additional exceptions apply. For full license details, see LICENSE.txt or visit: // http://yapb.jeefo.net/license // #include NetworkMsg::NetworkMsg (void) { m_message = NETMSG_UNDEFINED; m_state = 0; m_bot = NULL; for (int i = 0; i < NETMSG_NUM; i++) m_registerdMessages[i] = -1; } void NetworkMsg::HandleMessageIfRequired (int messageType, int requiredType) { if (messageType == m_registerdMessages[requiredType]) SetMessage (requiredType); } void NetworkMsg::Execute (void *p) { if (m_message == NETMSG_UNDEFINED) return; // no message or not for bot, return // some needed variables static byte r, g, b; static byte enabled; static int damageArmor, damageTaken, damageBits; static int killerIndex, victimIndex, playerIndex; static int index, numPlayers; static int state, id, clip; static Vector damageOrigin; static WeaponProperty weaponProp; // now starts of netmessage execution switch (m_message) { case NETMSG_VGUI: // this message is sent when a VGUI menu is displayed. if (m_state == 0) { switch (PTR_TO_INT (p)) { case VMS_TEAM: m_bot->m_startAction = GSM_TEAM_SELECT; break; case VMS_TF: case VMS_CT: m_bot->m_startAction = GSM_CLASS_SELECT; break; } } break; case NETMSG_SHOWMENU: // this message is sent when a text menu is displayed. if (m_state < 3) // ignore first 3 fields of message break; if (strcmp (PTR_TO_STR (p), "#Team_Select") == 0) // team select menu? m_bot->m_startAction = GSM_TEAM_SELECT; else if (strcmp (PTR_TO_STR (p), "#Team_Select_Spect") == 0) // team select menu? m_bot->m_startAction = GSM_TEAM_SELECT; else if (strcmp (PTR_TO_STR (p), "#IG_Team_Select_Spect") == 0) // team select menu? m_bot->m_startAction = GSM_TEAM_SELECT; else if (strcmp (PTR_TO_STR (p), "#IG_Team_Select") == 0) // team select menu? m_bot->m_startAction = GSM_TEAM_SELECT; else if (strcmp (PTR_TO_STR (p), "#IG_VIP_Team_Select") == 0) // team select menu? m_bot->m_startAction = GSM_TEAM_SELECT; else if (strcmp (PTR_TO_STR (p), "#IG_VIP_Team_Select_Spect") == 0) // team select menu? m_bot->m_startAction = GSM_TEAM_SELECT; else if (strcmp (PTR_TO_STR (p), "#Terrorist_Select") == 0) // T model select? m_bot->m_startAction = GSM_CLASS_SELECT; else if (strcmp (PTR_TO_STR (p), "#CT_Select") == 0) // CT model select menu? m_bot->m_startAction = GSM_CLASS_SELECT; break; case NETMSG_WEAPONLIST: // this message is sent when a client joins the game. All of the weapons are sent with the weapon ID and information about what ammo is used. switch (m_state) { case 0: strncpy (weaponProp.className, PTR_TO_STR (p), SIZEOF_CHAR (weaponProp.className)); break; case 1: weaponProp.ammo1 = PTR_TO_INT (p); // ammo index 1 break; case 2: weaponProp.ammo1Max = PTR_TO_INT (p); // max ammo 1 break; case 5: weaponProp.slotID = PTR_TO_INT (p); // slot for this weapon break; case 6: weaponProp.position = PTR_TO_INT (p); // position in slot break; case 7: weaponProp.id = PTR_TO_INT (p); // weapon ID break; case 8: weaponProp.flags = PTR_TO_INT (p); // flags for weapon (WTF???) g_weaponDefs[weaponProp.id] = weaponProp; // store away this weapon with it's ammo information... break; } break; case NETMSG_CURWEAPON: // this message is sent when a weapon is selected (either by the bot chosing a weapon or by the server auto assigning the bot a weapon). In CS it's also called when Ammo is increased/decreased switch (m_state) { case 0: state = PTR_TO_INT (p); // state of the current weapon (WTF???) break; case 1: id = PTR_TO_INT (p); // weapon ID of current weapon break; case 2: clip = PTR_TO_INT (p); // ammo currently in the clip for this weapon if (id <= 31) { if (state != 0) m_bot->m_currentWeapon = id; // ammo amount decreased ? must have fired a bullet... if (id == m_bot->m_currentWeapon && m_bot->m_ammoInClip[id] > clip) m_bot->m_timeLastFired = engine.Time (); // remember the last bullet time m_bot->m_ammoInClip[id] = clip; } break; } break; case NETMSG_AMMOX: // this message is sent whenever ammo amounts are adjusted (up or down). NOTE: Logging reveals that CS uses it very unreliable! switch (m_state) { case 0: index = PTR_TO_INT (p); // ammo index (for type of ammo) break; case 1: m_bot->m_ammo[index] = PTR_TO_INT (p); // store it away break; } break; case NETMSG_AMMOPICKUP: // this message is sent when the bot picks up some ammo (AmmoX messages are also sent so this message is probably // not really necessary except it allows the HUD to draw pictures of ammo that have been picked up. The bots // don't really need pictures since they don't have any eyes anyway. switch (m_state) { case 0: index = PTR_TO_INT (p); break; case 1: m_bot->m_ammo[index] = PTR_TO_INT (p); break; } break; case NETMSG_DAMAGE: // this message gets sent when the bots are getting damaged. switch (m_state) { case 0: damageArmor = PTR_TO_INT (p); break; case 1: damageTaken = PTR_TO_INT (p); break; case 2: damageBits = PTR_TO_INT (p); if (m_bot != NULL && (damageArmor > 0 || damageTaken > 0)) m_bot->TakeDamage (m_bot->pev->dmg_inflictor, damageTaken, damageArmor, damageBits); break; } break; case NETMSG_MONEY: // this message gets sent when the bots money amount changes if (m_state == 0) m_bot->m_moneyAmount = PTR_TO_INT (p); // amount of money break; case NETMSG_STATUSICON: switch (m_state) { case 0: enabled = PTR_TO_BYTE (p); break; case 1: if (strcmp (PTR_TO_STR (p), "defuser") == 0) m_bot->m_hasDefuser = (enabled != 0); else if (strcmp (PTR_TO_STR (p), "buyzone") == 0) { m_bot->m_inBuyZone = (enabled != 0); // try to equip in buyzone m_bot->EquipInBuyzone (BUYSTATE_PRIMARY_WEAPON); } else if (strcmp (PTR_TO_STR (p), "vipsafety") == 0) m_bot->m_inVIPZone = (enabled != 0); else if (strcmp (PTR_TO_STR (p), "c4") == 0) m_bot->m_inBombZone = (enabled == 2); break; } break; case NETMSG_DEATH: // this message sends on death switch (m_state) { case 0: killerIndex = PTR_TO_INT (p); break; case 1: victimIndex = PTR_TO_INT (p); break; case 2: bots.SetDeathMsgState (true); if (killerIndex != 0 && killerIndex != victimIndex) { edict_t *killer = engine.EntityOfIndex (killerIndex); edict_t *victim = engine.EntityOfIndex (victimIndex); if (engine.IsNullEntity (killer) || engine.IsNullEntity (victim)) break; if (yb_communication_type.GetInt () == 2) { // need to send congrats on well placed shot for (int i = 0; i < engine.MaxClients (); i++) { Bot *bot = bots.GetBot (i); if (bot != NULL && bot->m_notKilled && killer != bot->GetEntity () && bot->EntityIsVisible (victim->v.origin) && engine.GetTeam (killer) == bot->m_team && engine.GetTeam (killer) != engine.GetTeam (victim)) { if (killer == g_hostEntity) bot->HandleChatterMessage ("#Bot_NiceShotCommander"); else bot->HandleChatterMessage ("#Bot_NiceShotPall"); break; } } } // notice nearby to victim teammates, that attacker is near for (int i = 0; i < engine.MaxClients (); i++) { Bot *bot = bots.GetBot (i); if (bot != NULL && bot->m_seeEnemyTime + 2.0f < engine.Time () && bot->m_notKilled && bot->m_team == engine.GetTeam (victim) && IsVisible (killer->v.origin, bot->GetEntity ()) && engine.IsNullEntity (bot->m_enemy) && engine.GetTeam (killer) != engine.GetTeam (victim)) { bot->m_actualReactionTime = 0.0f; bot->m_seeEnemyTime = engine.Time (); bot->m_enemy = killer; bot->m_lastEnemy = killer; bot->m_lastEnemyOrigin = killer->v.origin; } } Bot *bot = bots.GetBot (killer); // is this message about a bot who killed somebody? if (bot != NULL) bot->m_lastVictim = victim; else // did a human kill a bot on his team? { Bot *target = bots.GetBot (victim); if (target != NULL) { if (engine.GetTeam (killer) == engine.GetTeam (victim)) target->m_voteKickIndex = killerIndex; target->m_notKilled = false; } } } break; } break; case NETMSG_SCREENFADE: // this message gets sent when the Screen fades (Flashbang) switch (m_state) { case 3: r = PTR_TO_BYTE (p); break; case 4: g = PTR_TO_BYTE (p); break; case 5: b = PTR_TO_BYTE (p); break; case 6: m_bot->TakeBlinded (Vector (r, g, b), PTR_TO_BYTE (p)); break; } break; case NETMSG_HLTV: // round restart in steam cs switch (m_state) { case 0: numPlayers = PTR_TO_INT (p); break; case 1: if (numPlayers == 0 && PTR_TO_INT (p) == 0) RoundInit (); break; } break; case NETMSG_RESETHUD: #if 0 if (m_bot != NULL) m_bot->NewRound (); #endif break; case NETMSG_TEXTMSG: if (m_state == 1) { if (FStrEq (PTR_TO_STR (p), "#CTs_Win") || FStrEq (PTR_TO_STR (p), "#Bomb_Defused") || FStrEq (PTR_TO_STR (p), "#Terrorists_Win") || FStrEq (PTR_TO_STR (p), "#Round_Draw") || FStrEq (PTR_TO_STR (p), "#All_Hostages_Rescued") || FStrEq (PTR_TO_STR (p), "#Target_Saved") || FStrEq (PTR_TO_STR (p), "#Hostages_Not_Rescued") || FStrEq (PTR_TO_STR (p), "#Terrorists_Not_Escaped") || FStrEq (PTR_TO_STR (p), "#VIP_Not_Escaped") || FStrEq (PTR_TO_STR (p), "#Escaping_Terrorists_Neutralized") || FStrEq (PTR_TO_STR (p), "#VIP_Assassinated") || FStrEq (PTR_TO_STR (p), "#VIP_Escaped") || FStrEq (PTR_TO_STR (p), "#Terrorists_Escaped") || FStrEq (PTR_TO_STR (p), "#CTs_PreventEscape") || FStrEq (PTR_TO_STR (p), "#Target_Bombed") || FStrEq (PTR_TO_STR (p), "#Game_Commencing") || FStrEq (PTR_TO_STR (p), "#Game_will_restart_in")) { g_roundEnded = true; if (FStrEq (PTR_TO_STR (p), "#Game_Commencing")) g_isCommencing = true; if (FStrEq (PTR_TO_STR (p), "#CTs_Win")) { bots.SetLastWinner (CT); // update last winner for economics if (yb_communication_type.GetInt () == 2) { Bot *bot = bots.FindOneValidAliveBot (); if (bot != NULL && bot->m_notKilled) bot->HandleChatterMessage (PTR_TO_STR (p)); } } if (FStrEq (PTR_TO_STR (p), "#Game_will_restart_in")) { bots.CheckTeamEconomics (CT, true); bots.CheckTeamEconomics (TERRORIST, true); } if (FStrEq (PTR_TO_STR (p), "#Terrorists_Win")) { bots.SetLastWinner (TERRORIST); // update last winner for economics if (yb_communication_type.GetInt () == 2) { Bot *bot = bots.FindOneValidAliveBot (); if (bot != NULL && bot->m_notKilled) bot->HandleChatterMessage (PTR_TO_STR (p)); } } waypoints.SetBombPosition (true); } else if (!g_bombPlanted && FStrEq (PTR_TO_STR (p), "#Bomb_Planted")) { waypoints.SetBombPosition (); g_bombPlanted = g_bombSayString = true; g_timeBombPlanted = engine.Time (); for (int i = 0; i < engine.MaxClients (); i++) { Bot *bot = bots.GetBot (i); if (bot != NULL && bot->m_notKilled) { bot->DeleteSearchNodes (); bot->ResetTasks (); if (yb_communication_type.GetInt () == 2 && Random.Long (0, 100) < 75 && bot->m_team == CT) bot->ChatterMessage (Chatter_WhereIsTheBomb); } } } else if (m_bot != NULL && FStrEq (PTR_TO_STR (p), "#Switch_To_BurstFire")) m_bot->m_weaponBurstMode = BM_ON; else if (m_bot != NULL && FStrEq (PTR_TO_STR (p), "#Switch_To_SemiAuto")) m_bot->m_weaponBurstMode = BM_OFF; } break; case NETMSG_SCOREINFO: switch (m_state) { case 0: playerIndex = PTR_TO_INT (p); break; case 4: if (playerIndex >= 0 && playerIndex <= engine.MaxClients ()) { #ifndef XASH_CSDM Client &cl = g_clients[playerIndex - 1]; if (PTR_TO_INT (p) == 1) cl.realTeam = TERRORIST; else if (PTR_TO_INT (p) == 2) cl.realTeam = CT; else cl.realTeam = SPECTATOR; if (yb_csdm_mode.GetInt () == 2) cl.team = playerIndex; else cl.team = g_clients[playerIndex - 1].realTeam; #endif } break; } break; case NETMSG_BARTIME: if (m_state == 0) { if (PTR_TO_INT (p) > 0) m_bot->m_hasProgressBar = true; // the progress bar on a hud else if (PTR_TO_INT (p) == 0) m_bot->m_hasProgressBar = false; // no progress bar or disappeared } break; default: AddLogEntry (true, LL_FATAL, "Network message handler error. Call to unrecognized message id (%d).\n", m_message); } m_state++; // and finally update network message state }