bool Bot::IsShieldDrawn (void) { // this function returns true, is the tactical shield is drawn if (!HasShield ()) return false; return pev->weaponanim == 6 || pev->weaponanim == 7; }
bool Bot::IsEnemyProtectedByShield (edict_t *enemy) { // this function returns true, if enemy protected by the shield if (FNullEnt (enemy) || (HasShield () && IsShieldDrawn ())) return false; // check if enemy has shield and this shield is drawn if (strncmp (STRING (enemy->v.viewmodel), "models/shield/v_shield_", 23) == 0 && (enemy->v.weaponanim == 6 || enemy->v.weaponanim == 7)) { if (::IsInViewCone (pev->origin, enemy)) return true; } return false; }
// SyPB Pro P.32 - Knife Attack Ai bool Bot::KnifeAttack(edict_t *entity) { float distance = (pev->origin - GetEntityOrigin(entity)).GetLength(); float kad1 = (m_knifeDistance1API <= 0) ? 64.0f : m_knifeDistance1API;; // Knife Attack Distance (API) float kad2 = (m_knifeDistance2API <= 0) ? 64.0f : m_knifeDistance2API; if (distance < kad1 || distance < kad2) { float distanceSkipZ = (pev->origin - GetEntityOrigin(entity)).GetLength2D(); //if (distanceSkipZ < distance && pev->origin.z > GetEntityOrigin(entity).z) // pev->button |= IN_DUCK; // SyPB Pro P.35 - Knife Attack Change if (pev->origin.z > GetEntityOrigin(entity).z && distanceSkipZ < 64.0f) pev->button |= IN_DUCK; else if (pev->origin.z + 150.0f < GetEntityOrigin(entity).z && distanceSkipZ < 300.0f && distanceSkipZ > 64.0f) pev->button |= IN_JUMP; if (IsZombieBot(GetEntity())) { if (distance < kad1) pev->button |= IN_ATTACK; else pev->button |= IN_ATTACK2; } else { if (distance > kad1) pev->button |= IN_ATTACK2; else if (distance > kad2) pev->button |= IN_ATTACK; else if (engine->RandomInt(1, 100) < 30 || HasShield()) pev->button |= IN_ATTACK; else pev->button |= IN_ATTACK2; } return true; } return false; }
void Bot::FireWeapon (void) { // this function will return true if weapon was fired, false otherwise float distance = (m_lookAt - EyePosition ()).GetLength (); // how far away is the enemy? // if using grenade stop this if (m_isUsingGrenade) { m_shootTime = engine->GetTime () + 0.1f; return; } // or if friend in line of fire, stop this too but do not update shoot time if (!FNullEnt (m_enemy) && IsFriendInLineOfFire (distance)) return; FireDelay *delay = &g_fireDelay[0]; WeaponSelect *selectTab = &g_weaponSelect[0]; edict_t *enemy = m_enemy; int selectId = WEAPON_KNIFE, selectIndex = 0, chosenWeaponIndex = 0; int weapons = pev->weapons; // if jason mode use knife only if (sypb_knifemode.GetBool ()) goto WeaponSelectEnd; // use knife if near and good skill (l33t dude!) if (m_skill > 80 && !FNullEnt (enemy) && distance < 80.0f && pev->health > 80 && pev->health >= enemy->v.health && !IsGroupOfEnemies (pev->origin) && !::IsInViewCone (pev->origin, enemy)) goto WeaponSelectEnd; // loop through all the weapons until terminator is found... while (selectTab[selectIndex].id) { // is the bot carrying this weapon? if (weapons & (1 << selectTab[selectIndex].id)) { // is enough ammo available to fire AND check is better to use pistol in our current situation... if ((m_ammoInClip[selectTab[selectIndex].id] > 0) && !IsWeaponBadInDistance (selectIndex, distance)) chosenWeaponIndex = selectIndex; } selectIndex++; } selectId = selectTab[chosenWeaponIndex].id; // if no available weapon... if (chosenWeaponIndex == 0) { selectIndex = 0; // loop through all the weapons until terminator is found... while (selectTab[selectIndex].id) { int id = selectTab[selectIndex].id; // is the bot carrying this weapon? if (weapons & (1 << id)) { if (g_weaponDefs[id].ammo1 != -1 && m_ammo[g_weaponDefs[id].ammo1] >= selectTab[selectIndex].minPrimaryAmmo) { // available ammo found, reload weapon if (m_reloadState == RSTATE_NONE || m_reloadCheckTime > engine->GetTime () || GetCurrentTask ()->taskID != TASK_ESCAPEFROMBOMB) { m_isReloading = true; m_reloadState = RSTATE_PRIMARY; m_reloadCheckTime = engine->GetTime (); m_fearLevel = 1.0f; // SyPB Pro P.7 RadioMessage (Radio_NeedBackup); } return; } } selectIndex++; } selectId = WEAPON_KNIFE; // no available ammo, use knife! } WeaponSelectEnd: // we want to fire weapon, don't reload now if (!m_isReloading) { m_reloadState = RSTATE_NONE; m_reloadCheckTime = engine->GetTime () + 3.0f; } // select this weapon if it isn't already selected if (m_currentWeapon != selectId) { SelectWeaponByName (g_weaponDefs[selectId].className); // reset burst fire variables m_firePause = 0.0f; m_timeLastFired = 0.0f; m_burstShotsFired = 0; return; } if (delay[chosenWeaponIndex].weaponIndex != selectId) return; if (selectTab[chosenWeaponIndex].id != selectId) { chosenWeaponIndex = 0; // loop through all the weapons until terminator is found... while (selectTab[chosenWeaponIndex].id) { if (selectTab[chosenWeaponIndex].id == selectId) break; chosenWeaponIndex++; } } // if we're have a glock or famas vary burst fire mode CheckBurstMode (distance); if (HasShield () && m_shieldCheckTime < engine->GetTime () && GetCurrentTask ()->taskID != TASK_CAMP) // better shield gun usage { if ((distance > 550) && !IsShieldDrawn ()) pev->button |= IN_ATTACK2; // draw the shield else if (IsShieldDrawn () || (!FNullEnt (m_enemy) && (m_enemy->v.button & IN_RELOAD))) pev->button |= IN_ATTACK2; // draw out the shield m_shieldCheckTime = engine->GetTime () + 1.0f; } if (UsesSniper () && m_zoomCheckTime < engine->GetTime ()) // is the bot holding a sniper rifle? { if (distance > 1500 && pev->fov >= 40) // should the bot switch to the long-range zoom? pev->button |= IN_ATTACK2; else if (distance > 150 && pev->fov >= 90) // else should the bot switch to the close-range zoom ? pev->button |= IN_ATTACK2; else if (distance <= 150 && pev->fov < 90) // else should the bot restore the normal view ? pev->button |= IN_ATTACK2; m_zoomCheckTime = engine->GetTime (); if (!FNullEnt (m_enemy) && (pev->velocity.x != 0 || pev->velocity.y != 0 || pev->velocity.z != 0) && (pev->basevelocity.x != 0 || pev->basevelocity.y != 0 || pev->basevelocity.z != 0)) { m_moveSpeed = 0.0f; m_strafeSpeed = 0.0f; m_navTimeset = engine->GetTime (); } } else if (UsesZoomableRifle () && m_zoomCheckTime < engine->GetTime () && m_skill < 90) // else is the bot holding a zoomable rifle? { if (distance > 800 && pev->fov >= 90) // should the bot switch to zoomed mode? pev->button |= IN_ATTACK2; else if (distance <= 800 && pev->fov < 90) // else should the bot restore the normal view? pev->button |= IN_ATTACK2; m_zoomCheckTime = engine->GetTime (); } const float baseDelay = delay[chosenWeaponIndex].primaryBaseDelay; const float minDelay = delay[chosenWeaponIndex].primaryMinDelay[abs ((m_skill / 20) - 5)]; const float maxDelay = delay[chosenWeaponIndex].primaryMaxDelay[abs ((m_skill / 20) - 5)]; // need to care for burst fire? if (distance < 256.0f || m_blindTime > engine->GetTime ()) { if (selectId == WEAPON_KNIFE) { if (distance < 64.0f) { if (engine->RandomInt (1, 100) < 30 || HasShield ()) pev->button |= IN_ATTACK; // use primary attack else pev->button |= IN_ATTACK2; // use secondary attack } } else { if (selectTab[chosenWeaponIndex].primaryFireHold) // if automatic weapon, just press attack pev->button |= IN_ATTACK; else // if not, toggle buttons { if ((pev->oldbuttons & IN_ATTACK) == 0) pev->button |= IN_ATTACK; } } if (pev->button & IN_ATTACK) m_shootTime = engine->GetTime (); } else { if (DoFirePause (distance, &delay[chosenWeaponIndex])) return; // don't attack with knife over long distance if (selectId == WEAPON_KNIFE) return; if (selectTab[chosenWeaponIndex].primaryFireHold) { m_shootTime = engine->GetTime (); m_zoomCheckTime = engine->GetTime (); pev->button |= IN_ATTACK; // use primary attack } else { pev->button |= IN_ATTACK; // use primary attack m_shootTime = engine->GetTime () + baseDelay + engine->RandomFloat (minDelay, maxDelay); m_zoomCheckTime = engine->GetTime (); } } }
// returns true if buying is completed, false if not bool CBotCS::BuyStuff() { int iId; CServerCS *pServerCS = dynamic_cast<CServerCS *>(g_pServer); switch (m_iBuyCount) { case 0: // if bot is rich, buy armor+helmet; else buy armor if (m_iAccount > RandomLong(3000, 5000)) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): buying armor + helmet"); g_General.FakeClientCommand(this, "buy;menuselect 8;menuselect 2"); } else { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): buying armor"); g_General.FakeClientCommand(this, "buy;menuselect 8;menuselect 1"); } break; case 1: // if bot doesn't have a primary weapon, buy one if (HasPrimary() || HasShield()) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): already have a primary weapon; exiting"); break; // don't proceed if we already have one } // TODO: emotion // select a primary weapon iId = g_pBuyMgrCS->ChooseWeapon(RandomLong(0, 100)/*FIXME*/, m_iAccount, GetTeam()); if (iId != 0) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): Buying weapon: %s", g_General.GetWeaponName(iId)); cs_weapontable_s *pWeapon = get_weapon(iId); assert(pWeapon); if (pServerCS->GetCSVersion() == CS_VERSION_STEAM) g_General.FakeClientCommand(this, pWeapon->szBuyCmd16); else g_General.FakeClientCommand(this, pWeapon->szBuyCmd15); } else { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): no primary weapon is selected"); } break; case 2: // if bot doesn't have a secondary weapon, buy one if (GetWeapons() & ((1 << CS_WEAPON_P228) | (1 << CS_WEAPON_DEAGLE) | (1 << CS_WEAPON_FIVESEVEN) | (1 << CS_WEAPON_ELITE))) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): already have a secondary weapon; exiting"); break; // don't proceed if we already have a good secondary weapon } // TODO: emotion // select a primary weapon iId = g_pBuyMgrCS->ChooseWeapon(RandomLong(0, 100)/*FIXME*/, m_iAccount, GetTeam(), 1); if (iId != 0) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): Buying weapon: %s", g_General.GetWeaponName(iId)); if (HasShield() && iId == CS_WEAPON_ELITE) break; // if we have a shield, we can't buy the dual elites cs_weapontable_s *pWeapon = get_weapon(iId); assert(pWeapon); if (pServerCS->GetCSVersion() == CS_VERSION_STEAM) g_General.FakeClientCommand(this, pWeapon->szBuyCmd16); else g_General.FakeClientCommand(this, pWeapon->szBuyCmd15); } else { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): no secondary weapon is selected"); } break; case 3: // buy enough ammo DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): buying ammo"); g_General.FakeClientCommand(this, "buy;menuselect 6"); // prim. ammo g_General.FakeClientCommand(this, "buy;menuselect 7"); // sec. ammo break; case 4: // buy grenades, defusers, etc. // if bot is CT, randomly buy the defuser if (GetTeam() == CS_TEAM_CT && RandomLong(1, 100) < 33 && m_iAccount > 200) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): buying defuser"); if (pServerCS->GetCSVersion() == CS_VERSION_STEAM) g_General.FakeClientCommand(this, "defuser"); // use alias in CS 1.6 else g_General.FakeClientCommand(this, "buyequip;menuselect 6"); } if (RandomLong(1, 100) < 75 && m_iAccount >= 300 && !(GetWeapons() & CS_WEAPON_HEGRENADE)) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): buying HE Grenade"); // Buy a HE Grenade g_General.FakeClientCommand(this, "buyequip"); g_General.FakeClientCommand(this, "menuselect 4"); } if (RandomLong(1, 100) < 50 && m_iAccount >= 200 && !(GetWeapons() & CS_WEAPON_FLASHBANG)) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): buying Concussion Grenade"); // Buy a Concussion Grenade, i.e., 'FlashBang' g_General.FakeClientCommand(this, "buyequip"); g_General.FakeClientCommand(this, "menuselect 3"); } if (RandomLong(1, 100) < 30 && m_iAccount >= 300 && !(GetWeapons() & CS_WEAPON_SMOKEGRENADE)) { DebugMsg(DEBUG_BOTAI, "CBotCS::BuyStuff(): buying Smoke Grenade"); // Buy a Smoke Grenade g_General.FakeClientCommand(this, "buyequip"); g_General.FakeClientCommand(this, "menuselect 5"); } break; case 5: // buying finished return true; // no more buying break; default: CGeneral::TerminateOnError("CBotCS::BuyStuff(): m_iBuyCount error"); break; } m_iBuyCount++; // add the buying counter return false; }