diff --git a/.gitattributes b/.gitattributes index 02b39b3..34c3c67 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,8 @@ -# Auto detect text files and perform LF normalization -* text=lf - -# Custom for Visual Studio -*.sln merge=union -*.vcxproj merge=union - +# Auto detect text files and perform LF normalization +* text=lf +* text eol=lf + +# Custom for Visual Studio +*.sln merge=union +*.vcxproj merge=union + diff --git a/src/analyze.cpp b/src/analyze.cpp index 613c22d..a5d310e 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -176,7 +176,7 @@ void GraphAnalyze::optimize () { } cleanup (); - auto smooth = [] (const Array &nodes) { + auto smooth = [] (const Array &nodes) { Vector result; for (const auto &node : nodes) { @@ -202,7 +202,7 @@ void GraphAnalyze::optimize () { for (const auto &link : path.links) { if (graph.exists (link.index) && !m_optimizedNodes[link.index] - && !AStarAlgo::cantSkipNode (path.number, link.index, true)) { + && !AStarAlgo::cantSkipNode (path.number, link.index, true)) { indexes.emplace (link.index); } @@ -342,8 +342,8 @@ void GraphAnalyze::flood (const Vector &pos, const Vector &next, float range) { auto testPos = m_isCrouch ? Vector { nextPos.x, nextPos.y, nextPos.z - 18.0f } : nextPos; if ((graph.isNodeReacheable (targetPos, testPos) - && graph.isNodeReacheable (testPos, targetPos)) || (graph.isNodeReacheableWithJump (testPos, targetPos) - && graph.isNodeReacheableWithJump (targetPos, testPos))) { + && graph.isNodeReacheable (testPos, targetPos)) || (graph.isNodeReacheableWithJump (testPos, targetPos) + && graph.isNodeReacheableWithJump (targetPos, testPos))) { graph.add (NodeAddFlag::Normal, m_isCrouch ? Vector { nextPos.x, nextPos.y, nextPos.z - 9.0f } : nextPos); } } @@ -364,7 +364,7 @@ void GraphAnalyze::markGoals () { auto updateNodeFlags = [] (int type, StringRef classname) { game.searchEntities ("classname", classname, [&] (edict_t *ent) { - for (auto &path : graph) { + for (auto &path : graph) { const auto &bb = path.origin + Vector (1.0f, 1.0f, 1.0f); if (ent->v.absmin.x > bb.x || ent->v.absmin.y > bb.y) { diff --git a/src/botlib.cpp b/src/botlib.cpp index a969d96..95c3d21 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -97,9 +97,9 @@ void Bot::avoidGrenades () { auto model = pent->v.model.str (9); if (m_preventFlashing < game.time () - && m_personality == Personality::Rusher - && m_difficulty == Difficulty::Expert - && model == kFlashbangModelName) { + && m_personality == Personality::Rusher + && m_difficulty == Difficulty::Expert + && model == kFlashbangModelName) { // don't look at flash bang if (!(m_states & Sense::SeeingEnemy)) { @@ -175,13 +175,13 @@ void Bot::checkBreakable (edict_t *touch) { void Bot::checkBreakablesAround () { if (!m_buyingFinished - || !cv_destroy_breakables_around - || usesKnife () - || rg.chance (25) - || !game.hasBreakables () - || m_seeEnemyTime + 4.0f > game.time () - || !game.isNullEntity (m_enemy) - || !hasPrimaryWeapon ()) { + || !cv_destroy_breakables_around + || usesKnife () + || rg.chance (25) + || !game.hasBreakables () + || m_seeEnemyTime + 4.0f > game.time () + || !game.isNullEntity (m_enemy) + || !hasPrimaryWeapon ()) { return; } @@ -421,7 +421,7 @@ void Bot::updatePickups () { pickupType = Pickup::DroppedC4; } else if ((isWeaponBox || classname.startsWith ("armoury_entity") || (isCSDM && classname.startsWith ("csdm"))) - && !m_isUsingGrenade) { + && !m_isUsingGrenade) { allowPickup = true; pickupType = Pickup::Weapon; @@ -438,15 +438,15 @@ void Bot::updatePickups () { const auto &secondaryProp = conf.getWeaponProp (secondary.id); if (secondaryWeaponCarried < kPrimaryWeaponMinIndex - && (getAmmo (secondary.id) > 0.3 * secondaryProp.ammo1Max) - && model == "357ammobox.mdl") { + && (getAmmo (secondary.id) > 0.3 * secondaryProp.ammo1Max) + && model == "357ammobox.mdl") { allowPickup = false; } else if (!m_isVIP && - primaryWeaponCarried >= kPrimaryWeaponMinIndex - && (getAmmo (primary.id) > 0.3 * primaryProp.ammo1Max) - && !m_isUsingGrenade && !hasShield ()) { + primaryWeaponCarried >= kPrimaryWeaponMinIndex + && (getAmmo (primary.id) > 0.3 * primaryProp.ammo1Max) + && !m_isUsingGrenade && !hasShield ()) { auto weaponType = conf.getWeaponType (primary.id); @@ -475,7 +475,7 @@ void Bot::updatePickups () { else if (m_healthValue >= 100.0f && model == "medkit.mdl") { allowPickup = false; } - else if (pev->armorvalue >= 100.0f && (model == "kevlar.mdl"|| model == "battery.mdl" || model == "assault.mdl")) { + else if (pev->armorvalue >= 100.0f && (model == "kevlar.mdl" || model == "battery.mdl" || model == "assault.mdl")) { allowPickup = false; } else if ((pev->weapons & cr::bit (Weapon::Flashbang)) && model == kFlashbangModelName) { @@ -570,10 +570,10 @@ void Bot::updatePickups () { allowPickup = false; if (!m_defendHostage && m_personality - != Personality::Rusher && m_difficulty >= Difficulty::Normal - && rg.chance (15) - && m_timeCamping + 15.0f < game.time () - && numFriendsNear (pev->origin, 384.0f) < 3) { + != Personality::Rusher && m_difficulty >= Difficulty::Normal + && rg.chance (15) + && m_timeCamping + 15.0f < game.time () + && numFriendsNear (pev->origin, 384.0f) < 3) { const int index = findDefendNode (origin); @@ -640,7 +640,7 @@ void Bot::updatePickups () { if (allowPickup) { for (auto &client : util.getClients ()) { if ((client.flags & ClientFlags::Used) && !(client.ent->v.flags & FL_FAKECLIENT) && (client.flags & ClientFlags::Alive) && - client.team == m_team && client.ent->v.origin.distanceSq (ent->v.origin) <= cr::sqrf (240.0f)) { + client.team == m_team && client.ent->v.origin.distanceSq (ent->v.origin) <= cr::sqrf (240.0f)) { allowPickup = false; break; } @@ -874,9 +874,9 @@ void Bot::showChatterIcon (bool show, bool disconnect) { void Bot::instantChatter (int type) { // this function sends instant chatter messages. if (!game.is (GameFlags::HasBotVoice) - || cv_radio_mode.as () != 2 - || !conf.hasChatterBank (type) - || !conf.hasChatterBank (Chatter::DiePain)) { + || cv_radio_mode.as () != 2 + || !conf.hasChatterBank (type) + || !conf.hasChatterBank (Chatter::DiePain)) { return; } @@ -1068,9 +1068,9 @@ void Bot::checkMsgQueue () { if (m_radioSelect != -1) { if ((m_radioSelect != Radio::ReportingIn && m_forceRadio) - || cv_radio_mode.as () != 2 - || !conf.hasChatterBank (m_radioSelect) - || !game.is (GameFlags::HasBotVoice)) { + || cv_radio_mode.as () != 2 + || !conf.hasChatterBank (m_radioSelect) + || !game.is (GameFlags::HasBotVoice)) { if (m_radioSelect < Radio::GoGoGo) { issueCommand ("radio1"); @@ -1340,8 +1340,8 @@ void Bot::buyStuff () { } if (selectedWeapon->id == Weapon::Shield - && m_moneyAmount > limit[EcoLimit::ShieldGreater] - && rg.chance (disrespectEconomicsPct)) { + && m_moneyAmount > limit[EcoLimit::ShieldGreater] + && rg.chance (disrespectEconomicsPct)) { ignoreWeapon = true; } @@ -1443,8 +1443,8 @@ void Bot::buyStuff () { case BuyState::ArmorVestHelm: // if armor is damaged and bot has some money, buy some armor if (pev->armorvalue < rg (50.0f, 80.0f) - && teamHasGoodEconomics - && (isPistolMode || (teamHasGoodEconomics && hasPrimaryWeapon ()))) { + && teamHasGoodEconomics + && (isPistolMode || (teamHasGoodEconomics && hasPrimaryWeapon ()))) { // if bot is rich, buy kevlar + helmet, else buy a single kevlar if (m_moneyAmount > 1500 && !isWeaponRestricted (Weapon::ArmorHelm)) { @@ -1458,9 +1458,9 @@ void Bot::buyStuff () { case BuyState::SecondaryWeapon: // if bot has still some money, buy a better secondary weapon if (isPistolMode - || (isFirstRound && hasDefaultPistols && rg.chance (60)) - || (hasDefaultPistols && bots.getLastWinner () == m_team && m_moneyAmount > rg (2000, 3000)) - || (hasPrimaryWeapon () && hasDefaultPistols && m_moneyAmount > rg (7500, 9000))) { + || (isFirstRound && hasDefaultPistols && rg.chance (60)) + || (hasDefaultPistols && bots.getLastWinner () == m_team && m_moneyAmount > rg (2000, 3000)) + || (hasPrimaryWeapon () && hasDefaultPistols && m_moneyAmount > rg (7500, 9000))) { do { pref--; @@ -1571,10 +1571,10 @@ void Bot::buyStuff () { case BuyState::DefusalKit: // if bot is CT and we're on a bomb map, randomly buy the defuse kit if (game.mapIs (MapFlags::Demolition) - && m_team == Team::CT - && rg.chance (80) - && m_moneyAmount > 200 - && !isWeaponRestricted (Weapon::Defuser)) { + && m_team == Team::CT + && rg.chance (80) + && m_moneyAmount > 200 + && !isWeaponRestricted (Weapon::Defuser)) { if (isOldGame) { issueCommand ("buyequip;menuselect 6"); @@ -1612,7 +1612,7 @@ void Bot::updateEmotions () { if (m_nextEmotionUpdate > game.time ()) { return; } - + if (m_agressionLevel > m_baseAgressionLevel) { m_agressionLevel -= 0.05f; } @@ -1642,11 +1642,11 @@ void Bot::overrideConditions () { // check if we need to escape from bomb if (game.mapIs (MapFlags::Demolition) - && bots.isBombPlanted () - && m_isAlive - && tid != Task::EscapeFromBomb - && tid != Task::Camp - && isOutOfBombTimer ()) { + && bots.isBombPlanted () + && m_isAlive + && tid != Task::EscapeFromBomb + && tid != Task::Camp + && isOutOfBombTimer ()) { completeTask (); // complete current task @@ -1663,8 +1663,8 @@ void Bot::overrideConditions () { const int nearestToEnemyPoint = graph.getNearest (m_enemy->v.origin); if (nearestToEnemyPoint != kInvalidNodeIndex - && nearestToEnemyPoint != m_currentNodeIndex - && cr::abs (graph[nearestToEnemyPoint].origin.z - m_enemy->v.origin.z) < 16.0f) { + && nearestToEnemyPoint != m_currentNodeIndex + && cr::abs (graph[nearestToEnemyPoint].origin.z - m_enemy->v.origin.z) < 16.0f) { if (tid != Task::MoveToPosition && !cr::fequal (getTask ()->desire, TaskPri::Hide)) { startTask (Task::MoveToPosition, TaskPri::Hide, nearestToEnemyPoint, game.time () + length / (m_moveSpeed * 2.0f), true); @@ -1686,8 +1686,8 @@ void Bot::overrideConditions () { // special handling for sniping if (usesSniper () && (m_states & (Sense::SeeingEnemy | Sense::SuspectEnemy)) - && m_shootTime - 0.4f <= game.time () - && m_sniperStopTime > game.time ()) { + && m_shootTime - 0.4f <= game.time () + && m_sniperStopTime > game.time ()) { ignoreCollision (); @@ -1699,11 +1699,11 @@ void Bot::overrideConditions () { // special handling for reloading if (!bots.isRoundOver () && - tid == Task::Normal - && m_reloadState != Reload::None - && m_isReloading - && !isDucking () - && !isInNarrowPlace ()) { + tid == Task::Normal + && m_reloadState != Reload::None + && m_isReloading + && !isDucking () + && !isInNarrowPlace ()) { if (m_reloadState != Reload::None || m_isReloading) { const auto maxClip = conf.findWeaponById (m_currentWeapon).maxClip; @@ -1901,8 +1901,8 @@ void Bot::setConditions () { // don't listen if seeing enemy, just checked for sounds or being blinded (because its inhuman) if (m_soundUpdateTime < game.time () - && m_blindTime < game.time () - && m_seeEnemyTime + 1.0f < game.time ()) { + && m_blindTime < game.time () + && m_seeEnemyTime + 1.0f < game.time ()) { updateHearing (); m_soundUpdateTime = game.time () + 0.25f; @@ -2037,14 +2037,14 @@ void Bot::filterTasks () { // if half of the round is over, allow hunting if (getCurrentTaskId () != Task::EscapeFromBomb - && game.isNullEntity (m_enemy) - && !m_isVIP - && bots.getRoundMidTime () < game.time () - && !m_hasHostage - && !m_isUsingGrenade - && m_currentNodeIndex != graph.getNearest (m_lastEnemyOrigin) - && m_personality != Personality::Careful - && !cv_ignore_enemies) { + && game.isNullEntity (m_enemy) + && !m_isVIP + && bots.getRoundMidTime () < game.time () + && !m_hasHostage + && !m_isUsingGrenade + && m_currentNodeIndex != graph.getNearest (m_lastEnemyOrigin) + && m_personality != Personality::Careful + && !cv_ignore_enemies) { float desireLevel = 4096.0f - ((1.0f - tempAgression) * m_lastEnemyOrigin.distance (pev->origin)); @@ -2335,8 +2335,8 @@ void Bot::checkRadioQueue () { // check if line of sight to object is not blocked (i.e. visible) if (seesEntity (m_radioEntity->v.origin) || m_radioOrder == Radio::StickTogetherTeam) { if (game.isNullEntity (m_targetEntity) - && game.isNullEntity (m_enemy) - && rg.chance (m_personality == Personality::Careful ? 80 : 20)) { + && game.isNullEntity (m_enemy) + && rg.chance (m_personality == Personality::Careful ? 80 : 20)) { int numFollowers = 0; @@ -2441,8 +2441,8 @@ void Bot::checkRadioQueue () { case Chatter::ScaredEmotion: case Chatter::PinnedDown: if (((game.isNullEntity (m_enemy) && seesEntity (m_radioEntity->v.origin)) || distanceSq < cr::sqrf (2048.0f) || !m_moveToC4) - && rg.chance (50) - && m_seeEnemyTime + 4.0f < game.time ()) { + && rg.chance (50) + && m_seeEnemyTime + 4.0f < game.time ()) { m_fearLevel -= 0.1f; @@ -2699,9 +2699,9 @@ void Bot::checkRadioQueue () { // check if it's a ct command if (game.getTeam (m_radioEntity) == Team::CT - && m_team == Team::CT - && util.isFakeClient (m_radioEntity) - && bots.getPlantedBombSearchTimestamp () < game.time ()) { + && m_team == Team::CT + && util.isFakeClient (m_radioEntity) + && bots.getPlantedBombSearchTimestamp () < game.time ()) { float nearestDistanceSq = kInfiniteDistance; int bombPoint = kInvalidNodeIndex; @@ -2798,8 +2798,8 @@ void Bot::tryHeadTowardRadioMessage () { } if ((util.isFakeClient (m_radioEntity) - && rg.chance (25) - && m_personality == Personality::Normal) || !(m_radioEntity->v.flags & FL_FAKECLIENT)) { + && rg.chance (25) + && m_personality == Personality::Normal) || !(m_radioEntity->v.flags & FL_FAKECLIENT)) { if (tid == Task::Pause || tid == Task::Camp) { getTask ()->time = game.time (); @@ -2856,9 +2856,9 @@ void Bot::frame () { const Vector &bombPosition = graph.getBombOrigin (); if (!m_hasProgressBar - && getCurrentTaskId () != Task::EscapeFromBomb - && pev->origin.distanceSq (bombPosition) < cr::sqrf (1540.0f) - && !isBombDefusing (bombPosition)) { + && getCurrentTaskId () != Task::EscapeFromBomb + && pev->origin.distanceSq (bombPosition) < cr::sqrf (1540.0f) + && !isBombDefusing (bombPosition)) { m_itemIgnore = nullptr; m_itemCheckTime = game.time (); @@ -2943,9 +2943,9 @@ void Bot::update () { } } else if (m_buyingFinished - && !(pev->maxspeed < 10.0f && tid != Task::PlantBomb && tid != Task::DefuseBomb) - && !cv_freeze_bots - && !graph.hasChanged ()) { + && !(pev->maxspeed < 10.0f && tid != Task::PlantBomb && tid != Task::DefuseBomb) + && !cv_freeze_bots + && !graph.hasChanged ()) { botMovement = true; } @@ -3017,9 +3017,9 @@ void Bot::checkSpawnConditions () { } if (m_difficulty >= Difficulty::Normal - && rg.chance (m_personality == Personality::Rusher ? 99 : 50) - && !m_isReloading - && game.mapIs (MapFlags::HostageRescue | MapFlags::Demolition | MapFlags::Escape | MapFlags::Assassination)) { + && rg.chance (m_personality == Personality::Rusher ? 99 : 50) + && !m_isReloading + && game.mapIs (MapFlags::HostageRescue | MapFlags::Demolition | MapFlags::Escape | MapFlags::Assassination)) { if (isKnifeMode ()) { dropCurrentWeapon (); @@ -3127,15 +3127,15 @@ void Bot::logic () { pushChatterMessage (Chatter::VIPSpotted); } else if (!hasFriendNearby - && rg.chance (50) - && game.getTeam (m_enemy) != m_team - && isGroupOfEnemies (m_enemy->v.origin, 2, 384.0f)) { + && rg.chance (50) + && game.getTeam (m_enemy) != m_team + && isGroupOfEnemies (m_enemy->v.origin, 2, 384.0f)) { pushChatterMessage (Chatter::ScaredEmotion); } else if (!hasFriendNearby - && rg.chance (40) - && (m_enemy->v.weapons & kSniperWeaponMask)) { + && rg.chance (40) + && (m_enemy->v.weapons & kSniperWeaponMask)) { pushChatterMessage (Chatter::SniperWarning); } @@ -3582,7 +3582,7 @@ void Bot::updatePracticeDamage (edict_t *attacker, int damage) { if (victimIndex == kInvalidNodeIndex) { victimIndex = findNearestNode (); } - + if (m_healthValue > 20.0f) { if (victimTeam == Team::Terrorist || victimTeam == Team::CT) { practice.setDamage (victimIndex, victimIndex, victimIndex, cr::clamp (practice.getDamage (victimTeam, victimIndex, victimIndex), 0, kMaxDamageValue)); @@ -3786,8 +3786,8 @@ void Bot::runMovement () { translateInput (); engfuncs.pfnRunPlayerMove (pev->pContainingEntity, - getRpmAngles (), m_moveSpeed, m_strafeSpeed, - 0.0f, static_cast (pev->button), static_cast (pev->impulse), msecVal); + getRpmAngles (), m_moveSpeed, m_strafeSpeed, + 0.0f, static_cast (pev->button), static_cast (pev->impulse), msecVal); // save our own copy of old buttons, since bot bot code is not running every frame now m_oldButtons = pev->button; @@ -3860,11 +3860,11 @@ void Bot::updateHearing () { // loop through all enemy clients to check for hearable stuff for (const auto &client : util.getClients ()) { if (!(client.flags & ClientFlags::Used) - || !(client.flags & ClientFlags::Alive) - || client.ent == ent () - || client.team == m_team - || !client.ent - || client.noise.last < game.time ()) { + || !(client.flags & ClientFlags::Alive) + || client.ent == ent () + || client.team == m_team + || !client.ent + || client.noise.last < game.time ()) { continue; } @@ -3888,12 +3888,12 @@ void Bot::updateHearing () { if (util.isPlayer (m_hearedEnemy)) { // change to best weapon if heard something if (m_shootTime < game.time () - 5.0f - && isOnFloor () - && m_currentWeapon != Weapon::C4 - && m_currentWeapon != Weapon::Explosive - && m_currentWeapon != Weapon::Smoke - && m_currentWeapon != Weapon::Flashbang - && !isKnifeMode ()) { + && isOnFloor () + && m_currentWeapon != Weapon::C4 + && m_currentWeapon != Weapon::Explosive + && m_currentWeapon != Weapon::Smoke + && m_currentWeapon != Weapon::Flashbang + && !isKnifeMode ()) { selectBestWeapon (); } @@ -3957,10 +3957,10 @@ void Bot::updateHearing () { // check if heard enemy can be shoot through some obstacle else { if (cv_shoots_thru_walls - && m_lastEnemy == m_hearedEnemy - && rg.chance (conf.getDifficultyTweaks (m_difficulty)->hearThruPct) - && m_seeEnemyTime + 3.0f > game.time () - && isPenetrableObstacle (m_hearedEnemy->v.origin)) { + && m_lastEnemy == m_hearedEnemy + && rg.chance (conf.getDifficultyTweaks (m_difficulty)->hearThruPct) + && m_seeEnemyTime + 3.0f > game.time () + && isPenetrableObstacle (m_hearedEnemy->v.origin)) { m_enemy = m_hearedEnemy; m_lastEnemy = m_hearedEnemy; @@ -3984,11 +3984,11 @@ void Bot::enteredBuyZone (int buyState) { // if bot is in buy zone, try to buy ammo for this weapon... if (m_seeEnemyTime + 12.0f < game.time () - && m_lastEquipTime + 15.0f < game.time () - && m_inBuyZone - && (bots.getRoundStartTime () + rg (10.0f, 20.0f) + mp_buytime.as () < game.time ()) - && !bots.isBombPlanted () - && m_moneyAmount > econLimit[EcoLimit::PrimaryGreater]) { + && m_lastEquipTime + 15.0f < game.time () + && m_inBuyZone + && (bots.getRoundStartTime () + rg (10.0f, 20.0f) + mp_buytime.as () < game.time ()) + && !bots.isBombPlanted () + && m_moneyAmount > econLimit[EcoLimit::PrimaryGreater]) { m_ignoreBuyDelay = true; m_buyingFinished = false; @@ -4057,7 +4057,7 @@ bool Bot::isBombDefusing (const Vector &bombOrigin) { if (client.team == m_team) { // if close enough, mark as progressing - if (bombDistanceSq < distanceToBomb && ((client.ent->v.button | client.ent->v.oldbuttons) & IN_USE)) { + if (bombDistanceSq < distanceToBomb && ((client.ent->v.button | client.ent->v.oldbuttons) & IN_USE)) { defusingInProgress = true; break; } @@ -4069,18 +4069,18 @@ bool Bot::isBombDefusing (const Vector &bombOrigin) { float Bot::getShiftSpeed () { if (getCurrentTaskId () == Task::SeekCover - || (m_aimFlags & AimFlags::Enemy) - || isDucking () - || (pev->button & IN_DUCK) - || (m_oldButtons & IN_DUCK) - || (m_currentTravelFlags & PathFlag::Jump) - || (m_pathFlags & NodeFlag::Ladder) - || isOnLadder () - || isInWater () - || isKnifeMode () - || m_isStuck - || m_numEnemiesLeft <= 0 - || !m_lostReachableNodeTimer.elapsed ()) { + || (m_aimFlags & AimFlags::Enemy) + || isDucking () + || (pev->button & IN_DUCK) + || (m_oldButtons & IN_DUCK) + || (m_currentTravelFlags & PathFlag::Jump) + || (m_pathFlags & NodeFlag::Ladder) + || isOnLadder () + || isInWater () + || isKnifeMode () + || m_isStuck + || m_numEnemiesLeft <= 0 + || !m_lostReachableNodeTimer.elapsed ()) { return pev->maxspeed; } diff --git a/src/chatlib.cpp b/src/chatlib.cpp index 01a1a07..9f9a056 100644 --- a/src/chatlib.cpp +++ b/src/chatlib.cpp @@ -203,7 +203,7 @@ void Bot::prepareChatMessage (StringRef message) { // get bot's victim auto getMyVictim = [&] () -> String {; - return humanizedName (game.indexOfPlayer (m_lastVictim)); + return humanizedName (game.indexOfPlayer (m_lastVictim)); }; // get the game name alias @@ -336,9 +336,9 @@ void Bot::checkForChat () { // bot chatting turned on? if (rg.chance (cv_chat_percent.as ()) - && m_lastChatTime + rg (6.0f, 10.0f) < game.time () - && bots.getLastChatTimestamp () + rg (2.5f, 5.0f) < game.time () - && !isReplyingToChat ()) { + && m_lastChatTime + rg (6.0f, 10.0f) < game.time () + && bots.getLastChatTimestamp () + rg (2.5f, 5.0f) < game.time () + && !isReplyingToChat ()) { if (conf.hasChatBank (Chat::Dead)) { StringRef phrase = conf.pickRandomFromChatBank (Chat::Dead); diff --git a/src/combat.cpp b/src/combat.cpp index d6d8d90..231babb 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -233,9 +233,9 @@ bool Bot::seesEnemy (edict_t *player) { } if ((ignoreFieldOfView || isInViewCone (player->v.origin)) - && frustum.check (m_viewFrustum, player) - && !isBehindSmokeClouds (player->v.origin) - && checkBodyParts (player)) { + && frustum.check (m_viewFrustum, player) + && !isBehindSmokeClouds (player->v.origin) + && checkBodyParts (player)) { return true; } return false; @@ -275,7 +275,7 @@ bool Bot::lookupEnemies () { && m_shootTime + 1.5f > game.time (); if (!(m_aimFlags & (AimFlags::Enemy | AimFlags::PredictPath | AimFlags::Danger)) - && !denyLastEnemy && seesEntity (m_lastEnemyOrigin, true)) { + && !denyLastEnemy && seesEntity (m_lastEnemyOrigin, true)) { m_aimFlags |= AimFlags::LastEnemy; } } @@ -287,9 +287,9 @@ bool Bot::lookupEnemies () { // is player is alive if (m_enemyUpdateTime > game.time () - && m_enemy->v.origin.distanceSq (pev->origin) < nearestDistanceSq - && util.isAlive (player) - && seesEnemy (player)) { + && m_enemy->v.origin.distanceSq (pev->origin) < nearestDistanceSq + && util.isAlive (player) + && seesEnemy (player)) { newEnemy = player; } @@ -336,10 +336,10 @@ bool Bot::lookupEnemies () { // search the world for players... for (const auto &client : util.getClients ()) { if (!(client.flags & ClientFlags::Used) - || !(client.flags & ClientFlags::Alive) - || client.team == m_team - || client.ent == ent () - || !client.ent) { + || !(client.flags & ClientFlags::Alive) + || client.team == m_team + || client.ent == ent () + || !client.ent) { continue; } player = client.ent; @@ -374,7 +374,7 @@ bool Bot::lookupEnemies () { } } m_enemyUpdateTime = game.time () + (usesKnife () ? 1.25f : 0.85f); - + if (game.isNullEntity (newEnemy) && !game.isNullEntity (shieldEnemy)) { newEnemy = shieldEnemy; } @@ -433,9 +433,9 @@ bool Bot::lookupEnemies () { } if (other->m_seeEnemyTime + 2.0f < game.time () - && game.isNullEntity (other->m_lastEnemy) - && util.isVisible (pev->origin, other->ent ()) - && other->isInViewCone (pev->origin)) { + && game.isNullEntity (other->m_lastEnemy) + && util.isVisible (pev->origin, other->ent ()) + && other->isInViewCone (pev->origin)) { other->m_lastEnemy = newEnemy; other->m_lastEnemyOrigin = newEnemy->v.origin; @@ -478,8 +478,8 @@ bool Bot::lookupEnemies () { // if no enemy visible check if last one shoot able through wall if (cv_shoots_thru_walls - && rg.chance (conf.getDifficultyTweaks (m_difficulty)->seenThruPct) - && isPenetrableObstacle (newEnemy->v.origin)) { + && rg.chance (conf.getDifficultyTweaks (m_difficulty)->seenThruPct) + && isPenetrableObstacle (newEnemy->v.origin)) { m_seeEnemyTime = game.time (); @@ -496,13 +496,13 @@ bool Bot::lookupEnemies () { // check if bots should reload... if ((m_aimFlags <= AimFlags::PredictPath - && m_seeEnemyTime + 3.0f < game.time () - && !(m_states & (Sense::SeeingEnemy | Sense::HearingEnemy)) - && game.isNullEntity (m_lastEnemy) - && game.isNullEntity (m_enemy) - && getCurrentTaskId () != Task::ShootBreakable - && getCurrentTaskId () != Task::PlantBomb - && getCurrentTaskId () != Task::DefuseBomb) || bots.isRoundOver ()) { + && m_seeEnemyTime + 3.0f < game.time () + && !(m_states & (Sense::SeeingEnemy | Sense::HearingEnemy)) + && game.isNullEntity (m_lastEnemy) + && game.isNullEntity (m_enemy) + && getCurrentTaskId () != Task::ShootBreakable + && getCurrentTaskId () != Task::PlantBomb + && getCurrentTaskId () != Task::DefuseBomb) || bots.isRoundOver ()) { if (!m_reloadState) { m_reloadState = Reload::Primary; @@ -532,7 +532,7 @@ Vector Bot::getBodyOffsetError (float distance) { m_aimLastError = Vector (rg (mins.x * hitError, maxs.x * hitError), rg (mins.y * hitError, maxs.y * hitError), rg (mins.z * hitError * 0.5f, maxs.z * hitError * 0.5f)); - const auto &aimError = conf.getDifficultyTweaks (m_difficulty) ->aimError; + const auto &aimError = conf.getDifficultyTweaks (m_difficulty)->aimError; m_aimLastError += Vector (rg (-aimError.x, aimError.x), rg (-aimError.y, aimError.y), rg (-aimError.z, aimError.z)); m_aimErrorTime = game.time () + rg (0.4f, 0.8f); @@ -643,7 +643,7 @@ Vector Bot::getCustomHeight (float distance) { { 0.0f, 0.0f, 0.0f }, // melee { 0.5f, -0.1f, -1.5f }, // pistol { 6.5f, 6.0f, -2.0f }, // shotgun - { 0.5f -7.5f, -9.5f }, // zoomrifle + { 0.5f - 7.5f, -9.5f }, // zoomrifle { 0.5f, -7.5f, -9.5f }, // rifle { 0.5f, -7.5f, -9.5f }, // smg { 0.0f, -2.5f, -6.0f }, // sniper @@ -696,7 +696,7 @@ bool Bot::isFriendInLineOfFire (float distance) { const auto friendDistanceSq = client.ent->v.origin.distanceSq (pev->origin); if (friendDistanceSq <= distanceSq - && util.getConeDeviation (ent (), client.ent->v.origin) > friendDistanceSq / (friendDistanceSq + cr::sqrf (33.0f))) { + && util.getConeDeviation (ent (), client.ent->v.origin) > friendDistanceSq / (friendDistanceSq + cr::sqrf (33.0f))) { return true; } } @@ -992,7 +992,7 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) { // we're should stand still before firing sniper weapons, else sniping is useless.. if (usesSniper () && (m_aimFlags & (AimFlags::Enemy | AimFlags::LastEnemy)) - && !m_isReloading && pev->velocity.lengthSq () > 0.0f) { + && !m_isReloading && pev->velocity.lengthSq () > 0.0f) { if (!cr::fzero (pev->velocity.x) || !cr::fzero (pev->velocity.y) || !cr::fzero (pev->velocity.z)) { m_moveSpeed = 0.0f; @@ -1101,12 +1101,12 @@ void Bot::fireWeapons () { // use knife if near and good difficulty (l33t dude!) if (cv_stab_close_enemies && m_difficulty >= Difficulty::Normal - && m_healthValue > 80.0f - && !game.isNullEntity (m_enemy) - && m_healthValue >= m_enemy->v.health - && distance < 100.0f - && !isOnLadder () - && !isGroupOfEnemies (pev->origin)) { + && m_healthValue > 80.0f + && !game.isNullEntity (m_enemy) + && m_healthValue >= m_enemy->v.health + && distance < 100.0f + && !isOnLadder () + && !isGroupOfEnemies (pev->origin)) { selectWeapons (distance, selectIndex, selectId, choosenWeapon); return; @@ -1346,8 +1346,8 @@ void Bot::attackMovement () { // fire hurts friend value here is from previous frame, but acceptable, and saves us alot of cpu cycles if (approach < 30 || m_fireHurtsFriend || ((usesPistol () || usesShotgun ()) - && distance < pistolStrafeDistance - && isInViewCone (m_enemyOrigin))) { + && distance < pistolStrafeDistance + && isInViewCone (m_enemyOrigin))) { m_fightStyle = Fight::Strafe; } m_lastFightStyleCheck = game.time (); @@ -1428,10 +1428,10 @@ void Bot::attackMovement () { } if (m_difficulty >= Difficulty::Normal - && (m_jumpTime + 5.0f < game.time () - && isOnFloor () - && rg (0, 1000) < (m_isReloading ? 8 : 2) - && pev->velocity.length2d () > 150.0f) && !usesSniper ()) { + && (m_jumpTime + 5.0f < game.time () + && isOnFloor () + && rg (0, 1000) < (m_isReloading ? 8 : 2) + && pev->velocity.length2d () > 150.0f) && !usesSniper ()) { pev->button |= IN_JUMP; } @@ -1443,14 +1443,14 @@ void Bot::attackMovement () { m_duckTime = game.time () + m_frameInterval * 3.0f; } else if ((distance > kSprayDistanceX2 && hasPrimaryWeapon ()) - && isFullView - && getCurrentTaskId () != Task::SeekCover - && getCurrentTaskId () != Task::Hunt) { + && isFullView + && getCurrentTaskId () != Task::SeekCover + && getCurrentTaskId () != Task::Hunt) { const int enemyNearestIndex = graph.getNearest (m_enemy->v.origin); if (vistab.visible (m_currentNodeIndex, enemyNearestIndex, VisIndex::Crouch) - && vistab.visible (enemyNearestIndex, m_currentNodeIndex, VisIndex::Crouch)) { + && vistab.visible (enemyNearestIndex, m_currentNodeIndex, VisIndex::Crouch)) { m_duckTime = game.time () + m_frameInterval * 3.0f; } } @@ -1828,11 +1828,11 @@ void Bot::checkReload () { // we're should not reload, while doing next tasks const bool uninterruptibleTask = (tid == Task::PlantBomb - || tid == Task::DefuseBomb - || tid == Task::PickupItem - || tid == Task::ThrowExplosive - || tid == Task::ThrowFlashbang - || tid == Task::ThrowSmoke); + || tid == Task::DefuseBomb + || tid == Task::PickupItem + || tid == Task::ThrowExplosive + || tid == Task::ThrowFlashbang + || tid == Task::ThrowSmoke); // do not check for reload if (uninterruptibleTask || m_isUsingGrenade || usesKnife ()) { @@ -2112,10 +2112,10 @@ void Bot::checkGrenadesThrow () { // special condition if we're have valid current enemy if (!isGrenadeMode && ((m_states & Sense::SeeingEnemy) - && util.isAlive (m_enemy) - && ((m_enemy->v.button | m_enemy->v.oldbuttons) & IN_ATTACK) - && util.isVisible (pev->origin, m_enemy)) - && util.isInViewCone (pev->origin, m_enemy)) { + && util.isAlive (m_enemy) + && ((m_enemy->v.button | m_enemy->v.oldbuttons) & IN_ATTACK) + && util.isVisible (pev->origin, m_enemy)) + && util.isInViewCone (pev->origin, m_enemy)) { // do not throw away grenades if anyone is attacking us distanceSq = kInfiniteDistance; @@ -2183,7 +2183,8 @@ void Bot::checkGrenadesThrow () { } break; - case Weapon::Flashbang: { + case Weapon::Flashbang: + { const int nearest = graph.getNearest (m_lastEnemy->v.velocity.get2d () + m_lastEnemy->v.origin); if (nearest != kInvalidNodeIndex) { diff --git a/src/control.cpp b/src/control.cpp index 1f5419f..08b6778 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -103,9 +103,9 @@ int BotControl::cmdFill () { return BotCommandResult::BadFormat; } bots.serverFill (arg (team), - hasArg (personality) ? arg (personality) : -1, - hasArg (difficulty) ? arg (difficulty) : -1, - hasArg (count) ? arg (count) - 1 : -1); + hasArg (personality) ? arg (personality) : -1, + hasArg (difficulty) ? arg (difficulty) : -1, + hasArg (count) ? arg (count) - 1 : -1); return BotCommandResult::Handled; } @@ -1299,8 +1299,8 @@ int BotControl::menuCommands (int item) { case 1: case 2: if (util.findNearestPlayer (reinterpret_cast (&m_djump), m_ent, 600.0f, true, true, true, true, false) - && !m_djump->m_hasC4 - && !m_djump->m_hasHostage) { + && !m_djump->m_hasC4 + && !m_djump->m_hasHostage) { if (item == 1) { m_djump->startDoubleJump (m_ent); diff --git a/src/graph.cpp b/src/graph.cpp index 4a6762f..eb17ad8 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -169,7 +169,7 @@ int BotGraph::clearConnections (int index) { // leave alone ladder connections and don't remove jump connections.. if (((path.flags & NodeFlag::Ladder) - && (m_paths[prev.index].flags & NodeFlag::Ladder)) || (path.links[prev.number].flags & PathFlag::Jump)) { + && (m_paths[prev.index].flags & NodeFlag::Ladder)) || (path.links[prev.number].flags & PathFlag::Jump)) { return false; } @@ -217,8 +217,8 @@ int BotGraph::clearConnections (int index) { if (exists (top.index) && exists (sorted[0].index) && exists (sorted[1].index)) { if ((sorted[1].angles - top.angles < 80.0f || 360.0f - (sorted[1].angles - top.angles) < 80.0f) - && (!(m_paths[sorted[0].index].flags & NodeFlag::Ladder) || !(path.flags & NodeFlag::Ladder)) - && !(path.links[sorted[0].number].flags & PathFlag::Jump)) { + && (!(m_paths[sorted[0].index].flags & NodeFlag::Ladder) || !(path.flags & NodeFlag::Ladder)) + && !(path.links[sorted[0].number].flags & PathFlag::Jump)) { if ((sorted[1].distance + top.distance) * 1.1f / 2.0f < sorted[0].distance) { if (path.links[sorted[0].number].index == sorted[0].index) { @@ -266,7 +266,7 @@ int BotGraph::clearConnections (int index) { // leave alone ladder connections and don't remove jump connections.. if (((path.flags & NodeFlag::Ladder) - && (m_paths[cur.index].flags & NodeFlag::Ladder)) || (path.links[cur.number].flags & PathFlag::Jump)) { + && (m_paths[cur.index].flags & NodeFlag::Ladder)) || (path.links[cur.number].flags & PathFlag::Jump)) { return false; } @@ -300,8 +300,8 @@ int BotGraph::clearConnections (int index) { else if (cur.distance < prev.distance * 1.1f) { // leave alone ladder connections and don't remove jump connections.. if (((path.flags & NodeFlag::Ladder) - && (m_paths[prev.index].flags & NodeFlag::Ladder)) - || (path.links[prev.number].flags & PathFlag::Jump)) { + && (m_paths[prev.index].flags & NodeFlag::Ladder)) + || (path.links[prev.number].flags & PathFlag::Jump)) { return false; } @@ -349,8 +349,8 @@ int BotGraph::clearConnections (int index) { if (exists (top.index) && exists (sorted[0].index)) { if ((top.angles - sorted[0].angles < 40.0f || (360.0f - top.angles - sorted[0].angles) < 40.0f) - && (!(m_paths[sorted[0].index].flags & NodeFlag::Ladder) || !(path.flags & NodeFlag::Ladder)) - && !(path.links[sorted[0].number].flags & PathFlag::Jump)) { + && (!(m_paths[sorted[0].index].flags & NodeFlag::Ladder) || !(path.flags & NodeFlag::Ladder)) + && !(path.links[sorted[0].number].flags & PathFlag::Jump)) { if (top.distance * 1.1f < sorted[0].distance) { if (path.links[sorted[0].number].index == sorted[0].index) { @@ -435,7 +435,7 @@ void BotGraph::addPath (int addIndex, int pathIndex, float distance) { if (link.index == kInvalidNodeIndex) { link.index = static_cast (pathIndex); link.distance = integerDistance; - + msg ("Path added from %d to %d.", addIndex, pathIndex); return; } @@ -832,9 +832,9 @@ void BotGraph::add (int type, const Vector &pos) { game.testLine (newOrigin, calc.origin, TraceIgnore::Monsters, m_editor, &tr); if (cr::fequal (tr.flFraction, 1.0f) - && cr::abs (newOrigin.x - calc.origin.x) < 64.0f - && cr::abs (newOrigin.y - calc.origin.y) < 64.0f - && cr::abs (newOrigin.z - calc.origin.z) < m_autoPathDistance) { + && cr::abs (newOrigin.x - calc.origin.x) < 64.0f + && cr::abs (newOrigin.y - calc.origin.y) < 64.0f + && cr::abs (newOrigin.z - calc.origin.z) < m_autoPathDistance) { const float distance = newOrigin.distance2d (calc.origin); @@ -1527,7 +1527,7 @@ void BotGraph::syncInitLightLevels () { // update light levels for all nodes for (auto &path : m_paths) { - path.light = illum.getLightLevel (path.origin + Vector { 0.0f, 0.0f, 16.0f} ); + path.light = illum.getLightLevel (path.origin + Vector { 0.0f, 0.0f, 16.0f }); } m_lightChecked = true; @@ -1796,7 +1796,7 @@ bool BotGraph::loadGraphData () { vistab.load (); // load/initialize visibility populateNodes (); - + if (exten.mapSize > 0) { int mapSize = getBspSize (); @@ -2093,8 +2093,8 @@ void BotGraph::frame () { // check if node is within a distance, and is visible if (distanceSq < cr::sqrf (cv_graph_draw_distance.as ()) - && ((util.isVisible (path.origin, m_editor) - && util.isInViewCone (path.origin, m_editor)) || !util.isAlive (m_editor) || distanceSq < cr::sqrf (64.0f))) { + && ((util.isVisible (path.origin, m_editor) + && util.isInViewCone (path.origin, m_editor)) || !util.isAlive (m_editor) || distanceSq < cr::sqrf (64.0f))) { // check the distance if (distanceSq < nearestDistanceSq) { @@ -2211,7 +2211,7 @@ void BotGraph::frame () { // draw a paths, camplines and danger directions for nearest node if (nearestDistanceSq < cr::clamp (m_paths[nearestIndex].radius, cr::sqrf (56.0f), cr::sqrf (90.0f)) - && m_pathDisplayTime < game.time ()) { + && m_pathDisplayTime < game.time ()) { m_pathDisplayTime = game.time () + 0.96f; @@ -2341,17 +2341,17 @@ void BotGraph::frame () { } } flags.assignf ("%s%s%s%s%s%s%s%s%s%s%s%s", - (p.flags & NodeFlag::Lift) ? " LIFT" : "", - (p.flags & NodeFlag::Crouch) ? " CROUCH" : "", - (p.flags & NodeFlag::Camp) ? " CAMP" : "", - (p.flags & NodeFlag::TerroristOnly) ? " TERRORIST" : "", - (p.flags & NodeFlag::CTOnly) ? " CT" : "", - (p.flags & NodeFlag::Sniper) ? " SNIPER" : "", - (p.flags & NodeFlag::Goal) ? " GOAL" : "", - (p.flags & NodeFlag::Ladder) ? " LADDER" : "", - (p.flags & NodeFlag::Rescue) ? " RESCUE" : "", - (p.flags & NodeFlag::DoubleJump) ? " JUMPHELP" : "", - (p.flags & NodeFlag::NoHostage) ? " NOHOSTAGE" : "", jumpPoint ? " JUMP" : ""); + (p.flags & NodeFlag::Lift) ? " LIFT" : "", + (p.flags & NodeFlag::Crouch) ? " CROUCH" : "", + (p.flags & NodeFlag::Camp) ? " CAMP" : "", + (p.flags & NodeFlag::TerroristOnly) ? " TERRORIST" : "", + (p.flags & NodeFlag::CTOnly) ? " CT" : "", + (p.flags & NodeFlag::Sniper) ? " SNIPER" : "", + (p.flags & NodeFlag::Goal) ? " GOAL" : "", + (p.flags & NodeFlag::Ladder) ? " LADDER" : "", + (p.flags & NodeFlag::Rescue) ? " RESCUE" : "", + (p.flags & NodeFlag::DoubleJump) ? " JUMPHELP" : "", + (p.flags & NodeFlag::NoHostage) ? " NOHOSTAGE" : "", jumpPoint ? " JUMP" : ""); if (flags.empty ()) { flags.assign ("(none)"); @@ -2359,9 +2359,9 @@ void BotGraph::frame () { // show the information about that point message.assignf (" %s node:\n" - " Node %d of %d, Radius: %.1f, Light: %s\n" - " Flags: %s\n" - " Origin: (%.1f, %.1f, %.1f)\n", type, node, m_paths.length () - 1, p.radius, p.light == kInvalidLightLevel ? "Invalid" : strings.format ("%1.f", p.light), flags, p.origin.x, p.origin.y, p.origin.z); + " Node %d of %d, Radius: %.1f, Light: %s\n" + " Flags: %s\n" + " Origin: (%.1f, %.1f, %.1f)\n", type, node, m_paths.length () - 1, p.radius, p.light == kInvalidLightLevel ? "Invalid" : strings.format ("%1.f", p.light), flags, p.origin.x, p.origin.y, p.origin.z); return message; }; @@ -2386,8 +2386,8 @@ void BotGraph::frame () { String practiceText; practiceText.assignf (" Node practice data (index / damage):\n" - " CT: %d / %d\n" - " T: %d / %d\n\n", dangerIndexCT, dangerIndexCT != kInvalidNodeIndex ? practice.getDamage (Team::CT, nearestIndex, dangerIndexCT) : 0, dangerIndexT, dangerIndexT != kInvalidNodeIndex ? practice.getDamage (Team::Terrorist, nearestIndex, dangerIndexT) : 0); + " CT: %d / %d\n" + " T: %d / %d\n\n", dangerIndexCT, dangerIndexCT != kInvalidNodeIndex ? practice.getDamage (Team::CT, nearestIndex, dangerIndexCT) : 0, dangerIndexT, dangerIndexT != kInvalidNodeIndex ? practice.getDamage (Team::Terrorist, nearestIndex, dangerIndexT) : 0); sendHudMessage ({ 255, 255, 255 }, 0.0f, 0.16f, practiceText + timeMessage); } diff --git a/src/linkage.cpp b/src/linkage.cpp index 0f4e8c0..b4f1ffc 100644 --- a/src/linkage.cpp +++ b/src/linkage.cpp @@ -34,43 +34,43 @@ plugin_info_t Plugin_info = { // compilers can't create lambdas with vaargs, so put this one in it's own namespace namespace Hooks { - void handler_engClientCommand (edict_t *ent, char const *format, ...) { - // this function forces the client whose player entity is ent to issue a client command. - // How it works is that clients all have a argv global string in their client DLL that - // stores the command string; if ever that string is filled with characters, the client DLL - // sends it to the engine as a command to be executed. When the engine has executed that - // command, this argv string is reset to zero. Here is somehow a curious implementation of - // ClientCommand: the engine sets the command it wants the client to issue in his argv, then - // the client DLL sends it back to the engine, the engine receives it then executes the - // command therein. Don't ask me why we need all this complicated crap. Anyhow since bots have - // no client DLL, be certain never to call this function upon a bot entity, else it will just - // make the server crash. Since hordes of uncautious, not to say stupid, programmers don't - // even imagine some players on their servers could be bots, this check is performed less than - // sometimes actually by their side, that's why we strongly recommend to check it here too. In - // case it's a bot asking for a client command, we handle it like we do for bot commands +void handler_engClientCommand (edict_t *ent, char const *format, ...) { + // this function forces the client whose player entity is ent to issue a client command. + // How it works is that clients all have a argv global string in their client DLL that + // stores the command string; if ever that string is filled with characters, the client DLL + // sends it to the engine as a command to be executed. When the engine has executed that + // command, this argv string is reset to zero. Here is somehow a curious implementation of + // ClientCommand: the engine sets the command it wants the client to issue in his argv, then + // the client DLL sends it back to the engine, the engine receives it then executes the + // command therein. Don't ask me why we need all this complicated crap. Anyhow since bots have + // no client DLL, be certain never to call this function upon a bot entity, else it will just + // make the server crash. Since hordes of uncautious, not to say stupid, programmers don't + // even imagine some players on their servers could be bots, this check is performed less than + // sometimes actually by their side, that's why we strongly recommend to check it here too. In + // case it's a bot asking for a client command, we handle it like we do for bot commands - if (!game.isNullEntity (ent)) { - if (bots[ent] || util.isFakeClient (ent) || (ent->v.flags & FL_DORMANT)) { - if (game.is (GameFlags::Metamod)) { - RETURN_META (MRES_SUPERCEDE); // prevent bots to be forced to issue client commands - } - return; + if (!game.isNullEntity (ent)) { + if (bots[ent] || util.isFakeClient (ent) || (ent->v.flags & FL_DORMANT)) { + if (game.is (GameFlags::Metamod)) { + RETURN_META (MRES_SUPERCEDE); // prevent bots to be forced to issue client commands } + return; } - - if (game.is (GameFlags::Metamod)) { - RETURN_META (MRES_IGNORED); - } - - va_list ap; - auto buffer = strings.chars (); - - va_start (ap, format); - vsnprintf (buffer, StringBuffer::StaticBufferSize, format, ap); - va_end (ap); - - engfuncs.pfnClientCommand (ent, buffer); } + + if (game.is (GameFlags::Metamod)) { + RETURN_META (MRES_IGNORED); + } + + va_list ap; + auto buffer = strings.chars (); + + va_start (ap, format); + vsnprintf (buffer, StringBuffer::StaticBufferSize, format, ap); + va_end (ap); + + engfuncs.pfnClientCommand (ent, buffer); +} } CR_EXPORT int GetEntityAPI (gamefuncs_t *table, int interfaceVersion) { @@ -488,7 +488,7 @@ CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) { } if (entlink.needsBypass () && !game.is (GameFlags::Metamod)) { - table->pfnCreateNamedEntity = [] (string_t classname) -> edict_t *{ + table->pfnCreateNamedEntity = [] (string_t classname) -> edict_t * { if (entlink.isPaused ()) { entlink.enable (); @@ -924,7 +924,7 @@ CR_EXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { worker.shutdown (); // kick all bots off this server - bots.kickEveryone (true); + bots.kickEveryone (true); // save collected practice on shutdown practice.save (); diff --git a/src/manager.cpp b/src/manager.cpp index 187148b..d57babd 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -896,8 +896,8 @@ void BotManager::listBots () { auto timelimitStr = cv_rotate_bots ? strings.format ("%-3.0f secs", bot->m_stayTime - game.time ()) : "unlimited"; ctrl.msg ("[%-2.1d]\t%-22.16s\t%-10.12s\t%-3.4s\t%-3.1d\t%-3.1d\t%-3.4s\t%s", - bot->index (), bot->pev->netname.chars (), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", - botTeam (bot->ent ()), bot->m_difficulty, static_cast (bot->pev->frags), bot->m_isAlive ? "yes" : "no", timelimitStr); + bot->index (), bot->pev->netname.chars (), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", + botTeam (bot->ent ()), bot->m_difficulty, static_cast (bot->pev->frags), bot->m_isAlive ? "yes" : "no", timelimitStr); } ctrl.msg ("%d bots", m_bots.length ()); } @@ -1325,10 +1325,10 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) { // need to send congrats on well placed shot for (const auto ¬ify : bots) { if (notify->m_isAlive - && killerTeam == notify->m_team - && killerTeam != victimTeam - && killer != notify->ent () - && notify->seesEntity (victim->v.origin)) { + && killerTeam == notify->m_team + && killerTeam != victimTeam + && killer != notify->ent () + && notify->seesEntity (victim->v.origin)) { if (!(killer->v.flags & FL_FAKECLIENT)) { notify->pushChatterMessage (Chatter::NiceShotCommander); @@ -1346,13 +1346,13 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) { // notice nearby to victim teammates, that attacker is near for (const auto ¬ify : bots) { if (notify->m_difficulty >= Difficulty::Hard - && killerTeam != victimTeam - && notify->m_seeEnemyTime + 2.0f < game.time () - && notify->m_isAlive - && notify->m_team == victimTeam - && game.isNullEntity (notify->m_enemy) - && game.isNullEntity (notify->m_lastEnemy) - && util.isVisible (killer->v.origin, notify->ent ())) { + && killerTeam != victimTeam + && notify->m_seeEnemyTime + 2.0f < game.time () + && notify->m_isAlive + && notify->m_team == victimTeam + && game.isNullEntity (notify->m_enemy) + && game.isNullEntity (notify->m_lastEnemy) + && util.isVisible (killer->v.origin, notify->ent ())) { // make bot look at last enemy position notify->m_actualReactionTime = 0.0f; @@ -1890,10 +1890,10 @@ void BotManager::notifyBombDefuse () { const auto task = bot->getCurrentTaskId (); if (!bot->m_defuseNotified - && bot->m_isAlive - && task != Task::MoveToPosition - && task != Task::DefuseBomb - && task != Task::EscapeFromBomb) { + && bot->m_isAlive + && task != Task::MoveToPosition + && task != Task::DefuseBomb + && task != Task::EscapeFromBomb) { if (bot->m_team == Team::Terrorist && bot->pev->origin.distanceSq (bombPos) < cr::sqrf (512.0f)) { bot->clearSearchNodes (); @@ -2263,7 +2263,7 @@ bool BotManager::isLineBlockedBySmoke (const Vector &from, const Vector &to, flo } } } - + // define how much smoke a bot can see thru const float maxSmokedLength = 0.7f * kSmokeGrenadeRadius; diff --git a/src/navigate.cpp b/src/navigate.cpp index 25b76c6..a8bd8e8 100644 --- a/src/navigate.cpp +++ b/src/navigate.cpp @@ -302,7 +302,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offensive) { postprocessGoals (graph.m_goalPoints, goalChoices); } } - else if (tactic == GoalTactic::RescueHostage && !graph.m_rescuePoints.empty ()) { + else if (tactic == GoalTactic::RescueHostage && !graph.m_rescuePoints.empty ()) { // force ct with hostage(s) to select closest rescue goal float nearestDistanceSq = kInfiniteDistance; int count = 0; @@ -893,7 +893,7 @@ void Bot::moveToGoal () { src.z += 12.0f; dst.z += 18.0f + 28.0f; - + game.testLine (src, dst, TraceIgnore::Everything, ent (), &tr); if (tr.flFraction >= 0.95f) { @@ -1037,7 +1037,7 @@ bool Bot::updateNavigation () { selectBestWeapon (); } } - + if (m_pathFlags & NodeFlag::Ladder) { const float ladderDistance = pev->origin.distance (m_pathOrigin); @@ -1074,10 +1074,10 @@ bool Bot::updateNavigation () { // special detection if someone is using the ladder (to prevent to have bots-towers on ladders) for (const auto &client : util.getClients ()) { if (!(client.flags & ClientFlags::Used) - || !(client.flags & ClientFlags::Alive) - || (client.ent->v.movetype != MOVETYPE_FLY) - || client.team != m_team - || client.ent == ent ()) { + || !(client.flags & ClientFlags::Alive) + || (client.ent->v.movetype != MOVETYPE_FLY) + || client.team != m_team + || client.ent == ent ()) { continue; } @@ -1091,8 +1091,8 @@ bool Bot::updateNavigation () { // someone is above or below us and is using the ladder already if (tr.pHit == client.ent - && cr::abs (pev->origin.z - client.ent->v.origin.z) > 15.0f - && (client.ent->v.movetype == MOVETYPE_FLY)) { + && cr::abs (pev->origin.z - client.ent->v.origin.z) > 15.0f + && (client.ent->v.movetype == MOVETYPE_FLY)) { const auto numPreviousNode = rg (0, 2); @@ -1246,8 +1246,8 @@ bool Bot::updateNavigation () { // needs precise placement - check if we get past the point if (desiredDistanceSq < cr::sqrf (22.0f) - && nodeDistanceSq < cr::sqrf (30.0f) - && m_pathOrigin.distanceSq (pev->origin + pev->velocity * m_frameInterval) >= nodeDistanceSq) { + && nodeDistanceSq < cr::sqrf (30.0f) + && m_pathOrigin.distanceSq (pev->origin + pev->velocity * m_frameInterval) >= nodeDistanceSq) { desiredDistanceSq = nodeDistanceSq + 1.0f; } @@ -1287,10 +1287,10 @@ bool Bot::updateNavigation () { const int taskTarget = getTask ()->data; if (game.mapIs (MapFlags::Demolition) - && bots.isBombPlanted () - && m_team == Team::CT - && getCurrentTaskId () != Task::EscapeFromBomb - && taskTarget != kInvalidNodeIndex) { + && bots.isBombPlanted () + && m_team == Team::CT + && getCurrentTaskId () != Task::EscapeFromBomb + && taskTarget != kInvalidNodeIndex) { const Vector &bombOrigin = isBombAudible (); @@ -1350,9 +1350,9 @@ bool Bot::updateLiftHandling () { game.testLine (pev->origin, m_pathOrigin, TraceIgnore::Everything, ent (), &tr); if (tr.flFraction < 1.0f - && util.isDoorEntity (tr.pHit) - && (m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor || m_liftState == LiftState::LookingButtonOutside) - && pev->groundentity != tr.pHit) { + && util.isDoorEntity (tr.pHit) + && (m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor || m_liftState == LiftState::LookingButtonOutside) + && pev->groundentity != tr.pHit) { if (m_liftState == LiftState::None) { m_liftState = LiftState::LookingButtonOutside; @@ -1372,8 +1372,8 @@ bool Bot::updateLiftHandling () { // if trace result shows us that it is a lift if (!game.isNullEntity (tr.pHit) && !m_pathWalk.empty () && isFunc (tr.pHit->v.classname.str ()) && !liftClosedDoorExists) { if ((m_liftState == LiftState::None - || m_liftState == LiftState::WaitingFor - || m_liftState == LiftState::LookingButtonOutside) && cr::fzero (tr.pHit->v.velocity.z)) { + || m_liftState == LiftState::WaitingFor + || m_liftState == LiftState::LookingButtonOutside) && cr::fzero (tr.pHit->v.velocity.z)) { if (cr::abs (pev->origin.z - tr.vecEndPos.z) < 70.0f) { m_liftEntity = tr.pHit; @@ -1449,10 +1449,10 @@ bool Bot::updateLiftHandling () { for (const auto &bot : bots) { if (!bot->m_isAlive - || bot->m_team != m_team - || bot->m_targetEntity != ent () - || bot->getCurrentTaskId () != Task::FollowUser - || bot->m_liftEntity != m_liftEntity) { + || bot->m_team != m_team + || bot->m_targetEntity != ent () + || bot->getCurrentTaskId () != Task::FollowUser + || bot->m_liftEntity != m_liftEntity) { continue; } @@ -1484,10 +1484,10 @@ bool Bot::updateLiftHandling () { // got a valid button entity ? if (!game.isNullEntity (button) - && pev->groundentity == m_liftEntity - && m_buttonPushTime + 1.0f < game.time () - && cr::fzero (m_liftEntity->v.velocity.z) - && isOnFloor ()) { + && pev->groundentity == m_liftEntity + && m_buttonPushTime + 1.0f < game.time () + && cr::fzero (m_liftEntity->v.velocity.z) + && isOnFloor ()) { auto buttonWithLineOfSight = lookupButton (m_liftEntity->v.targetname.str (), false); @@ -1508,14 +1508,14 @@ bool Bot::updateLiftHandling () { // is lift activated and bot is standing on it and lift is moving ? if (m_liftState == LiftState::LookingButtonInside - || m_liftState == LiftState::EnteringIn - || m_liftState == LiftState::WaitingForTeammates - || m_liftState == LiftState::WaitingFor) { + || m_liftState == LiftState::EnteringIn + || m_liftState == LiftState::WaitingForTeammates + || m_liftState == LiftState::WaitingFor) { if (pev->groundentity == m_liftEntity - && !cr::fzero (m_liftEntity->v.velocity.z) - && isOnFloor () - && ((graph[m_previousNodes[0]].flags & NodeFlag::Lift) || !game.isNullEntity (m_targetEntity))) { + && !cr::fzero (m_liftEntity->v.velocity.z) + && isOnFloor () + && ((graph[m_previousNodes[0]].flags & NodeFlag::Lift) || !game.isNullEntity (m_targetEntity))) { m_liftState = LiftState::TravelingBy; m_liftUsageTime = game.time () + 14.0f; @@ -1555,10 +1555,10 @@ bool Bot::updateLiftHandling () { // iterate though clients, and find if lift already used for (const auto &client : util.getClients ()) { if (!(client.flags & ClientFlags::Used) - || !(client.flags & ClientFlags::Alive) - || client.team != m_team - || client.ent == ent () - || game.isNullEntity (client.ent->v.groundentity)) { + || !(client.flags & ClientFlags::Alive) + || client.team != m_team + || client.ent == ent () + || game.isNullEntity (client.ent->v.groundentity)) { continue; } @@ -1613,8 +1613,8 @@ bool Bot::updateLiftHandling () { // bot fall down somewhere inside the lift's groove :) if (pev->groundentity != m_liftEntity && graph.exists (m_previousNodes[0])) { if ((graph[m_previousNodes[0]].flags & NodeFlag::Lift) - && (m_path->origin.z - pev->origin.z) > 50.0f - && (graph[m_previousNodes[0]].origin.z - pev->origin.z) > 50.0f) { + && (m_path->origin.z - pev->origin.z) > 50.0f + && (graph[m_previousNodes[0]].origin.z - pev->origin.z) > 50.0f) { m_liftState = LiftState::None; m_liftEntity = nullptr; @@ -2129,8 +2129,8 @@ int Bot::findDefendNode (const Vector &origin) { for (const auto &path : graph) { if (origin.distanceSq (path.origin) < cr::sqrf (kMaxDistance) - && vistab.visible (path.number, posIndex) - && !isOccupiedNode (path.number)) { + && vistab.visible (path.number, posIndex) + && !isOccupiedNode (path.number)) { found.push (path.number); } @@ -2379,13 +2379,13 @@ bool Bot::advanceMovement () { // only if we in normal task and bomb is not planted if (tid == Task::Normal - && bots.getRoundMidTime () + 5.0f < game.time () - && m_timeCamping + 5.0f < game.time () - && !bots.isBombPlanted () - && m_personality != Personality::Rusher - && !m_hasC4 && !m_isVIP - && m_loosedBombNodeIndex == kInvalidNodeIndex - && !m_hasHostage && !m_isCreature) { + && bots.getRoundMidTime () + 5.0f < game.time () + && m_timeCamping + 5.0f < game.time () + && !bots.isBombPlanted () + && m_personality != Personality::Rusher + && !m_hasC4 && !m_isVIP + && m_loosedBombNodeIndex == kInvalidNodeIndex + && !m_hasHostage && !m_isCreature) { m_campButtons = 0; @@ -2497,10 +2497,10 @@ bool Bot::advanceMovement () { // is there a jump node right ahead and do we need to draw out the light weapon ? if (willJump && !usesKnife () - && m_currentWeapon != Weapon::Scout - && !m_isReloading && !usesPistol () - && (jumpDistanceSq > cr::sqrf (145.0f) || (dst.z - 32.0f > src.z && jumpDistanceSq > cr::sqrf (125.0f))) - && !(m_states & Sense::SeeingEnemy)) { + && m_currentWeapon != Weapon::Scout + && !m_isReloading && !usesPistol () + && (jumpDistanceSq > cr::sqrf (145.0f) || (dst.z - 32.0f > src.z && jumpDistanceSq > cr::sqrf (125.0f))) + && !(m_states & Sense::SeeingEnemy)) { selectWeaponById (Weapon::Knife); // draw out the knife if we needed } @@ -3351,7 +3351,7 @@ void Bot::syncFindPath (int srcIndex, int destIndex, FindPath pathType) { m_planner->setG (Heuristic::gfunctionPathDist); } } - + m_chosenGoalIndex = srcIndex; m_goalValue = 0.0f; diff --git a/src/planner.cpp b/src/planner.cpp index f391328..ac4e01e 100644 --- a/src/planner.cpp +++ b/src/planner.cpp @@ -391,7 +391,7 @@ bool FloydWarshallAlgo::load () { return true; } rebuild (); // rebuilds matrix - + return true; } diff --git a/src/storage.cpp b/src/storage.cpp index f873c64..b02f147 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -1,464 +1,464 @@ -// -// YaPB, based on PODBot by Markus Klinge ("CountFloyd"). -// Copyright © YaPB Project Developers . -// -// SPDX-License-Identifier: MIT -// - -#include - -#if defined (BOT_STORAGE_EXPLICIT_INSTANTIATIONS) - -template bool BotStorage::load (SmallArray &data, ExtenHeader *exten, int32_t *outOptions) { - auto type = guessType (); - String filename = buildPath (storageToBotFile (type.option), true); - - extern ConVar cv_debug, cv_graph_url; - - // graphs can be downloaded... - const bool isGraph = !!(type.option & StorageOption::Graph); - const bool isDebug = cv_debug; - - MemFile file (filename); // open the file - data.clear (); - - // resize data to fit the stuff - auto resizeData = [&] (const size_t length) { - data.resize (length); // for non-graph data the graph should be already loaded - data.shrink (); // free up memory to minimum - - // ensure we're have enough memory to decompress the data - data.ensure (length + ULZ::Excess); - }; - - // if graph & attempted to load multiple times, bail out, we're failed - if (isGraph && ++m_retries > 2) { - resetRetries (); - - return error (isGraph, isDebug, file, "Unable to load %s (filename: '%s'). Download process has failed as well. No nodes has been found.", type.name, filename); - } - - // downloader for graph - auto download = [&] () -> bool { - if (!graph.canDownload ()) { - return false; - } - String lowercaseMapName = game.getMapName (); - lowercaseMapName = lowercaseMapName.lowercase (); - - auto downloadAddress = cv_graph_url.as (); - - auto toDownload = buildPath (storageToBotFile (type.option), false); - auto fromDownload = strings.format ("%s://%s/graph/%s.graph", product.httpScheme, downloadAddress, lowercaseMapName); - - // try to download - if (http.downloadFile (fromDownload, toDownload)) { - ctrl.msg ("%s file '%s' successfully downloaded. Processing...", type.name, filename); - return true; - } - else { - ctrl.msg ("Can't download '%s' from '%s' to '%s'... (%d).", filename, fromDownload, toDownload, http.getLastStatusCode ()); - } - return false; - }; - - // tries to reload or open pwf file - auto tryReload = [&] () -> bool { - file.close (); - - if (!isGraph) { - return false; - } - - if (download ()) { - return load (data, exten, outOptions); - } - - if (graph.convertOldFormat ()) { - return load (data, exten, outOptions); - } - return false; - }; - - // no open no fun - if (!file) { - if (tryReload ()) { - return true; - } - return error (isGraph, isDebug, file, "Unable to open %s file for reading (filename: '%s').", type.name, filename); - } - - // read the header - StorageHeader hdr {}; - file.read (&hdr, sizeof (StorageHeader)); - - // check the magic - if (hdr.magic != kStorageMagic && hdr.magic != kStorageMagicUB) { - if (tryReload ()) { - return true; - } - return error (isGraph, isDebug, file, "Unable to read magic of %s (filename: '%s').", type.name, filename); - } - - // check the path-numbers - if (!isGraph && hdr.length != graph.length ()) { - return error (isGraph, isDebug, file, "Damaged %s (filename: '%s'). Mismatch number of nodes (got: '%d', need: '%d').", type.name, filename, hdr.length, graph.length ()); - } - - // check the count - if (hdr.length == 0 || hdr.length > kMaxNodes || hdr.length < kMaxNodeLinks) { - if (tryReload ()) { - return true; - } - return error (isGraph, isDebug, file, "Damaged %s (filename: '%s'). Paths length is overflowed (got: '%d').", type.name, filename, hdr.length); - } - - // check the version - if (hdr.version > type.version && isGraph) { - ctrl.msg ("Graph version mismatch %s (filename: '%s'). Version number differs (got: '%d', need: '%d') Please, upgrade %s.", type.name, filename, hdr.version, type.version, product.name); - } - else if (hdr.version != type.version && !isGraph) { - return error (isGraph, isDebug, file, "Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", type.name, filename, hdr.version, type.version); - } - - // save graph version - if (isGraph) { - graph.setGraphHeader (&hdr); - } - - // check the storage type - if ((hdr.options & type.option) != type.option) { - return error (isGraph, isDebug, file, "Incorrect storage format for %s (filename: '%s').", type.name, filename); - } - const auto compressedSize = static_cast (hdr.compressed); - const auto numberNodes = static_cast (hdr.length); - - SmallArray compressed (compressedSize + sizeof (uint8_t) * ULZ::Excess); - - // graph is not resized upon load - if (isGraph) { - resizeData (numberNodes); - } - else { - resizeData (hdr.uncompressed / sizeof (U)); - } - - // read compressed data - if (file.read (compressed.data (), sizeof (uint8_t), compressedSize) == compressedSize) { - - // try to uncompress - if (ulz.uncompress (compressed.data (), hdr.compressed, reinterpret_cast (data.data ()), hdr.uncompressed) == ULZ::UncompressFailure) { - return error (isGraph, isDebug, file, "Unable to decompress ULZ data for %s (filename: '%s').", type.name, filename); - } - else { - - if (outOptions) { - outOptions = &hdr.options; - } - - // author of graph.. save - if ((hdr.options & StorageOption::Exten) && exten != nullptr) { - const auto extenSize = sizeof (ExtenHeader); - const auto actuallyRead = file.read (exten, extenSize) * extenSize; - - if (isGraph) { - resetRetries (); - - ExtenHeader extenHeader; - strings.copy (extenHeader.author, exten->author, cr::bufsize (exten->author)); - - if (extenSize <= actuallyRead) { - // write modified by, only if the name is different - if (!strings.isEmpty (extenHeader.author) - && strncmp (extenHeader.author, exten->modified, cr::bufsize (extenHeader.author)) != 0) { - - strings.copy (extenHeader.modified, exten->modified, cr::bufsize (exten->modified)); - } - } - else { - strings.copy (extenHeader.modified, "(none)", cr::bufsize (exten->modified)); - } - extenHeader.mapSize = exten->mapSize; - - // tell graph about exten header - graph.setExtenHeader (&extenHeader); - } +// +// YaPB, based on PODBot by Markus Klinge ("CountFloyd"). +// Copyright © YaPB Project Developers . +// +// SPDX-License-Identifier: MIT +// + +#include + +#if defined (BOT_STORAGE_EXPLICIT_INSTANTIATIONS) + +template bool BotStorage::load (SmallArray &data, ExtenHeader *exten, int32_t *outOptions) { + auto type = guessType (); + String filename = buildPath (storageToBotFile (type.option), true); + + extern ConVar cv_debug, cv_graph_url; + + // graphs can be downloaded... + const bool isGraph = !!(type.option & StorageOption::Graph); + const bool isDebug = cv_debug; + + MemFile file (filename); // open the file + data.clear (); + + // resize data to fit the stuff + auto resizeData = [&] (const size_t length) { + data.resize (length); // for non-graph data the graph should be already loaded + data.shrink (); // free up memory to minimum + + // ensure we're have enough memory to decompress the data + data.ensure (length + ULZ::Excess); + }; + + // if graph & attempted to load multiple times, bail out, we're failed + if (isGraph && ++m_retries > 2) { + resetRetries (); + + return error (isGraph, isDebug, file, "Unable to load %s (filename: '%s'). Download process has failed as well. No nodes has been found.", type.name, filename); + } + + // downloader for graph + auto download = [&] () -> bool { + if (!graph.canDownload ()) { + return false; + } + String lowercaseMapName = game.getMapName (); + lowercaseMapName = lowercaseMapName.lowercase (); + + auto downloadAddress = cv_graph_url.as (); + + auto toDownload = buildPath (storageToBotFile (type.option), false); + auto fromDownload = strings.format ("%s://%s/graph/%s.graph", product.httpScheme, downloadAddress, lowercaseMapName); + + // try to download + if (http.downloadFile (fromDownload, toDownload)) { + ctrl.msg ("%s file '%s' successfully downloaded. Processing...", type.name, filename); + return true; + } + else { + ctrl.msg ("Can't download '%s' from '%s' to '%s'... (%d).", filename, fromDownload, toDownload, http.getLastStatusCode ()); + } + return false; + }; + + // tries to reload or open pwf file + auto tryReload = [&] () -> bool { + file.close (); + + if (!isGraph) { + return false; + } + + if (download ()) { + return load (data, exten, outOptions); + } + + if (graph.convertOldFormat ()) { + return load (data, exten, outOptions); + } + return false; + }; + + // no open no fun + if (!file) { + if (tryReload ()) { + return true; + } + return error (isGraph, isDebug, file, "Unable to open %s file for reading (filename: '%s').", type.name, filename); + } + + // read the header + StorageHeader hdr {}; + file.read (&hdr, sizeof (StorageHeader)); + + // check the magic + if (hdr.magic != kStorageMagic && hdr.magic != kStorageMagicUB) { + if (tryReload ()) { + return true; + } + return error (isGraph, isDebug, file, "Unable to read magic of %s (filename: '%s').", type.name, filename); + } + + // check the path-numbers + if (!isGraph && hdr.length != graph.length ()) { + return error (isGraph, isDebug, file, "Damaged %s (filename: '%s'). Mismatch number of nodes (got: '%d', need: '%d').", type.name, filename, hdr.length, graph.length ()); + } + + // check the count + if (hdr.length == 0 || hdr.length > kMaxNodes || hdr.length < kMaxNodeLinks) { + if (tryReload ()) { + return true; + } + return error (isGraph, isDebug, file, "Damaged %s (filename: '%s'). Paths length is overflowed (got: '%d').", type.name, filename, hdr.length); + } + + // check the version + if (hdr.version > type.version && isGraph) { + ctrl.msg ("Graph version mismatch %s (filename: '%s'). Version number differs (got: '%d', need: '%d') Please, upgrade %s.", type.name, filename, hdr.version, type.version, product.name); + } + else if (hdr.version != type.version && !isGraph) { + return error (isGraph, isDebug, file, "Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", type.name, filename, hdr.version, type.version); + } + + // save graph version + if (isGraph) { + graph.setGraphHeader (&hdr); + } + + // check the storage type + if ((hdr.options & type.option) != type.option) { + return error (isGraph, isDebug, file, "Incorrect storage format for %s (filename: '%s').", type.name, filename); + } + const auto compressedSize = static_cast (hdr.compressed); + const auto numberNodes = static_cast (hdr.length); + + SmallArray compressed (compressedSize + sizeof (uint8_t) * ULZ::Excess); + + // graph is not resized upon load + if (isGraph) { + resizeData (numberNodes); + } + else { + resizeData (hdr.uncompressed / sizeof (U)); + } + + // read compressed data + if (file.read (compressed.data (), sizeof (uint8_t), compressedSize) == compressedSize) { + + // try to uncompress + if (ulz.uncompress (compressed.data (), hdr.compressed, reinterpret_cast (data.data ()), hdr.uncompressed) == ULZ::UncompressFailure) { + return error (isGraph, isDebug, file, "Unable to decompress ULZ data for %s (filename: '%s').", type.name, filename); + } + else { + + if (outOptions) { + outOptions = &hdr.options; + } + + // author of graph.. save + if ((hdr.options & StorageOption::Exten) && exten != nullptr) { + const auto extenSize = sizeof (ExtenHeader); + const auto actuallyRead = file.read (exten, extenSize) * extenSize; + + if (isGraph) { + resetRetries (); + + ExtenHeader extenHeader; + strings.copy (extenHeader.author, exten->author, cr::bufsize (exten->author)); + + if (extenSize <= actuallyRead) { + // write modified by, only if the name is different + if (!strings.isEmpty (extenHeader.author) + && strncmp (extenHeader.author, exten->modified, cr::bufsize (extenHeader.author)) != 0) { + + strings.copy (extenHeader.modified, exten->modified, cr::bufsize (exten->modified)); + } + } + else { + strings.copy (extenHeader.modified, "(none)", cr::bufsize (exten->modified)); + } + extenHeader.mapSize = exten->mapSize; + + // tell graph about exten header + graph.setExtenHeader (&extenHeader); + } } // for visibility tables load counts of stand/count numbers - if (type.option & StorageOption::Vistable) { - for (auto &path : graph) { + if (type.option & StorageOption::Vistable) { + for (auto &path : graph) { file.read (&path.vis, sizeof (PathVis)); } } - - ctrl.msg ("Loaded Bots %s data v%d (Memory: %.2fMB).", type.name, hdr.version, static_cast (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f); - file.close (); - - return true; - } - } - else { - return error (isGraph, isDebug, file, "Unable to read ULZ data for %s (filename: '%s').", type.name, filename); - } - return false; -} - -template bool BotStorage::save (const SmallArray &data, ExtenHeader *exten, int32_t passOptions) { - auto type = guessType (); - - // append additional options - if (passOptions != 0) { - type.option |= passOptions; - } - const auto isGraph = !!(type.option & StorageOption::Graph); - - // do not allow to save graph with less than 8 nodes - if (isGraph && graph.length () < kMaxNodeLinks) { - ctrl.msg ("Can't save graph data with less than %d nodes. Please add some more before saving.", kMaxNodeLinks); - return false; - } - String filename = buildPath (storageToBotFile (type.option)); - - if (data.empty ()) { - logger.error ("Unable to save %s file. Empty data. (filename: '%s').", type.name, filename); - return false; - } - else if (isGraph) { - for (auto &path : graph) { - path.display = 0.0f; - path.light = illum.getLightLevel (path.origin); - } - } - - // open the file - File file (filename, "wb"); - - // no open no fun - if (!file) { - logger.error ("Unable to open %s file for writing (filename: '%s').", type.name, filename); - return false; - } - const auto rawLength = data.length () * sizeof (U); - SmallArray compressed (rawLength + sizeof (uint8_t) * ULZ::Excess); - - // try to compress - const auto compressedLength = static_cast (ulz.compress (reinterpret_cast (data.data ()), static_cast (rawLength), reinterpret_cast (compressed.data ()))); - - if (compressedLength > 0) { - StorageHeader hdr {}; - - hdr.magic = kStorageMagic; - hdr.version = type.version; - hdr.options = type.option; - hdr.length = graph.length (); - hdr.compressed = static_cast (compressedLength); - hdr.uncompressed = static_cast (rawLength); - - file.write (&hdr, sizeof (StorageHeader)); + + ctrl.msg ("Loaded Bots %s data v%d (Memory: %.2fMB).", type.name, hdr.version, static_cast (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f); + file.close (); + + return true; + } + } + else { + return error (isGraph, isDebug, file, "Unable to read ULZ data for %s (filename: '%s').", type.name, filename); + } + return false; +} + +template bool BotStorage::save (const SmallArray &data, ExtenHeader *exten, int32_t passOptions) { + auto type = guessType (); + + // append additional options + if (passOptions != 0) { + type.option |= passOptions; + } + const auto isGraph = !!(type.option & StorageOption::Graph); + + // do not allow to save graph with less than 8 nodes + if (isGraph && graph.length () < kMaxNodeLinks) { + ctrl.msg ("Can't save graph data with less than %d nodes. Please add some more before saving.", kMaxNodeLinks); + return false; + } + String filename = buildPath (storageToBotFile (type.option)); + + if (data.empty ()) { + logger.error ("Unable to save %s file. Empty data. (filename: '%s').", type.name, filename); + return false; + } + else if (isGraph) { + for (auto &path : graph) { + path.display = 0.0f; + path.light = illum.getLightLevel (path.origin); + } + } + + // open the file + File file (filename, "wb"); + + // no open no fun + if (!file) { + logger.error ("Unable to open %s file for writing (filename: '%s').", type.name, filename); + return false; + } + const auto rawLength = data.length () * sizeof (U); + SmallArray compressed (rawLength + sizeof (uint8_t) * ULZ::Excess); + + // try to compress + const auto compressedLength = static_cast (ulz.compress (reinterpret_cast (data.data ()), static_cast (rawLength), reinterpret_cast (compressed.data ()))); + + if (compressedLength > 0) { + StorageHeader hdr {}; + + hdr.magic = kStorageMagic; + hdr.version = type.version; + hdr.options = type.option; + hdr.length = graph.length (); + hdr.compressed = static_cast (compressedLength); + hdr.uncompressed = static_cast (rawLength); + + file.write (&hdr, sizeof (StorageHeader)); file.write (compressed.data (), sizeof (uint8_t), compressedLength); // for visibility tables save counts of stand/count numbers - if (type.option & StorageOption::Vistable) { - for (auto &path : graph) { - file.write (&path.vis, sizeof (PathVis)); - } - } - - // add extension - if ((type.option & StorageOption::Exten) && exten != nullptr) { - file.write (exten, sizeof (ExtenHeader)); - } - extern ConVar cv_debug; - - // notify only about graph - if (isGraph || cv_debug) { - ctrl.msg ("Successfully saved Bots %s data.", type.name); - } - } - else { - logger.error ("Unable to compress %s data (filename: '%s').", type.name, filename); - return false; - } - return true; -} - -template bool BotStorage::error (bool isGraph, bool isDebug, MemFile &file, const char *fmt, Args &&...args) { - auto result = strings.format (fmt, cr::forward (args)...); - - // display error only for graph file - if (isGraph || isDebug) { - logger.error (result); - } - - // if graph reset paths - if (isGraph) { - bots.kickEveryone (true); - graph.reset (); - } - file.close (); - - return false; -} - -template BotStorage::SaveLoadData BotStorage::guessType () { - if constexpr (cr::is_same ::value) { - return { "Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix }; - } - else if constexpr (cr::is_same ::value) { - return { "Practice", StorageOption::Practice, StorageVersion::Practice }; - } - else if constexpr (cr::is_same ::value) { - return { "Vistable", StorageOption::Vistable, StorageVersion::Vistable }; - } - else if constexpr (cr::is_same ::value) { - return { "Graph", StorageOption::Graph, StorageVersion::Graph }; - } -} - -#else - -String BotStorage::buildPath (int32_t file, bool isMemoryLoad, bool withoutMapName) { - using FilePath = Twin ; - - static HashMap paths = { - { BotFile::Vistable, FilePath (folders.train, "vis")}, - { BotFile::Practice, FilePath (folders.train, "prc")}, - { BotFile::Pathmatrix, FilePath (folders.train, "pmx")}, - { BotFile::LogFile, FilePath (folders.logs, "txt")}, - { BotFile::Graph, FilePath (folders.graph, "graph")}, - { BotFile::PodbotPWF, FilePath (folders.podbot, "pwf")}, - { BotFile::EbotEWP, FilePath (folders.ebot, "ewp")}, - }; - - static StringArray path; - path.clear (); - - // if not memory file we're don't need game dir - if (isMemoryLoad) { - path.emplace (getRunningPathVFS ()); - } - else { - path.emplace (getRunningPath ()); - } - - // the datadir - path.emplace (folders.data); - - // append real filepath - path.emplace (paths[file].first); - - // if file is logfile use correct logfile name with date - if (file == BotFile::LogFile) { - time_t ticks = time (&ticks); - tm timeinfo {}; - - plat.loctime (&timeinfo, &ticks); - auto timebuf = strings.chars (); - - strftime (timebuf, StringBuffer::StaticBufferSize, "L%d%m%Y", &timeinfo); - path.emplace (strings.format ("%s_%s.%s", product.nameLower, timebuf, paths[file].second)); - } - else if (!withoutMapName) { - String mapName = game.getMapName (); - path.emplace (strings.format ("%s.%s", mapName.lowercase (), paths[file].second)); - } - - // finally use correct path separators for us - return String::join (path, kPathSeparator); -} - -int32_t BotStorage::storageToBotFile (int32_t options) { - // converts storage option to storage filename - - if (options & StorageOption::Graph) { - return BotFile::Graph; - } - else if (options & StorageOption::Matrix) { - return BotFile::Pathmatrix; - } - else if (options & StorageOption::Vistable) { - return BotFile::Vistable; - } - else if (options & StorageOption::Practice) { - return BotFile::Practice; - } - return BotFile::Graph; -} - -void BotStorage::unlinkFromDisk () { - // this function removes graph file from the hard disk - - StringArray unlinkable; - bots.kickEveryone (true); - - // if we're delete graph, delete all corresponding to it files - unlinkable.emplace (buildPath (BotFile::Graph)); // graph itself - unlinkable.emplace (buildPath (BotFile::Practice)); // corresponding to practice - unlinkable.emplace (buildPath (BotFile::Vistable)); // corresponding to vistable - unlinkable.emplace (buildPath (BotFile::Pathmatrix)); // corresponding to matrix - - for (const auto &item : unlinkable) { - if (plat.fileExists (item.chars ())) { - plat.removeFile (item.chars ()); - ctrl.msg ("File %s, has been deleted from the hard disk", item); - } - else { - logger.error ("Unable to open %s", item); - } - } - graph.reset (); // re-initialize points -} - -StringRef BotStorage::getRunningPath () { - // this function get's relative path against bot library (bot library should reside in bin dir) - - static String path; - - // we're do not do relative (against bot's library) paths on android - if (plat.android) { - if (path.empty ()) { - path = strings.joinPath (game.getRunningModName (), folders.addons, folders.bot); - } - return path; - } - - // compute the full path to the our folder - if (path.empty ()) { - path = SharedLibrary::path (&bstor); - - if (path.startsWith (" bool BotStorage::error (bool isGraph, bool isDebug, MemFile &file, const char *fmt, Args &&...args) { + auto result = strings.format (fmt, cr::forward (args)...); + + // display error only for graph file + if (isGraph || isDebug) { + logger.error (result); + } + + // if graph reset paths + if (isGraph) { + bots.kickEveryone (true); + graph.reset (); + } + file.close (); + + return false; +} + +template BotStorage::SaveLoadData BotStorage::guessType () { + if constexpr (cr::is_same ::value) { + return { "Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix }; + } + else if constexpr (cr::is_same ::value) { + return { "Practice", StorageOption::Practice, StorageVersion::Practice }; + } + else if constexpr (cr::is_same ::value) { + return { "Vistable", StorageOption::Vistable, StorageVersion::Vistable }; + } + else if constexpr (cr::is_same ::value) { + return { "Graph", StorageOption::Graph, StorageVersion::Graph }; + } +} + +#else + +String BotStorage::buildPath (int32_t file, bool isMemoryLoad, bool withoutMapName) { + using FilePath = Twin ; + + static HashMap paths = { + { BotFile::Vistable, FilePath (folders.train, "vis")}, + { BotFile::Practice, FilePath (folders.train, "prc")}, + { BotFile::Pathmatrix, FilePath (folders.train, "pmx")}, + { BotFile::LogFile, FilePath (folders.logs, "txt")}, + { BotFile::Graph, FilePath (folders.graph, "graph")}, + { BotFile::PodbotPWF, FilePath (folders.podbot, "pwf")}, + { BotFile::EbotEWP, FilePath (folders.ebot, "ewp")}, + }; + + static StringArray path; + path.clear (); + + // if not memory file we're don't need game dir + if (isMemoryLoad) { + path.emplace (getRunningPathVFS ()); + } + else { + path.emplace (getRunningPath ()); + } + + // the datadir + path.emplace (folders.data); + + // append real filepath + path.emplace (paths[file].first); + + // if file is logfile use correct logfile name with date + if (file == BotFile::LogFile) { + time_t ticks = time (&ticks); + tm timeinfo {}; + + plat.loctime (&timeinfo, &ticks); + auto timebuf = strings.chars (); + + strftime (timebuf, StringBuffer::StaticBufferSize, "L%d%m%Y", &timeinfo); + path.emplace (strings.format ("%s_%s.%s", product.nameLower, timebuf, paths[file].second)); + } + else if (!withoutMapName) { + String mapName = game.getMapName (); + path.emplace (strings.format ("%s.%s", mapName.lowercase (), paths[file].second)); + } + + // finally use correct path separators for us + return String::join (path, kPathSeparator); +} + +int32_t BotStorage::storageToBotFile (int32_t options) { + // converts storage option to storage filename + + if (options & StorageOption::Graph) { + return BotFile::Graph; + } + else if (options & StorageOption::Matrix) { + return BotFile::Pathmatrix; + } + else if (options & StorageOption::Vistable) { + return BotFile::Vistable; + } + else if (options & StorageOption::Practice) { + return BotFile::Practice; + } + return BotFile::Graph; +} + +void BotStorage::unlinkFromDisk () { + // this function removes graph file from the hard disk + + StringArray unlinkable; + bots.kickEveryone (true); + + // if we're delete graph, delete all corresponding to it files + unlinkable.emplace (buildPath (BotFile::Graph)); // graph itself + unlinkable.emplace (buildPath (BotFile::Practice)); // corresponding to practice + unlinkable.emplace (buildPath (BotFile::Vistable)); // corresponding to vistable + unlinkable.emplace (buildPath (BotFile::Pathmatrix)); // corresponding to matrix + + for (const auto &item : unlinkable) { + if (plat.fileExists (item.chars ())) { + plat.removeFile (item.chars ()); + ctrl.msg ("File %s, has been deleted from the hard disk", item); + } + else { + logger.error ("Unable to open %s", item); + } + } + graph.reset (); // re-initialize points +} + +StringRef BotStorage::getRunningPath () { + // this function get's relative path against bot library (bot library should reside in bin dir) + + static String path; + + // we're do not do relative (against bot's library) paths on android + if (plat.android) { + if (path.empty ()) { + path = strings.joinPath (game.getRunningModName (), folders.addons, folders.bot); + } + return path; + } + + // compute the full path to the our folder + if (path.empty ()) { + path = SharedLibrary::path (&bstor); + + if (path.startsWith ("data != kInvalidNodeIndex - && !(graph[getTask ()->data].flags & NodeFlag::Goal) - && getCurrentTaskId () != Task::EscapeFromBomb) { + && bots.isBombPlanted () + && m_team == Team::CT + && getTask ()->data != kInvalidNodeIndex + && !(graph[getTask ()->data].flags & NodeFlag::Goal) + && getCurrentTaskId () != Task::EscapeFromBomb) { clearSearchNodes (); getTask ()->data = kInvalidNodeIndex; @@ -77,10 +77,10 @@ void Bot::normal_ () { if (updateNavigation ()) { // if we're reached the goal, and there is not enemies, notify the team if (!bots.isBombPlanted () - && m_currentNodeIndex != kInvalidNodeIndex - && (m_pathFlags & NodeFlag::Goal) - && rg.chance (15) - && numEnemiesNear (pev->origin, 650.0f) == 0) { + && m_currentNodeIndex != kInvalidNodeIndex + && (m_pathFlags & NodeFlag::Goal) + && rg.chance (15) + && numEnemiesNear (pev->origin, 650.0f) == 0) { pushRadioMessage (Radio::SectorClear); } @@ -90,12 +90,12 @@ void Bot::normal_ () { // spray logo sometimes if allowed to do so if (!(m_states & (Sense::SeeingEnemy | Sense::SuspectEnemy)) - && m_seeEnemyTime + 5.0f < game.time () - && !m_reloadState && m_timeLogoSpray < game.time () - && cv_spraypaints - && rg.chance (50) - && m_moveSpeed > getShiftSpeed () - && game.isNullEntity (m_pickupItem)) { + && m_seeEnemyTime + 5.0f < game.time () + && !m_reloadState && m_timeLogoSpray < game.time () + && cv_spraypaints + && rg.chance (50) + && m_moveSpeed > getShiftSpeed () + && game.isNullEntity (m_pickupItem)) { if (!(game.mapIs (MapFlags::Demolition) && bots.isBombPlanted () && m_team == Team::CT)) { startTask (Task::Spraypaint, TaskPri::Spraypaint, kInvalidNodeIndex, game.time () + 1.0f, false); @@ -126,7 +126,7 @@ void Bot::normal_ () { // don't allow vip on as_ maps to camp + don't allow terrorist carrying c4 to camp if (campingAllowed - && (m_isVIP || (game.mapIs (MapFlags::Demolition) && m_team == Team::Terrorist && !bots.isBombPlanted () && m_hasC4))) { + && (m_isVIP || (game.mapIs (MapFlags::Demolition) && m_team == Team::Terrorist && !bots.isBombPlanted () && m_hasC4))) { campingAllowed = false; } @@ -180,7 +180,7 @@ void Bot::normal_ () { // and reached a rescue point? if (m_pathFlags & NodeFlag::Rescue) { m_hostages.clear (); - } + } } else if (m_team == Team::Terrorist && rg.chance (75) && !game.mapIs (MapFlags::Demolition)) { const int index = findDefendNode (m_path->origin); @@ -269,22 +269,22 @@ void Bot::normal_ () { const float shiftSpeed = getShiftSpeed (); if ((!cr::fzero (m_moveSpeed) && m_moveSpeed > shiftSpeed) && (cv_walking_allowed && mp_footsteps) - && m_difficulty >= Difficulty::Normal - && (m_heardSoundTime + 6.0f >= game.time () || (m_states & Sense::HearingEnemy)) - && numEnemiesNear (pev->origin, 768.0f) >= 1 - && !isKnifeMode () - && !bots.isBombPlanted ()) { + && m_difficulty >= Difficulty::Normal + && (m_heardSoundTime + 6.0f >= game.time () || (m_states & Sense::HearingEnemy)) + && numEnemiesNear (pev->origin, 768.0f) >= 1 + && !isKnifeMode () + && !bots.isBombPlanted ()) { m_moveSpeed = shiftSpeed; } // bot hasn't seen anything in a long time and is asking his teammates to report in if (cv_radio_mode.as () > 1 - && bots.getLastRadio (m_team) != Radio::ReportInTeam - && bots.getRoundStartTime () + 20.0f < game.time () - && m_askCheckTime < game.time () && rg.chance (15) - && m_seeEnemyTime + rg (45.0f, 80.0f) < game.time () - && numFriendsNear (pev->origin, 1024.0f) == 0) { + && bots.getLastRadio (m_team) != Radio::ReportInTeam + && bots.getRoundStartTime () + 20.0f < game.time () + && m_askCheckTime < game.time () && rg.chance (15) + && m_seeEnemyTime + rg (45.0f, 80.0f) < game.time () + && numFriendsNear (pev->origin, 1024.0f) == 0) { pushRadioMessage (Radio::ReportInTeam); @@ -944,8 +944,8 @@ void Bot::defuseBomb_ () { // bot is reloading and we close enough to start defusing if (m_isReloading && bombPos.distanceSq2d (pev->origin) < cr::sqrf (80.0f)) { if (m_numEnemiesLeft == 0 - || timeToBlowUp < fullDefuseTime + 7.0f - || ((getAmmoInClip () > 8 && m_reloadState == Reload::Primary)|| (getAmmoInClip () > 5 && m_reloadState == Reload::Secondary))) { + || timeToBlowUp < fullDefuseTime + 7.0f + || ((getAmmoInClip () > 8 && m_reloadState == Reload::Primary) || (getAmmoInClip () > 5 && m_reloadState == Reload::Secondary))) { const int weaponIndex = bestWeaponCarried (); @@ -1301,8 +1301,8 @@ void Bot::throwSmoke_ () { void Bot::doublejump_ () { if (!util.isAlive (m_doubleJumpEntity) - || (m_aimFlags & AimFlags::Enemy) - || (m_travelStartIndex != kInvalidNodeIndex && getTask ()->time + (graph.calculateTravelTime (pev->maxspeed, graph[m_travelStartIndex].origin, m_doubleJumpOrigin) + 11.0f) < game.time ())) { + || (m_aimFlags & AimFlags::Enemy) + || (m_travelStartIndex != kInvalidNodeIndex && getTask ()->time + (graph.calculateTravelTime (pev->maxspeed, graph[m_travelStartIndex].origin, m_doubleJumpOrigin) + 11.0f) < game.time ())) { resetDoubleJump (); return; } @@ -1649,7 +1649,7 @@ void Bot::pickupItem_ () { // check if hostage is with a human teammate (hack) for (auto &client : util.getClients ()) { if ((client.flags & ClientFlags::Used) && !(client.ent->v.flags & FL_FAKECLIENT) && (client.flags & ClientFlags::Alive) && - client.team == m_team && client.ent->v.origin.distanceSq (ent->v.origin) <= cr::sqrf (240.0f)) { + client.team == m_team && client.ent->v.origin.distanceSq (ent->v.origin) <= cr::sqrf (240.0f)) { return EntitySearchResult::Continue; } } diff --git a/src/vision.cpp b/src/vision.cpp index c63b3f1..934b95a 100644 --- a/src/vision.cpp +++ b/src/vision.cpp @@ -79,17 +79,17 @@ void Bot::checkDarkness () { const auto tid = getCurrentTaskId (); if (!flashOn && - tid != Task::Camp - && tid != Task::Attack - && m_heardSoundTime + 3.0f < game.time () - && m_flashLevel > 30 - && ((skyColor > 50.0f && lightLevel < 10.0f) || (skyColor <= 50.0f && lightLevel < 40.0f))) { + tid != Task::Camp + && tid != Task::Attack + && m_heardSoundTime + 3.0f < game.time () + && m_flashLevel > 30 + && ((skyColor > 50.0f && lightLevel < 10.0f) || (skyColor <= 50.0f && lightLevel < 40.0f))) { pev->impulse = 100; } else if (flashOn - && (((lightLevel > 15.0f && skyColor > 50.0f) || (lightLevel > 45.0f && skyColor <= 50.0f)) - || tid == Task::Camp || tid == Task::Attack || m_flashLevel <= 0 || m_heardSoundTime + 3.0f >= game.time ())) { + && (((lightLevel > 15.0f && skyColor > 50.0f) || (lightLevel > 45.0f && skyColor <= 50.0f)) + || tid == Task::Camp || tid == Task::Attack || m_flashLevel <= 0 || m_heardSoundTime + 3.0f >= game.time ())) { pev->impulse = 100; } @@ -201,9 +201,9 @@ void Bot::updateLookAngles () { // just force directioon if (m_difficulty == Difficulty::Expert - && (m_aimFlags & AimFlags::Enemy) - && (m_wantsToFire || usesSniper ()) - && cv_whose_your_daddy) { + && (m_aimFlags & AimFlags::Enemy) + && (m_wantsToFire || usesSniper ()) + && cv_whose_your_daddy) { pev->v_angle = direction; pev->v_angle.clampAngles (); @@ -300,8 +300,8 @@ void Bot::updateLookAnglesNewbie (const Vector &direction, float delta) { else { // is it time for bot to randomize the aim direction again (more often where moving) ? if (m_randomizeAnglesTime < game.time () - && ((pev->velocity.length () > 1.0f - && m_angularDeviation.length () < 5.0f) || m_angularDeviation.length () < 1.0f)) { + && ((pev->velocity.length () > 1.0f + && m_angularDeviation.length () < 5.0f) || m_angularDeviation.length () < 1.0f)) { // is the bot standing still ? if (pev->velocity.length () < 1.0f) { @@ -428,10 +428,10 @@ void Bot::setAimDirection () { // don't switch view right away after loosing focus with current enemy if ((m_shootTime + 1.5f > game.time () || m_seeEnemyTime + 1.5 > game.time ()) - && m_forgetLastVictimTimer.elapsed () - && !m_lastEnemyOrigin.empty () - && util.isAlive (m_lastEnemy) - && game.isNullEntity (m_enemy)) { + && m_forgetLastVictimTimer.elapsed () + && !m_lastEnemyOrigin.empty () + && util.isAlive (m_lastEnemy) + && game.isNullEntity (m_enemy)) { flags |= AimFlags::LastEnemy; } @@ -543,11 +543,11 @@ void Bot::setAimDirection () { if (m_moveToGoal && m_seeEnemyTime + 4.0f < game.time () - && !m_isStuck && !(pev->button & IN_DUCK) - && m_currentNodeIndex != kInvalidNodeIndex - && !(m_pathFlags & (NodeFlag::Ladder | NodeFlag::Crouch)) - && m_pathWalk.hasNext () && !isOnLadder () - && pev->origin.distanceSq (destOrigin) < cr::sqrf (512.0f)) { + && !m_isStuck && !(pev->button & IN_DUCK) + && m_currentNodeIndex != kInvalidNodeIndex + && !(m_pathFlags & (NodeFlag::Ladder | NodeFlag::Crouch)) + && m_pathWalk.hasNext () && !isOnLadder () + && pev->origin.distanceSq (destOrigin) < cr::sqrf (512.0f)) { const auto nextPathIndex = m_pathWalk.next (); const auto nextPathX2 = m_pathWalk.nextX2 (); @@ -573,8 +573,8 @@ void Bot::setAimDirection () { const auto dangerIndex = practice.getIndex (m_team, m_currentNodeIndex, m_currentNodeIndex); if (graph.exists (dangerIndex) - && vistab.visible (m_currentNodeIndex, dangerIndex) - && !(graph[dangerIndex].flags & NodeFlag::Crouch)) { + && vistab.visible (m_currentNodeIndex, dangerIndex) + && !(graph[dangerIndex].flags & NodeFlag::Crouch)) { if (pev->origin.distanceSq (graph[dangerIndex].origin) < cr::sqrf (512.0f)) { m_lookAt = destOrigin;