Get rid of Visual Studio warnings.

Relicensed under the MIT license.
Added safety checks here and there.
This commit is contained in:
jeefo 2019-09-21 23:20:33 +03:00
commit 61fad287e7
48 changed files with 517 additions and 554 deletions

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -93,20 +92,20 @@ bool Bot::isInViewCone (const Vector &origin) {
}
bool Bot::seesItem (const Vector &destination, const char *itemName) {
TraceResult tr;
TraceResult tr {};
// trace a line from bot's eyes to destination..
game.testLine (getEyesPos (), destination, TraceIgnore::Monsters, ent (), &tr);
// check if line of sight to object is not blocked (i.e. visible)
if (tr.flFraction != 1.0f) {
if (tr.flFraction != 1.0f && tr.pHit) {
return strcmp (tr.pHit->v.classname.chars (), itemName) == 0;
}
return true;
}
bool Bot::seesEntity (const Vector &dest, bool fromBody) {
TraceResult tr;
TraceResult tr {};
// trace a line from bot's eyes to destination...
game.testLine (fromBody ? pev->origin : getEyesPos (), dest, TraceIgnore::Everything, ent (), &tr);
@ -330,7 +329,7 @@ void Bot::avoidGrenades () {
if (!seesEntity (pent->v.origin) && isInFOV (pent->v.origin - getEyesPos ()) > pev->fov * 0.5f) {
continue;
}
auto model = pent->v.model.chars () + 9;
auto model = pent->v.model.chars (9);
if (m_preventFlashing < game.time () && m_personality == Personality::Rusher && m_difficulty == 4 && strcmp (model, "flashbang.mdl") == 0) {
// don't look at flash bang
@ -428,7 +427,7 @@ void Bot::checkBreakablesAround () {
edict_t *Bot::lookupBreakable () {
// this function checks if bot is blocked by a shoot able breakable in his moving direction
TraceResult tr;
TraceResult tr {};
game.testLine (pev->origin, pev->origin + (m_destOrigin - pev->origin).normalize () * 72.0f, TraceIgnore::None, ent (), &tr);
if (tr.flFraction != 1.0f) {
@ -539,7 +538,7 @@ void Bot::updatePickups () {
}
auto classname = ent->v.classname.chars ();
auto model = ent->v.model.chars () + 9;
auto model = ent->v.model.chars (9);
// check if line of sight to object is not blocked (i.e. visible)
if (seesItem (origin, classname)) {
@ -830,7 +829,7 @@ void Bot::getCampDirection (Vector *dest) {
// this function check if view on last enemy position is blocked - replace with better vector then
// mostly used for getting a good camping direction vector if not camping on a camp waypoint
TraceResult tr;
TraceResult tr {};
const Vector &src = getEyesPos ();
game.testLine (src, *dest, TraceIgnore::Monsters, ent (), &tr);
@ -1484,7 +1483,7 @@ void Bot::buyStuff () {
break;
case BuyState::SecondaryWeapon: // if bot has still some money, buy a better secondary weapon
if (isPistolMode || (isFirstRound && hasDefaultPistols) || (hasDefaultPistols && bots.getLastWinner () == m_team && m_moneyAmount > rg.int_ (3500, 4500)) || (hasPrimaryWeapon () && hasDefaultPistols && m_moneyAmount > rg.int_ (7500, 9000))) {
if (isPistolMode || (isFirstRound && hasDefaultPistols) || (hasDefaultPistols && bots.getLastWinner () == m_team && m_moneyAmount > rg.int_ (2000, 3000)) || (hasPrimaryWeapon () && hasDefaultPistols && m_moneyAmount > rg.int_ (7500, 9000))) {
do {
pref--;
@ -2031,6 +2030,8 @@ void Bot::clearTasks () {
}
void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
static const auto &filter = bots.getFilters ();
for (auto &task : m_tasks) {
if (task.id == id) {
if (!cr::fequal (task.desire, desire)) {
@ -2039,7 +2040,7 @@ void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
return;
}
}
m_tasks.emplace (id, desire, data, time, resume);
m_tasks.emplace (filter[id].func, id, desire, data, time, resume);
clearSearchNodes ();
ignoreCollision ();
@ -2056,21 +2057,27 @@ void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
}
// this is best place to handle some voice commands report team some info
if (rg.chance (90)) {
if (tid == Task::Blind) {
pushChatterMessage (Chatter::Blind);
if (yb_radio_mode.int_ () > 1) {
if (rg.chance (90)) {
if (tid == Task::Blind) {
pushChatterMessage (Chatter::Blind);
}
else if (tid == Task::PlantBomb) {
pushChatterMessage (Chatter::PlantingBomb);
}
}
else if (tid == Task::PlantBomb) {
pushChatterMessage (Chatter::PlantingBomb);
}
}
if (rg.chance (25) && tid == Task::Camp) {
if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted ()) {
pushChatterMessage (Chatter::GuardingDroppedC4);
if (rg.chance (25) && tid == Task::Camp) {
if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted ()) {
pushChatterMessage (Chatter::GuardingDroppedC4);
}
else {
pushChatterMessage (Chatter::GoingToCamp);
}
}
else {
pushChatterMessage (Chatter::GoingToCamp);
if (rg.chance (75) && tid == Task::Camp && m_team == Team::Terrorist && m_inVIPZone) {
pushChatterMessage (Chatter::GoingToGuardVIPSafety);
}
}
@ -2080,15 +2087,11 @@ void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
else {
m_chosenGoalIndex = getTask ()->data;
}
if (rg.chance (75) && tid == Task::Camp && m_team == Team::Terrorist && m_inVIPZone) {
pushChatterMessage (Chatter::GoingToGuardVIPSafety);
}
}
BotTask *Bot::getTask () {
if (m_tasks.empty ()) {
m_tasks.emplace (Task::Normal, TaskPri::Normal, kInvalidNodeIndex, 0.0f, true);
startTask (Task::Normal, TaskPri::Normal, kInvalidNodeIndex, 0.0f, true);
}
return &m_tasks.last ();
}
@ -3200,7 +3203,7 @@ void Bot::spraypaint_ () {
const auto &forward = pev->v_angle.forward ();
Vector sprayOrigin = getEyesPos () + forward * 128.0f;
TraceResult tr;
TraceResult tr {};
game.testLine (getEyesPos (), sprayOrigin, TraceIgnore::Monsters, ent (), &tr);
// no wall in front?
@ -3732,7 +3735,7 @@ void Bot::plantBomb_ () {
}
}
void Bot::bombDefuse_ () {
void Bot::defuseBomb_ () {
float fullDefuseTime = m_hasDefuser ? 7.0f : 12.0f;
float timeToBlowUp = getBombTimeleft ();
float defuseRemainingTime = fullDefuseTime;
@ -3908,7 +3911,7 @@ void Bot::followUser_ () {
}
if (m_targetEntity->v.button & IN_ATTACK) {
TraceResult tr;
TraceResult tr {};
game.testLine (m_targetEntity->v.origin + m_targetEntity->v.view_ofs, m_targetEntity->v.v_angle.forward () * 500.0f, TraceIgnore::Everything, ent (), &tr);
if (!game.isNullEntity (tr.pHit) && util.isPlayer (tr.pHit) && game.getTeam (tr.pHit) != m_team) {
@ -4201,7 +4204,7 @@ void Bot::doublejump_ () {
const auto &src = pev->origin + Vector (0.0f, 0.0f, 45.0f);
const auto &dest = src + Vector (0.0f, pev->angles.y, 0.0f).upward () * 256.0f;
TraceResult tr;
TraceResult tr {};
game.testLine (src, dest, TraceIgnore::None, ent (), &tr);
if (tr.flFraction < 1.0f && tr.pHit == m_doubleJumpEntity && inJump) {
@ -4373,7 +4376,7 @@ void Bot::pickupItem_ () {
auto &info = conf.getWeapons ();
for (index = 0; index < 7; ++index) {
if (strcmp (info[index].model, m_pickupItem->v.model.chars () + 9) == 0) {
if (strcmp (info[index].model, m_pickupItem->v.model.chars (9)) == 0) {
break;
}
}
@ -4536,108 +4539,15 @@ void Bot::pickupItem_ () {
void Bot::executeTasks () {
// this is core function that handle task execution
switch (getCurrentTaskId ()) {
// normal task
default:
case Task::Normal:
normal_ ();
break;
auto func = getTask ()->func;
// bot sprays messy logos all over the place...
case Task::Spraypaint:
spraypaint_ ();
break;
// hunt down enemy
case Task::Hunt:
huntEnemy_ ();
break;
// bot seeks cover from enemy
case Task::SeekCover:
seekCover_ ();
break;
// plain attacking
case Task::Attack:
attackEnemy_ ();
break;
// Bot is pausing
case Task::Pause:
pause_ ();
break;
// blinded (flashbanged) behaviour
case Task::Blind:
blind_ ();
break;
// camping behaviour
case Task::Camp:
camp_ ();
break;
// hiding behaviour
case Task::Hide:
hide_ ();
break;
// moves to a position specified in position has a higher priority than task_normal
case Task::MoveToPosition:
moveToPos_ ();
break;
// planting the bomb right now
case Task::PlantBomb:
plantBomb_ ();
break;
// bomb defusing behaviour
case Task::DefuseBomb:
bombDefuse_ ();
break;
// follow user behaviour
case Task::FollowUser:
followUser_ ();
break;
// HE grenade throw behaviour
case Task::ThrowExplosive:
throwExplosive_ ();
break;
// flashbang throw behavior (basically the same code like for HE's)
case Task::ThrowFlashbang:
throwFlashbang_ ();
break;
// smoke grenade throw behavior
// a bit different to the others because it mostly tries to throw the sg on the ground
case Task::ThrowSmoke:
throwSmoke_ ();
break;
// bot helps human player (or other bot) to get somewhere
case Task::DoubleJump:
doublejump_ ();
break;
// escape from bomb behaviour
case Task::EscapeFromBomb:
escapeFromBomb_ ();
break;
// shooting breakables in the way action
case Task::ShootBreakable:
shootBreakable_ ();
break;
// picking up items and stuff behaviour
case Task::PickupItem:
pickupItem_ ();
break;
// run the current task
if (func != nullptr) {
(this->*func) ();
}
else {
logger.error ("Missing callback function of Task %d.", getCurrentTaskId ());
kick (); // drop the player, as it's fatal for bot
}
}
@ -4737,6 +4647,9 @@ void Bot::logic () {
if (canRunHeavyWeight ()) {
setConditions ();
}
else if (!game.isNullEntity (m_enemy)) {
trackEnemies ();
}
// some stuff required by by chatter engine
if (yb_radio_mode.int_ () == 2) {
@ -5086,7 +4999,6 @@ void Bot::takeDamage (edict_t *inflictor, int damage, int armor, int bits) {
m_enemyOrigin = m_enemy->v.origin;
pushChatMessage (Chat::TeamAttack);
handleChatter ("#Bot_TeamAttack");
pushChatterMessage (Chatter::FriendlyFire);
}
else {
@ -5235,29 +5147,6 @@ void Bot::updatePracticeDamage (edict_t *attacker, int damage) {
graph.setDangerDamage (m_team, victimIndex, attackerIndex, damageValue);
}
void Bot::handleChatter (const char *tempMessage) {
// this function is added to prevent engine crashes with: 'Message XX started, before message XX ended', or something.
if ((m_team == Team::CT && strcmp (tempMessage, "#CTs_Win") == 0) || (m_team == Team::Terrorist && strcmp (tempMessage, "#Terrorists_Win") == 0)) {
if (bots.getRoundMidTime () > game.time ()) {
pushChatterMessage (Chatter::QuickWonRound);
}
else {
pushChatterMessage (Chatter::WonTheRound);
}
}
else if (strcmp (tempMessage, "#Bot_TeamAttack") == 0) {
pushChatterMessage (Chatter::FriendlyFire);
}
else if (strcmp (tempMessage, "#Bot_NiceShotCommander") == 0) {
pushChatterMessage (Chatter::NiceShotCommander);
}
else if (strcmp (tempMessage, "#Bot_NiceShotPall") == 0) {
pushChatterMessage (Chatter::NiceShotPall);
}
}
void Bot::pushChatMessage (int type, bool isTeamSay) {
if (!conf.hasChatBank (type) || !yb_chat.bool_ ()) {
return;
@ -5352,7 +5241,7 @@ Vector Bot::calcToss (const Vector &start, const Vector &stop) {
// this function returns the velocity at which an object should looped from start to land near end.
// returns null vector if toss is not feasible.
TraceResult tr;
TraceResult tr {};
float gravity = sv_gravity.float_ () * 0.55f;
Vector end = stop - pev->velocity;
@ -5364,7 +5253,7 @@ Vector Bot::calcToss (const Vector &start, const Vector &stop) {
Vector midPoint = start + (end - start) * 0.5f;
game.testHull (midPoint, midPoint + Vector (0.0f, 0.0f, 500.0f), TraceIgnore::Monsters, head_hull, ent (), &tr);
if (tr.flFraction < 1.0f) {
if (tr.flFraction < 1.0f && tr.pHit) {
midPoint = tr.vecEndPos;
midPoint.z = tr.pHit->v.absmin.z - 1.0f;
}
@ -5406,7 +5295,7 @@ Vector Bot::calcThrow (const Vector &start, const Vector &stop) {
// returns null vector if throw is not feasible.
Vector velocity = stop - start;
TraceResult tr;
TraceResult tr {};
float gravity = sv_gravity.float_ () * 0.55f;
float time = velocity.length () / 195.0f;
@ -5444,7 +5333,7 @@ edict_t *Bot::correctGrenadeVelocity (const char *model) {
edict_t *result = nullptr;
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
if (ent->v.owner == this->ent () && strcmp (ent->v.model.chars () + 9, model) == 0) {
if (ent->v.owner == this->ent () && strcmp (ent->v.model.chars (9), model) == 0) {
result = ent;
// set the correct velocity for the grenade

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -97,7 +96,7 @@ bool Bot::checkBodyParts (edict_t *target) {
return false;
}
TraceResult result;
TraceResult result {};
auto eyes = getEyesPos ();
auto spot = target->v.origin;
@ -539,7 +538,7 @@ bool Bot::isFriendInLineOfFire (float distance) {
return false;
}
TraceResult tr;
TraceResult tr {};
game.testLine (getEyesPos (), getEyesPos () + distance * pev->v_angle.normalize (), TraceIgnore::None, ent (), &tr);
// check if we hit something
@ -582,7 +581,7 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
if (penetratePower == 0) {
return false;
}
TraceResult tr;
TraceResult tr {};
float obstacleDistance = 0.0f;
game.testLine (getEyesPos (), dest, TraceIgnore::Monsters, ent (), &tr);
@ -632,7 +631,7 @@ bool Bot::isPenetrableObstacle2 (const Vector &dest) {
int numHits = 0;
Vector point;
TraceResult tr;
TraceResult tr {};
game.testLine (source, dest, TraceIgnore::Everything, ent (), &tr);
@ -1197,7 +1196,7 @@ bool Bot::hasSecondaryWeapon () {
bool Bot::hasShield () {
// this function returns true, if bot has a tactical shield
return strncmp (pev->viewmodel.chars (), "models/shield/v_shield_", 23) == 0;
return strncmp (pev->viewmodel.chars (14), "v_shield_", 9) == 0;
}
bool Bot::isShieldDrawn () {
@ -1217,7 +1216,7 @@ bool Bot::isEnemyBehindShield (edict_t *enemy) {
}
// check if enemy has shield and this shield is drawn
if ((enemy->v.weaponanim == 6 || enemy->v.weaponanim == 7) && strncmp (enemy->v.viewmodel.chars (), "models/shield/v_shield_", 23) == 0) {
if ((enemy->v.weaponanim == 6 || enemy->v.weaponanim == 7) && strncmp (enemy->v.viewmodel.chars (14), "v_shield_", 9) == 0) {
if (util.isInViewCone (pev->origin, enemy)) {
return true;
}
@ -1356,7 +1355,7 @@ bool Bot::rateGroundWeapon (edict_t *ent) {
auto tab = conf.getRawWeapons ();
for (int i = 0; i < kNumWeapons; ++i) {
if (strcmp (tab[*pref].model, ent->v.model.chars () + 9) == 0) {
if (strcmp (tab[*pref].model, ent->v.model.chars (9)) == 0) {
groundIndex = i;
break;
}

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -22,8 +21,8 @@ Game::Game () {
m_precached = false;
m_isBotCommand = false;
memset (m_drawModels, 0, sizeof (m_drawModels));
memset (m_spawnCount, 0, sizeof (m_spawnCount));
plat.bzero (m_drawModels, sizeof (m_drawModels));
plat.bzero (m_spawnCount, sizeof (m_spawnCount));
m_gameFlags = 0;
m_mapFlags = 0;
@ -88,7 +87,7 @@ void Game::levelInitialize (edict_t *entities, int max) {
util.installSendTo ();
}
else if (strcmp (classname, "player_weaponstrip") == 0) {
if (is (GameFlags::Legacy) && ent->v.target.chars ()[0] == '\0') {
if (is (GameFlags::Legacy) && strings.isEmpty (ent->v.target.chars ())) {
ent->v.target = ent->v.targetname = engfuncs.pfnAllocString ("fake");
}
else {
@ -256,7 +255,7 @@ float Game::getWaveLen (const char *fileName) {
unsigned long dataChunkLength;
} waveHdr;
memset (&waveHdr, 0, sizeof (waveHdr));
plat.bzero (&waveHdr, sizeof (waveHdr));
if (fp.read (&waveHdr, sizeof (WavHeader)) == 0) {
logger.error ("Wave File %s - has wrong or unsupported format", filePath);
@ -465,6 +464,20 @@ bool Game::isSoftwareRenderer () {
if (isDedicated ()) {
return true;
}
auto model = illum.getWorldModel ();
if (model->nodes[0].parent != nullptr) {
return false;
}
const auto child = model->nodes[0].children[0];
if (child < model->nodes || child > model->nodes + model->numnodes) {
return false;
}
if (child->parent != &model->nodes[0]) {
return false;
}
// and on only windows version you can use software-render game. Linux, OSX always defaults to OpenGL
if (plat.win32) {
@ -476,7 +489,7 @@ bool Game::isSoftwareRenderer () {
void Game::addNewCvar (const char *name, const char *value, const char *info, bool bounded, float min, float max, Var varType, bool missingAction, const char *regval, ConVar *self) {
// this function adds globally defined variable to registration stack
VarPair pair;
VarPair pair {};
pair.reg.name = const_cast <char *> (name);
pair.reg.string = const_cast <char *> (value);
@ -747,7 +760,7 @@ bool Game::postload () {
if (is (GameFlags::Metamod)) {
return true; // we should stop the attempt for loading the real gamedll, since metamod handle this for us
}
auto gamedll = strings.format ("%s/%s", getenv ("XASH3D_GAMELIBDIR"), plat.hfp ? "libserver_hardfp.so" : "libserver.so");
auto gamedll = strings.format ("%s/%s", plat.env ("XASH3D_GAMELIBDIR"), plat.hfp ? "libserver_hardfp.so" : "libserver.so");
if (!m_gameLib.load (gamedll)) {
logger.fatal ("Unable to load gamedll \"%s\". Exiting... (gamedir: %s)", gamedll, getModName ());
@ -938,7 +951,7 @@ void LightMeasure::updateLight (int style, char *value) {
return;
}
const auto copyLimit = sizeof (m_lightstyle[style].map) - sizeof ('\0');
strncpy (m_lightstyle[style].map, value, copyLimit);
strings.copy (m_lightstyle[style].map, value, copyLimit);
m_lightstyle[style].map[copyLimit] = '\0';
m_lightstyle[style].length = strlen (m_lightstyle[style].map);
@ -1072,7 +1085,7 @@ DynamicEntityLink::Handle DynamicEntityLink::search (Handle module, Name functio
Handle ret = nullptr;
if (m_dlsym.disable ()) {
ret = LookupSymbol (reinterpret_cast <CastType> (handle), function);
ret = MODULE_SYMBOL (reinterpret_cast <MODULE_HANDLE> (handle), function);
m_dlsym.enable ();
}
return ret;

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -637,7 +636,7 @@ void BotGraph::add (int type, const Vector &pos) {
if (m_paths.length () >= kMaxNodes) {
return;
}
m_paths.push (Path ());
m_paths.push (Path {});
index = m_paths.length () - 1;
path = &m_paths[index];
@ -737,7 +736,7 @@ void BotGraph::add (int type, const Vector &pos) {
float minDistance = kInfiniteDistance;
int destIndex = kInvalidNodeIndex;
TraceResult tr;
TraceResult tr {};
// calculate all the paths to this new node
for (const auto &calc : m_paths) {
@ -929,7 +928,7 @@ int BotGraph::getFacingIndex () {
}
// check if visible, (we're not using visiblity tables here, as they not valid at time of waypoint editing)
TraceResult tr;
TraceResult tr {};
game.testLine (editorEyes, path.origin, TraceIgnore::Everything, m_editor, &tr);
if (!cr::fequal (tr.flFraction, 1.0f)) {
@ -1076,7 +1075,7 @@ void BotGraph::calculatePathRadius (int index) {
return;
}
}
TraceResult tr;
TraceResult tr {};
bool wayBlocked = false;
for (float scanDistance = 32.0f; scanDistance < 128.0f; scanDistance += 16.0f) {
@ -1098,7 +1097,7 @@ void BotGraph::calculatePathRadius (int index) {
if (tr.flFraction < 1.0f) {
game.testLine (radiusStart, radiusEnd, TraceIgnore::Monsters, nullptr, &tr);
if (strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
if (tr.pHit && strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
path.radius = 0.0f;
wayBlocked = true;
@ -1336,7 +1335,7 @@ bool BotGraph::convertOldFormat () {
MemFile fp (getOldFormatGraphName (true));
PODGraphHeader header;
memset (&header, 0, sizeof (header));
plat.bzero (&header, sizeof (header));
// save for faster access
const char *map = game.getMapName ();
@ -1350,7 +1349,7 @@ bool BotGraph::convertOldFormat () {
if (header.fileVersion != StorageVersion::Podbot) {
return false;
}
else if (!plat.caseStrMatch (header.mapName, map)) {
else if (!strings.matches (header.mapName, map)) {
return false;
}
else {
@ -1693,9 +1692,9 @@ bool BotGraph::saveGraphData () {
void BotGraph::saveOldFormat () {
PODGraphHeader header {};
strcpy (header.header, kPodbotMagic);
strncpy (header.author, m_editor->v.netname.chars (), cr::bufsize (header.author));
strncpy (header.mapName, game.getMapName (), cr::bufsize (header.mapName));
strings.copy (header.header, kPodbotMagic, sizeof (kPodbotMagic));
strings.copy (header.author, m_editor->v.netname.chars (), cr::bufsize (header.author));
strings.copy (header.mapName, game.getMapName (), cr::bufsize (header.mapName));
header.mapName[31] = 0;
header.fileVersion = StorageVersion::Podbot;
@ -1739,7 +1738,7 @@ float BotGraph::calculateTravelTime (float maxSpeed, const Vector &src, const Ve
}
bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
TraceResult tr;
TraceResult tr {};
float distance = (destination - src).length ();
@ -1751,7 +1750,7 @@ bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
// check if we go through a func_illusionary, in which case return false
game.testHull (src, destination, TraceIgnore::Monsters, head_hull, m_editor, &tr);
if (!game.isNullEntity (tr.pHit) && strcmp ("func_illusionary", tr.pHit->v.classname.chars ()) == 0) {
if (tr.pHit && strcmp ("func_illusionary", tr.pHit->v.classname.chars ()) == 0) {
return false; // don't add pathnodes through func_illusionaries
}
@ -1759,7 +1758,7 @@ bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
game.testLine (src, destination, TraceIgnore::Monsters, m_editor, &tr);
// if node is visible from current position (even behind head)...
if (tr.flFraction >= 1.0f || strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
if (tr.flFraction >= 1.0f || (tr.pHit && strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0)) {
// if it's a door check if nothing blocks behind
if (strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
game.testLine (tr.vecEndPos, destination, TraceIgnore::Monsters, tr.pHit, &tr);
@ -1827,7 +1826,7 @@ void BotGraph::rebuildVisibility () {
return;
}
TraceResult tr;
TraceResult tr {};
uint8 res, shift;
for (const auto &vis : m_paths) {
@ -2525,7 +2524,7 @@ void BotGraph::addBasic () {
Vector ladderRight = ent->v.absmax;
ladderLeft.z = ladderRight.z;
TraceResult tr;
TraceResult tr {};
Vector up, down, front, back;
const Vector &diff = ((ladderLeft - ladderRight) ^ Vector (0.0f, 0.0f, 0.0f)).normalize () * 15.0f;
@ -2650,7 +2649,7 @@ void BotGraph::setBombOrigin (bool reset, const Vector &pos) {
}
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
if (strcmp (ent->v.model.chars () + 9, "c4.mdl") == 0) {
if (strcmp (ent->v.model.chars (9), "c4.mdl") == 0) {
m_bombOrigin = game.getEntityWorldOrigin (ent);
return EntitySearchResult::Break;
}
@ -2674,7 +2673,7 @@ void BotGraph::setSearchIndex (int index) {
}
BotGraph::BotGraph () {
memset (m_highestDamage, 0, sizeof (m_highestDamage));
plat.bzero (m_highestDamage, sizeof (m_highestDamage));
m_endJumpPoint = false;
m_needsVisRebuild = false;

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -87,7 +86,7 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
// engine, and then calls the MOD DLL's version of GetEntityAPI to get the REAL gamedll
// functions this time (to use in the bot code).
memset (table, 0, sizeof (gamefuncs_t));
plat.bzero (table, sizeof (gamefuncs_t));
if (!(game.is (GameFlags::Metamod))) {
auto api_GetEntityAPI = game.lib ().resolve <int (*) (gamefuncs_t *, int)> ("GetEntityAPI");
@ -457,7 +456,7 @@ CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
// engine, and then calls the MOD DLL's version of GetEntityAPI to get the REAL gamedll
// functions this time (to use in the bot code). Post version, called only by metamod.
memset (table, 0, sizeof (gamefuncs_t));
plat.bzero (table, sizeof (gamefuncs_t));
table->pfnSpawn = [] (edict_t *ent) {
// this function asks the game DLL to spawn (i.e, give a physical existence in the virtual
@ -505,7 +504,7 @@ CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
if (game.is (GameFlags::Metamod)) {
memset (table, 0, sizeof (enginefuncs_t));
plat.bzero (table, sizeof (enginefuncs_t));
}
table->pfnChangeLevel = [] (char *s1, char *s2) {
@ -811,7 +810,7 @@ CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion)
}
CR_LINKAGE_C int GetEngineFunctions_Post (enginefuncs_t *table, int *) {
memset (table, 0, sizeof (enginefuncs_t));
plat.bzero (table, sizeof (enginefuncs_t));
table->pfnMessageEnd = [] () {
msgs.stop (); // this allows us to send messages right in handler code

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -273,7 +272,7 @@ void BotManager::frame () {
void BotManager::addbot (const String &name, int difficulty, int personality, int team, int member, bool manual) {
// this function putting bot creation process to queue to prevent engine crashes
CreateQueue create;
CreateQueue create {};
// fill the holder
create.name = name;
@ -290,7 +289,7 @@ void BotManager::addbot (const String &name, int difficulty, int personality, in
void BotManager::addbot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member, bool manual) {
// this function is same as the function above, but accept as parameters string instead of integers
CreateQueue create;
CreateQueue create {};
const String &any = "*";
create.name = (name.empty () || name == any) ? String ("\0") : name;
@ -358,10 +357,10 @@ void BotManager::maintainQuota () {
int desiredBotCount = yb_quota.int_ ();
int botsInGame = getBotCount ();
if (plat.caseStrMatch (yb_quota_mode.str (), "fill")) {
if (strings.matches (yb_quota_mode.str (), "fill")) {
botsInGame += humanPlayersInGame;
}
else if (plat.caseStrMatch (yb_quota_mode.str (), "match")) {
else if (strings.matches (yb_quota_mode.str (), "match")) {
int detectQuotaMatch = yb_quota_match.int_ () == 0 ? yb_quota.int_ () : yb_quota_match.int_ ();
desiredBotCount = cr::max <int> (0, detectQuotaMatch * humanPlayersInGame);
@ -427,26 +426,26 @@ void BotManager::reset () {
void BotManager::initFilters () {
// table with all available actions for the bots (filtered in & out in bot::setconditions) some of them have subactions included
m_filters.emplace (Task::Normal, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::Pause, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::MoveToPosition, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::FollowUser, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::PickupItem, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::Camp, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::PlantBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::DefuseBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Attack, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Hunt, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::SeekCover, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::ThrowExplosive, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::ThrowFlashbang, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::ThrowSmoke, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::DoubleJump, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::EscapeFromBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::ShootBreakable, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Hide, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Blind, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Spraypaint, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::normal_, Task::Normal, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (&Bot::pause_, Task::Pause, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::moveToPos_, Task::MoveToPosition, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (&Bot::followUser_, Task::FollowUser, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (&Bot::pickupItem_, Task::PickupItem, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (&Bot::camp_, Task::Camp, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (&Bot::plantBomb_, Task::PlantBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::defuseBomb_, Task::DefuseBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::attackEnemy_, Task::Attack, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::huntEnemy_, Task::Hunt, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::seekCover_, Task::SeekCover, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::throwExplosive_, Task::ThrowExplosive, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::throwFlashbang_, Task::ThrowFlashbang, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::throwSmoke_, Task::ThrowSmoke, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::doublejump_, Task::DoubleJump, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::escapeFromBomb_, Task::EscapeFromBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::shootBreakable_, Task::ShootBreakable, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::hide_, Task::Hide, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::blind_, Task::Blind, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (&Bot::spraypaint_, Task::Spraypaint, 0.0f, kInvalidNodeIndex, 0.0f, false);
}
void BotManager::resetFilters () {
@ -619,6 +618,26 @@ bool BotManager::kickRandom (bool decQuota, Team fromTeam) {
return false;
}
void BotManager::setLastWinner (int winner) {
m_lastWinner = winner;
if (yb_radio_mode.int_ () != 2) {
return;
}
auto notify = findAliveBot ();
if (notify) {
if (notify->m_team == winner) {
if (getRoundMidTime () > game.time ()) {
notify->pushChatterMessage (Chatter::QuickWonRound);
}
else {
notify->pushChatterMessage (Chatter::WonTheRound);
}
}
}
}
void BotManager::setWeaponMode (int selection) {
// this function sets bots weapon mode
@ -785,12 +804,13 @@ void BotManager::destroy () {
}
Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) {
// this function does core operation of creating bot, it's called by CreateBot (),
// this function does core operation of creating bot, it's called by addbot (),
// when bot setup completed, (this is a bot class constructor)
int clientIndex = game.indexOfEntity (bot);
// we're not initializing all the variables in bot class, so do an ugly thing... memset this
plat.bzero (this, sizeof (*this));
memset (reinterpret_cast <void *> (this), 0, sizeof (*this));
int clientIndex = game.indexOfEntity (bot);
pev = &bot->v;
if (bot->pvPrivateData != nullptr) {
@ -881,8 +901,8 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) {
break;
}
memset (&m_ammoInClip, 0, sizeof (m_ammoInClip));
memset (&m_ammo, 0, sizeof (m_ammo));
plat.bzero (&m_ammoInClip, sizeof (m_ammoInClip));
plat.bzero (&m_ammo, sizeof (m_ammo));
m_currentWeapon = 0; // current weapon is not assigned at start
m_voicePitch = rg.int_ (80, 115); // assign voice pitch
@ -975,10 +995,10 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
for (const auto &notify : bots) {
if (notify->m_notKilled && killerTeam == notify->m_team && killerTeam != victimTeam && killer != notify->ent () && notify->seesEntity (victim->v.origin)) {
if (!(killer->v.flags & FL_FAKECLIENT)) {
notify->handleChatter ("#Bot_NiceShotCommander");
notify->pushChatterMessage (Chatter::NiceShotCommander);
}
else {
notify->handleChatter ("#Bot_NiceShotPall");
notify->pushChatterMessage (Chatter::NiceShotPall);
}
break;
}
@ -1179,8 +1199,8 @@ void Bot::newRound () {
// if bot died, clear all weapon stuff and force buying again
if (!m_notKilled) {
memset (&m_ammoInClip, 0, sizeof (m_ammoInClip));
memset (&m_ammo, 0, sizeof (m_ammo));
plat.bzero (&m_ammoInClip, sizeof (m_ammoInClip));
plat.bzero (&m_ammo, sizeof (m_ammo));
m_currentWeapon = 0;
}
@ -1339,7 +1359,7 @@ void BotManager::captureChatRadio (const char *cmd, const char *arg, edict_t *en
return;
}
if (plat.caseStrMatch (cmd, "say") || plat.caseStrMatch (cmd, "say_team")) {
if (strings.matches (cmd, "say") || strings.matches (cmd, "say_team")) {
bool alive = util.isAlive (ent);
int team = -1;
@ -1414,7 +1434,7 @@ void BotManager::updateActiveGrenade () {
// search the map for any type of grenade
game.searchEntities ("classname", "grenade", [&] (edict_t *e) {
// do not count c4 as a grenade
if (strcmp (e->v.model.chars () + 9, "c4.mdl") == 0) {
if (strcmp (e->v.model.chars (9), "c4.mdl") == 0) {
return EntitySearchResult::Continue;
}
m_activeGrenades.push (e);
@ -1668,10 +1688,10 @@ void BotConfig::loadMainConfig () {
if (cvar != nullptr) {
auto value = const_cast <char *> (keyval[1].trim ().trim ("\"").trim ().chars ());
if (needsToIgnoreVar (ignore, key) && !plat.caseStrMatch (value, cvar->string)) {
if (needsToIgnoreVar (ignore, key) && !strings.matches (value, cvar->string)) {
// preserve quota number if it's zero
if (plat.caseStrMatch (cvar->name, "yb_quota") && yb_quota.int_ () <= 0) {
if (strings.matches (cvar->name, "yb_quota") && yb_quota.int_ () <= 0) {
engfuncs.pfnCvar_DirectSet (cvar, value);
continue;
}

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -17,18 +16,6 @@ void MessageDispatcher::netMsgTextMsg () {
return;
}
// bots chatter notification
const auto dispatchChatterMessage = [&] () -> void {
if (yb_radio_mode.int_ () == 2) {
auto notify = bots.findAliveBot ();
if (notify && notify->m_notKilled) {
notify->handleChatter (m_args[msg].chars_);
}
}
};
// lookup cached message
auto cached = m_textMsgCache[m_args[msg].chars_];
@ -50,8 +37,6 @@ void MessageDispatcher::netMsgTextMsg () {
}
else if (cached & TextMsgCache::CounterWin) {
bots.setLastWinner (Team::CT); // update last winner for economics
dispatchChatterMessage ();
resetBombPosition ();
}
else if (cached & TextMsgCache::RestartRound) {
@ -70,8 +55,6 @@ void MessageDispatcher::netMsgTextMsg () {
}
else if (cached & TextMsgCache::TerroristWin) {
bots.setLastWinner (Team::Terrorist); // update last winner for economics
dispatchChatterMessage ();
resetBombPosition ();
}
else if ((cached & TextMsgCache::BombPlanted) && !bots.isBombPlanted ()) {

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -19,7 +18,7 @@ int Bot::findBestGoal () {
int result = kInvalidNodeIndex;
game.searchEntities ("classname", "weaponbox", [&] (edict_t *ent) {
if (strcmp (ent->v.model.chars () + 9, "backpack.mdl") == 0) {
if (strcmp (ent->v.model.chars (9), "backpack.mdl") == 0) {
result = graph.getNearest (game.getEntityWorldOrigin (ent));
if (graph.exists (result)) {
@ -361,7 +360,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
m_isStuck = false;
// if avoiding someone do not consider stuck
TraceResult tr;
TraceResult tr {};
doPlayerAvoidance (dirNormal);
// Standing still, no need to check?
@ -702,7 +701,7 @@ bool Bot::updateNavigation () {
return false;
}
}
TraceResult tr;
TraceResult tr {};
// check if we are going through a door...
if (game.mapIs (MapFlags::HasDoors)) {
@ -849,7 +848,7 @@ bool Bot::updateLiftHandling () {
// update node time set
m_navTimeset = game.time ();
TraceResult tr;
TraceResult tr {};
// wait for something about for lift
auto wait = [&] () {
@ -867,7 +866,7 @@ bool Bot::updateLiftHandling () {
// trace line to door
game.testLine (pev->origin, m_path->origin, TraceIgnore::Everything, ent (), &tr);
if (tr.flFraction < 1.0f && strcmp (tr.pHit->v.classname.chars (), "func_door") == 0 && (m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor || m_liftState == LiftState::LookingButtonOutside) && pev->groundentity != tr.pHit) {
if (tr.flFraction < 1.0f && tr.pHit && strcmp (tr.pHit->v.classname.chars (), "func_door") == 0 && (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;
m_liftUsageTime = game.time () + 7.0f;
@ -1817,7 +1816,7 @@ int Bot::findDefendNode (const Vector &origin) {
if (m_currentNodeIndex == kInvalidNodeIndex) {
m_currentNodeIndex = changePointIndex (findNearestNode ());
}
TraceResult tr;
TraceResult tr {};
int nodeIndex[kMaxNodeLinks];
int minDistance[kMaxNodeLinks];
@ -2016,7 +2015,7 @@ int Bot::findCoverNode (float maxDistance) {
}
} while (sorting);
TraceResult tr;
TraceResult tr {};
// take the first one which isn't spotted by the enemy
for (const auto &index : nodeIndex) {
@ -2073,7 +2072,7 @@ bool Bot::advanceMovement () {
if (m_pathWalk.empty ()) {
return false;
}
TraceResult tr;
TraceResult tr {};
m_pathWalk.shift (); // advance in list
m_currentTravelFlags = 0; // reset travel flags (jumping etc)
@ -2392,7 +2391,7 @@ bool Bot::canStrafeRight (TraceResult *tr) {
bool Bot::canJumpUp (const Vector &normal) {
// this function check if bot can jump over some obstacle
TraceResult tr;
TraceResult tr {};
// can't jump if not on ground and not on ladder/swimming
if (!isOnFloor () && (isOnLadder () || !isInWater ())) {
@ -2472,7 +2471,7 @@ bool Bot::doneCanJumpUp (const Vector &normal, const Vector &right) {
Vector src = pev->origin + Vector (0.0f, 0.0f, -36.0f + 63.0f);
Vector dest = src + normal * 32.0f;
TraceResult tr;
TraceResult tr {};
// trace a line forward at maximum jump height...
game.testLine (src, dest, TraceIgnore::Monsters, ent (), &tr);
@ -2541,7 +2540,7 @@ bool Bot::doneCanJumpUp (const Vector &normal, const Vector &right) {
bool Bot::canDuckUnder (const Vector &normal) {
// this function check if bot can duck under obstacle
TraceResult tr;
TraceResult tr {};
Vector baseHeight;
// use center of the body first...
@ -2590,7 +2589,7 @@ bool Bot::canDuckUnder (const Vector &normal) {
}
bool Bot::isBlockedLeft () {
TraceResult tr;
TraceResult tr {};
float direction = 48.0f;
if (m_moveSpeed < 0.0f) {
@ -2603,14 +2602,14 @@ bool Bot::isBlockedLeft () {
game.testLine (pev->origin, forward * direction - right * 48.0f, TraceIgnore::Monsters, ent (), &tr);
// check if the trace hit something...
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && strncmp ("func_door", tr.pHit->v.classname.chars (), 9) != 0) {
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && tr.pHit && strncmp ("func_door", tr.pHit->v.classname.chars (), 9) != 0) {
return true; // bot's body will hit something
}
return false;
}
bool Bot::isBlockedRight () {
TraceResult tr;
TraceResult tr {};
float direction = 48.0f;
if (m_moveSpeed < 0.0f) {
@ -2623,14 +2622,14 @@ bool Bot::isBlockedRight () {
game.testLine (pev->origin, pev->origin + forward * direction + right * 48.0f, TraceIgnore::Monsters, ent (), &tr);
// check if the trace hit something...
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && (strncmp ("func_door", tr.pHit->v.classname.chars (), 9) != 0)) {
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && tr.pHit && strncmp ("func_door", tr.pHit->v.classname.chars (), 9) != 0) {
return true; // bot's body will hit something
}
return false;
}
bool Bot::checkWallOnLeft () {
TraceResult tr;
TraceResult tr {};
game.testLine (pev->origin, pev->origin - pev->angles.right () * 40.0f, TraceIgnore::Monsters, ent (), &tr);
// check if the trace hit something...
@ -2641,7 +2640,7 @@ bool Bot::checkWallOnLeft () {
}
bool Bot::checkWallOnRight () {
TraceResult tr;
TraceResult tr {};
// do a trace to the right...
game.testLine (pev->origin, pev->origin + pev->angles.right () * 40.0f, TraceIgnore::Monsters, ent (), &tr);
@ -2656,7 +2655,7 @@ bool Bot::checkWallOnRight () {
bool Bot::isDeadlyMove (const Vector &to) {
// this function eturns if given location would hurt Bot with falling damage
TraceResult tr;
TraceResult tr {};
const auto &direction = (to - pev->origin).normalize (); // 1 unit long
Vector check = to, down = to;
@ -2984,7 +2983,7 @@ int Bot::getNearestToPlantedBomb () {
// search the bomb on the map
game.searchEntities ("classname", "grenade", [&result] (edict_t *ent) {
if (strcmp (ent->v.model.chars () + 9, "c4.mdl") == 0) {
if (strcmp (ent->v.model.chars (9), "c4.mdl") == 0) {
result = graph.getNearest (game.getEntityWorldOrigin (ent));
if (graph.exists (result)) {
@ -3077,7 +3076,7 @@ bool Bot::isReachableNode (int index) {
}
float ladderDist = (dst - src).length2d ();
TraceResult tr;
TraceResult tr {};
game.testLine (src, dst, TraceIgnore::Monsters, ent (), &tr);
// if node is visible from current position (even behind head)...

View file

@ -1,9 +1,9 @@
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://yapb.ru/license
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
//
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
//
#include <yapb.h>
@ -115,7 +115,7 @@ bool BotUtils::isVisible (const Vector &origin, edict_t *ent) {
if (game.isNullEntity (ent)) {
return false;
}
TraceResult tr;
TraceResult tr {};
game.testLine (ent->v.origin + ent->v.view_ofs, origin, TraceIgnore::Everything, ent, &tr);
if (tr.flFraction != 1.0f) {